Ignore:
Timestamp:
Nov 13, 2011, 3:38:40 PM (12 years ago)
Author:
krille_n_@…
google:author:
krille_n_@hotmail.com
Message:

Changes to all parts of the project:

  • Size optimizations.
  • Added a define (EXCLUDE_FROM_XTIDECFG) to exclude unused library code from XTIDECFG.
  • Tried to minimize time spent with interrupts disabled.
  • Some minor attempts to improve speed (reordering instructions etc).
  • Tried to improve readability, did some cleanup and fixed some errors in comments.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialCommand.asm

    r179 r181  
    1010;    http://en.wikibooks.org/wiki/Serial_Programming
    1111;
    12        
     12
    1313SerialCommand_UART_base                         EQU     0
    1414SerialCommand_UART_transmitByte                 EQU     0
    1515SerialCommand_UART_receiveByte                  EQU     0
    1616SerialCommand_UART_divisorLow                   EQU     0
    17 ; Values for UART_divisorLow:   
     17; Values for UART_divisorLow:
    1818; 60h = 1200, 30h = 2400, 18h = 4800, 0ch = 9600, 6 = 19200, 3 = 38400, 2 = 57600, 1 = 115200
    1919
     
    2323; Note: hardware baud multipliers (2x, 4x) will impact the final baud rate and are not known at this level
    2424
    25 SerialCommand_UART_interruptEnable              EQU     1               
     25SerialCommand_UART_interruptEnable              EQU     1
    2626SerialCommand_UART_divisorHigh                  EQU     1
    2727; UART_divisorHigh is zero for all speeds including and above 1200 baud
     
    3131
    3232SerialCommand_UART_lineControl                  EQU     3
    33        
     33
    3434SerialCommand_UART_modemControl                 EQU     4
    3535
     
    4040SerialCommand_UART_scratch                      EQU     7
    4141
    42 SerialCommand_PackedPortAndBaud_StartingPort    EQU     240h   
     42SerialCommand_PackedPortAndBaud_StartingPort    EQU     240h
    4343SerialCommand_PackedPortAndBaud_PortMask        EQU     0fch    ; upper 6 bits - 240h through 438h
    4444SerialCommand_PackedPortAndBaud_BaudMask        EQU     3       ; lower 2 bits - 4 baud rates
     
    4848SerialCommand_Protocol_Inquire                  EQU     0
    4949SerialCommand_Protocol_Header                   EQU     0a0h
    50        
     50
    5151;--------------------------------------------------------------------
    5252; SerialCommand_OutputWithParameters
     
    6565;       AL, BX, CX, DX, (ES:SI for data transfer commands)
    6666;--------------------------------------------------------------------
    67 
    6867ALIGN JUMP_ALIGN
    6968SerialCommand_OutputWithParameters:
    70        
     69
    7170        mov     ah,(SerialCommand_Protocol_Header | SerialCommand_Protocol_Read)
    72        
     71
    7372        mov     al,[bp+IDEPACK.bCommand]
    7473
     
    7877        cmp     al,30h          ; Write Sectors IDE command
    7978        jz      .readOrWrite
    80        
     79
    8180;  all other commands return success
    8281;  including function 0ech which should return drive information, this is handled with the identify functions
    8382        xor     ah,ah           ;  also clears carry
    8483        ret
    85        
    86 .readOrWrite:   
     84
     85.readOrWrite:
    8786        mov     [bp+IDEPACK.bFeatures],ah       ; store protocol command
    88        
    89         mov     dl, byte [ds:di+DPT.bSerialPortAndBaud]
    90        
     87
     88        mov     dl, byte [di+DPT.bSerialPortAndBaud]
     89
    9190; fall-through
    9291
     
    9493; SerialCommand_OutputWithParameters_DeviceInDL
    9594;   Parameters:
    96 ;       AH:     Protocol Command 
     95;       AH:     Protocol Command
    9796;       DL:     Packed I/O port and baud rate
    9897;       ES:SI:  Ptr to buffer (for data transfer commands)
     
    103102;   Corrupts registers:
    104103;       AL, BX, CX, DX, (ES:SI for data transfer commands)
    105 ;--------------------------------------------------------------------       
     104;--------------------------------------------------------------------
    106105SerialCommand_OutputWithParameters_DeviceInDL:
    107        
     106
    108107        push    si
    109108        push    di
     
    111110        push    es
    112111
    113 ; 
     112;
    114113; Unpack I/O port and baud from DPT
    115114;       Port to DX more or less for the remainder of the routine
     
    117116;
    118117        mov     cl, dl
    119        
     118
    120119        and     cl, SerialCommand_PackedPortAndBaud_BaudMask
    121120        shl     cl, 1
     
    125124
    126125        and     dl, SerialCommand_PackedPortAndBaud_PortMask
    127         mov     dh, 0       
     126        mov     dh, 0
    128127        shl     dx, 1
    129128        add     dx, SerialCommand_PackedPortAndBaud_StartingPort
     
    131130;
    132131; Buffer is referenced through ES:DI throughout, since we need to store faster than we read
    133 ; 
     132;
    134133        mov     di,si
    135134
     
    138137;
    139138; Command byte and sector count live at the top of the stack, pop/push are used to access
    140 ; 
     139;
    141140        push    ax
    142        
    143         cld
     141
     142;       cld     ; Shouldn't be needed. DF has already been cleared (line 24, Int13h.asm)
    144143
    145144;----------------------------------------------------------------------
     
    147146; Initialize UART
    148147;
    149 ; We do this each time since DOS (at boot) or another program may have 
     148; We do this each time since DOS (at boot) or another program may have
    150149; decided to reprogram the UART
    151150;
    152151        push    dx
    153        
     152
    154153        mov     al,83h
    155154        add     dl,SerialCommand_UART_lineControl
     
    167166        mov     al,047h
    168167        inc     dx              ;  fifo
    169         out     dx,al       
     168        out     dx,al
    170169
    171170        mov     al,03h
     
    192191        push    es              ; save off real buffer location
    193192        push    di
    194        
    195         mov     di,bp           ; point to IDEREGS for command dispatch;       
     193
     194        mov     di,bp           ; point to IDEREGS for command dispatch;
    196195        push    ss
    197196        pop     es
    198197
    199198        xor     si,si           ; initialize checksum for write
    200         dec     si     
     199        dec     si
    201200        mov     bp,si
    202201
    203202        mov     bl,03h      ; writing 3 words
    204        
     203
    205204        call    SerialCommand_WriteProtocol
    206205
     
    213212;
    214213; Top of the read/write loop, one iteration per sector
    215 ; 
     214;
    216215.nextSector:
    217216        xor     si,si           ; initialize checksum for read or write
     
    220219
    221220        mov     bx,0100h
    222        
     221
    223222        shr     ah,1            ; command byte, are we doing a write?
    224223        jnc     .readSector
    225224        call    SerialCommand_WriteProtocol
    226        
     225
    227226        xor     bx,bx
    228227
     
    230229        mov     cx,bx
    231230        inc     cx
    232        
     231
    233232        mov     bl,dl           ; setup bl with proper values for read loop (bh comes later)
    234233
     
    246245        push    cx
    247246        xor     cx,cx
    248 .readTimeoutLoop:   
     247.readTimeoutLoop:
    249248        push    dx
    250249        or      dl,SerialCommand_UART_lineStatus
     
    257256        mov     bh,1
    258257        call    SerialCommand_WaitAndPoll_Init
    259         cli     
     258        cli
    260259.readTimeoutComplete:
    261260        mov     bh,bl
    262261        or      bh,SerialCommand_UART_lineStatus
    263        
     262
    264263        pop     cx
    265264        test    dl,1
     
    271270; Read Block (without interrupts, used when there is a FIFO, high speed)
    272271;
    273 ; NOTE: This loop is very time sensitive.  Literally, another instruction 
     272; NOTE: This loop is very time sensitive.  Literally, another instruction
    274273; cannot be inserted into this loop without us falling behind at high
    275 ; speed (460.8K baud) on a 4.77Mhz 8088, making it hard to receive 
     274; speed (460.8K baud) on a 4.77Mhz 8088, making it hard to receive
    276275; a full 512 byte block.
    277276;
    278 .readLoop:     
     277.readLoop:
     278        stosw                   ; store word in caller's data buffer
     279
    279280        add     bp, ax          ; update Fletcher's checksum
    280281        adc     bp, 0
     
    282283        adc     si, 0
    283284
    284         stosw                   ; store word in caller's data buffer
    285 
    286         mov     dl,bh           
    287         in      al,dx           
     285        mov     dl,bh
     286        in      al,dx
    288287        shr     al,1            ; data ready (byte 1)?
    289         mov     dl,bl           ; get ready to read data           
     288        mov     dl,bl           ; get ready to read data
    290289        jnc     .readTimeout    ; nope not ready, update timeouts
    291        
    292 ; 
     290
     291;
    293292; Entry point after initial timeout.  We enter here so that the checksum word
    294293; is not stored (and is left in AX after the loop is complete).
    295 ; 
    296 .readByte1Ready:       
     294;
     295.readByte1Ready:
    297296        in      al, dx          ; read data byte 1
    298297
    299298        mov     ah, al          ; store byte in ah for now
    300        
    301 ;
    302 ; note the placement of this reset of dl to bh, and that it is 
    303 ; before the return, which is assymetric with where this is done 
    304 ; above for byte 1.  The value of dl is used by the timeout routine 
    305 ; to know which byte to return to (.read_byte1_ready or 
     299
     300;
     301; note the placement of this reset of dl to bh, and that it is
     302; before the return, which is assymetric with where this is done
     303; above for byte 1.  The value of dl is used by the timeout routine
     304; to know which byte to return to (.read_byte1_ready or
    306305; .read_byte2_ready)
    307306;
    308         mov     dl,bh           
    309                                
     307        mov     dl,bh
     308
    310309        in      al,dx
    311310        shr     al,1            ; data ready (byte 2)?
    312311        jnc     .readTimeout
    313 .readByte2Ready:                       
    314         mov     dl,bl       
     312.readByte2Ready:
     313        mov     dl,bl
    315314        in      al, dx          ; read data byte 2
    316315
    317316        xchg    al, ah          ; ah was holding byte 1, reverse byte order
    318        
     317
    319318        loop    .readLoop
    320319
     320        sti                     ; interrupts back on ASAP, if we turned them off
     321
    321322;
    322323; Compare checksums
    323 ; 
     324;
    324325        xor     bp,si
    325326        cmp     ax,bp
    326327        jnz     SerialCommand_OutputWithParameters_Error
    327328
    328         sti                 ; interrupts back on ASAP, if we turned them off
    329        
     329
    330330;----------------------------------------------------------------------
    331 ; 
     331;
    332332; Clear read buffer
    333333;
    334334; In case there are extra characters or an error in the FIFO, clear it out.
    335 ; In theory the initialization of the UART registers above should have 
     335; In theory the initialization of the UART registers above should have
    336336; taken care of this, but I have seen cases where this is not true.
    337337;
    338338.clearBuffer:
    339         mov     dl,bh       
     339        mov     dl,bh
    340340        in      al,dx
    341         mov     dl,bl               
     341        mov     dl,bl
    342342        test    al,08fh
    343343        jz      .clearBufferComplete
    344344        shr     al,1
    345         in      al,dx       
     345        in      al,dx
    346346        jc      .clearBuffer    ; note CF from shr above
    347347        jmp     SerialCommand_OutputWithParameters_Error
    348        
    349 .clearBufferComplete:   
     348
     349.clearBufferComplete:
    350350        pop     ax              ; sector count and command byte
    351351        dec     al              ; decrememnt sector count
    352352        push    ax              ; save
    353353        jz      SerialCommand_OutputWithParameters_ReturnCodeInALCF    ; CF clear from .clearBuffer test above
    354                
     354
    355355        cli                     ; interrupts back off for ACK byte to host
    356356                                ; (host could start sending data immediately)
    357357        out     dx,al           ; ACK with next sector number
    358        
     358
    359359        jmp     .nextSector     ; all is well, time for next sector
    360360
     
    363363; Cleanup, error reporting, and exit
    364364;
    365        
    366 ; 
     365
     366;
    367367; Used in situations where a call is underway, such as with SerialCommand_WaitAndPoll
    368 ; 
     368;
    369369SerialCommand_OutputWithParameters_ErrorAndPop2Words:
    370370        pop     ax
    371371        pop     ax
    372372
    373 SerialCommand_OutputWithParameters_Error:       
     373SerialCommand_OutputWithParameters_Error:
     374        stc
    374375        mov     al,1
    375         stc
    376 
    377 SerialCommand_OutputWithParameters_ReturnCodeInALCF:   
     376
     377SerialCommand_OutputWithParameters_ReturnCodeInALCF:
     378        sti
    378379        mov     ah,al
    379         sti
    380380
    381381        pop     bp              ;  recover ax from stack, throw away
     
    398398;       Returns when desired UART_LineStatus bit is cleared
    399399;       Jumps directly to error exit if timeout elapses (and cleans up stack)
    400 ;   Corrupts registers: 
     400;   Corrupts registers:
    401401;       CX, flags
    402402;--------------------------------------------------------------------
     
    404404SerialCommand_WaitAndPoll_SoftDelayTicks   EQU   20
    405405
    406 ALIGN JUMP_ALIGN               
     406ALIGN JUMP_ALIGN
    407407SerialCommand_WaitAndPoll_Init:
    408408        mov     cl,SerialCommand_WaitAndPoll_SoftDelayTicks
    409409        call    Timer_InitializeTimeoutWithTicksInCL
    410410; fall-through
    411        
     411
    412412SerialCommand_WaitAndPoll:
    413413        call    Timer_SetCFifTimeout
     
    422422        jz      SerialCommand_WaitAndPoll
    423423; fall-through
    424        
    425 SerialCommand_WaitAndPoll_Done: 
     424
     425SerialCommand_WaitAndPoll_Done:
    426426        ret
    427427
     
    442442SerialCommand_WriteProtocol:
    443443        mov     bh,20h
    444        
     444
    445445.writeLoop:
    446446        test    bh,1
    447447        jnz     SerialCommand_WaitAndPoll_Done
    448        
     448
    449449        mov     ax,[es:di]      ; fetch next word
    450450        inc     di
    451451        inc     di
    452        
     452
    453453        add     bp,ax           ; update checksum
    454454        adc     bp,0
     
    458458.writeLoopChecksum:
    459459        call    SerialCommand_WaitAndPoll_Init
    460        
     460
    461461        out     dx,al           ; output first byte
    462462
    463463        call    SerialCommand_WaitAndPoll
    464        
     464
    465465        mov     al,ah           ; output second byte
    466466        out     dx,al
     
    468468        dec     bl
    469469        jnz     .writeLoop
    470        
     470
    471471        inc     bh
    472        
     472
    473473        mov     ax,bp           ; merge checksum for possible write (last loop)
    474         xor     ax,si       
    475        
     474        xor     ax,si
     475
    476476        jmp     .writeLoopChecksum
    477477
     
    501501        mov     dx,[cs:bp+IDEVARS.wPortCtrl]
    502502        inc     dx
    503         dec     dx     
     503        dec     dx
    504504        jz      SerialCommand_AutoSerial
    505505
    506506; fall-through
    507 SerialCommand_IdentifyDeviceInDL_DriveInBH:     
     507SerialCommand_IdentifyDeviceInDL_DriveInBH:
    508508
    509509        push    bp              ; setup fake IDEREGS_AND_INTPACK
     
    516516        mov     bl,0a0h         ; protocol command to ah and onto stack with bh
    517517        mov     ah,bl
    518        
     518
    519519        push    bx
    520520
     
    524524
    525525        pop     bx
    526        
    527         pop     cx             
     526
     527        pop     cx
    528528        pop     dx
    529529
    530530        pop     bp
    531531
    532 ; place packed port/baud in vendor area of packet, read by FinalizeDPT 
    533         mov     byte [es:si+SerialCommand_IdentifyDevice_PackedPortAndBaud], dl 
     532; place packed port/baud in vendor area of packet, read by FinalizeDPT
     533        mov     byte [es:si+SerialCommand_IdentifyDevice_PackedPortAndBaud], dl
    534534
    535535        ret
     
    540540;
    541541; When the SerialAuto IDEVARS entry is used, scans the COM ports on the machine for a possible serial connection.
    542 ; 
    543        
     542;
     543
    544544SerialCommand_ScanPortAddresses:  db  0b8h, 0f8h, 0bch, 0bah, 0fah, 0beh, 0feh, 0
    545545; Corresponds to I/O port:             3f8,  2f8,  3e8,  2e8,  2f0,  3e0,  2e0,  260,  368,  268,  360,  270
    546546; COM Assignments:                       1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12
    547547
    548 ALIGN JUMP_ALIGN                       
    549 SerialCommand_AutoSerial:       
     548ALIGN JUMP_ALIGN
     549SerialCommand_AutoSerial:
    550550        mov     di,SerialCommand_ScanPortAddresses-1
    551        
     551
    552552.nextPort:
    553553        inc     di              ; load next port address
    554554        mov     dl,[cs:di]
    555        
     555
    556556        mov     dh,0            ; shift from one byte to two
    557         shl     dx,1
    558         shl     dx,1       
     557        eSHL_IM dx, 2
    559558        jz      .exitNotFound
    560559
    561560;
    562561; Test for COM port presence, write to and read from registers
    563 ; 
    564         push    dx     
     562;
     563        push    dx
    565564        add     dl,SerialCommand_UART_lineControl
    566565        mov     al, 09ah
     
    569568        pop     dx
    570569        cmp     al, 09ah
    571         jnz     .nextPort       
     570        jnz     .nextPort
    572571
    573572        mov     al, 0ch
     
    579578;
    580579; Pack into dl, baud rate starts at 0
    581 ; 
     580;
    582581        add     dx,-(SerialCommand_PackedPortAndBaud_StartingPort)
    583582        shr     dx,1
    584        
     583
    585584        jmp     .testFirstBaud
    586585
    587586;
    588587; Walk through 4 possible baud rates
    589 ; 
    590 .nextBaud:     
     588;
     589.nextBaud:
    591590        inc     dx
    592591        test    dl,3
    593592        jz      .nextPort
    594        
    595 .testFirstBaud:     
     593
     594.testFirstBaud:
    596595        call    SerialCommand_IdentifyDeviceInDL_DriveInBH
    597596        jc      .nextBaud
    598597
    599598        ret
    600                
     599
    601600.exitNotFound:
     601        stc
    602602        mov     ah,1
    603         stc
    604603
    605604        ret
Note: See TracChangeset for help on using the changeset viewer.