Ignore:
Timestamp:
Feb 28, 2012, 2:45:48 PM (12 years ago)
Author:
gregli@…
google:author:
gregli@hotmail.com
Message:

Moved the bulk of the serial code to the assembly library, for inclusion in other utilities. Fixed a bug in int13h.asm when floppy support was not enabled that was preventing foreign drives from working properly.

File:
1 edited

Legend:

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

    r262 r277  
    44; Section containing code
    55SECTION .text
    6 
    7 ;--------------- UART Equates -----------------------------
    8 ;
    9 ; Serial Programming References:
    10 ;    http://en.wikibooks.org/wiki/Serial_Programming
    11 ;
    12 
    13 SerialCommand_UART_base                         EQU     0
    14 SerialCommand_UART_transmitByte                 EQU     0
    15 SerialCommand_UART_receiveByte                  EQU     0
    16 
    17 ;
    18 ; Values for UART_divisorLow:
    19 ; 60h = 1200, 30h = 2400, 18h = 4800, 0ch = 9600, 6 = 19200, 4 = 28800, 3 = 38400, 2 = 57600, 1 = 115200
    20 ;
    21 SerialCommand_UART_divisorLow                   EQU     0
    22 
    23 ;
    24 ; UART_divisorHigh is zero for all speeds including and above 1200 baud (which is all we do)
    25 ;
    26 SerialCommand_UART_divisorHigh                  EQU     1
    27 
    28 SerialCommand_UART_interruptIdent               EQU     2
    29 SerialCommand_UART_FIFOControl                  EQU     2
    30 
    31 SerialCommand_UART_lineControl                  EQU     3
    32 
    33 SerialCommand_UART_modemControl                 EQU     4
    34 
    35 SerialCommand_UART_lineStatus                   EQU     5
    36 
    37 SerialCommand_UART_modemStatus                  EQU     6
    38 
    39 SerialCommand_UART_scratch                      EQU     7
    40 
    41 SerialCommand_Protocol_Write                    EQU     3
    42 SerialCommand_Protocol_Read                     EQU     2
    43 SerialCommand_Protocol_Inquire                  EQU     0
    44 SerialCommand_Protocol_Header                   EQU     0a0h
    456
    467;--------------------------------------------------------------------
     
    6425SerialCommand_OutputWithParameters:
    6526
    66         mov     ah,(SerialCommand_Protocol_Header | SerialCommand_Protocol_Read)
     27        mov     ah,SerialServer_Command_Read
    6728
    6829        mov     al,[bp+IDEPACK.bCommand]
     
    7031        cmp     al,20h          ; Read Sectors IDE command
    7132        jz      .readOrWrite
    72         inc     ah              ; now SerialCommand_Protocol_Write
     33        inc     ah              ; now SerialServer_Protocol_Write
    7334        cmp     al,30h          ; Write Sectors IDE command
    7435        jz      .readOrWrite
     
    8546        mov     dx, [di+DPT_SERIAL.wSerialPortAndBaud]
    8647
    87 ; fall-through
     48        jmp     SerialServer_SendReceive
    8849
    89 ;--------------------------------------------------------------------
    90 ; SerialCommand_OutputWithParameters_DeviceInDX
    91 ;   Parameters:
    92 ;       AH:     Protocol Command
    93 ;       DX:     Packed I/O port and baud rate
    94 ;       ES:SI:  Ptr to buffer (for data transfer commands)
    95 ;       SS:BP:  Ptr to IDEREGS_AND_INTPACK
    96 ;   Returns:
    97 ;       AH:     INT 13h Error Code
    98 ;       CF:     Cleared if success, Set if error
    99 ;   Corrupts registers:
    100 ;       AL, BX, CX, DX, (ES:SI for data transfer commands)
    101 ;--------------------------------------------------------------------
    102 SerialCommand_OutputWithParameters_DeviceInDX:
    103 
    104         push    si
    105         push    di
    106         push    bp
    107 
    108 ;
    109 ; Unpack I/O port and baud from DPT
    110 ;       Port to DX for the remainder of the routine (+/- different register offsets)
    111 ;       Baud in CH until UART initialization is complete
    112 ;
    113         mov     ch,dh
    114         xor     dh,dh
    115         eSHL_IM dx, 2           ; shift from one byte to two
    116 
    117         mov     al,[bp+IDEPACK.bSectorCount]
    118 
    119 ;
    120 ; Command byte and sector count live at the top of the stack, pop/push are used to access
    121 ;
    122         push    ax
    123 
    124 %if 0
    125         cld     ; Shouldn't be needed. DF has already been cleared (line 24, Int13h.asm)
    126 %endif
    127 
    128 ;----------------------------------------------------------------------
    129 ;
    130 ; Initialize UART
    131 ;
    132 ; We do this each time since DOS (at boot) or another program may have
    133 ; decided to reprogram the UART
    134 ;
    135         mov     bl,dl           ; setup BL with proper values for read/write loops (BH comes later)
    136 
    137         mov     al,83h
    138         add     dl,SerialCommand_UART_lineControl
    139         out     dx,al
    140 
    141         mov     al,ch
    142         mov     dl,bl           ; divisor low
    143         out     dx,al
    144 
    145         xor     ax,ax
    146         inc     dx              ; divisor high
    147         push    dx
    148         out     dx,al
    149 
    150         mov     al,047h
    151         inc     dx              ;  fifo
    152         out     dx,al
    153 
    154         mov     al,03h
    155         inc     dx              ;  linecontrol
    156         out     dx,al
    157 
    158         mov     al,0bh
    159         inc     dx              ;  modemcontrol
    160         out     dx,al
    161 
    162         inc     dx              ;  linestatus (no output now, just setting up BH for later use)
    163         mov     bh,dl
    164 
    165         pop     dx              ; base, interrupts disabled
    166         xor     ax,ax
    167         out     dx,al
    168 
    169 ;----------------------------------------------------------------------
    170 ;
    171 ; Send Command
    172 ;
    173 ; Sends first six bytes of IDEREGS_AND_INTPACK as the command
    174 ;
    175         push    es              ; save off real buffer location
    176         push    si
    177 
    178         mov     si,bp           ; point to IDEREGS for command dispatch;
    179         push    ss
    180         pop     es
    181 
    182         mov     di,0ffffh       ; initialize checksum for write
    183         mov     bp,di
    184 
    185         mov     cx,4            ; writing 3 words (plus 1)
    186 
    187         cli                     ; interrupts off...
    188 
    189         call    SerialCommand_WriteProtocol.entry
    190 
    191         pop     di              ; restore real buffer location (note change from SI to DI)
    192                                 ; Buffer is primarily referenced through ES:DI throughout, since
    193                                 ; we need to store (read sector) faster than we read (write sector)
    194         pop     es
    195 
    196 %if 0
    197 ;;; no longer needed, since the pointer is normalized before we are called and we do not support
    198 ;;; more than 128 sectors (and for 128 specifically, the pointer must be segment aligned).
    199 ;;; See comments below at the point this entry point was called for more details...
    200 .nextSectorNormalize:
    201         call    Registers_NormalizeESDI
    202 %endif
    203 
    204         pop     ax              ; load command byte (done before call to .nextSector on subsequent iterations)
    205         push    ax
    206 
    207 ;
    208 ; Top of the read/write loop, one iteration per sector
    209 ;
    210 .nextSector:
    211         mov     si,0ffffh       ; initialize checksum for read or write
    212         mov     bp,si
    213 
    214         mov     cx,0101h        ; writing 256 words (plus 1)
    215 
    216         shr     ah,1            ; command byte, are we doing a write?
    217         jnc     .readEntry
    218 
    219         xchg    si,di
    220         call    SerialCommand_WriteProtocol.entry
    221         xchg    si,di
    222 
    223         inc     cx              ; CX = 1 now (0 out of WriteProtocol)
    224         jmp     .readEntry
    225 
    226 ;----------------------------------------------------------------------
    227 ;
    228 ; Timeout
    229 ;
    230 ; To save code space, we use the contents of DL to decide which byte in the word to return for reading.
    231 ;
    232 .readTimeout:
    233         push    ax              ; not only does this push preserve AX (which we need), but it also
    234                                 ; means the stack has the same number of bytes on it as when we are
    235                                 ; sending a packet, important for error cleanup and exit
    236         mov     ah,1
    237         call    SerialCommand_WaitAndPoll_Read
    238         pop     ax
    239         test    dl,1
    240         jz      .readByte1Ready
    241         jmp     .readByte2Ready
    242 
    243 ;----------------------------------------------------------------------------
    244 ;
    245 ; Read Block (without interrupts, used when there is a FIFO, high speed)
    246 ;
    247 ; NOTE: This loop is very time sensitive.  Literally, another instruction
    248 ; cannot be inserted into this loop without us falling behind at high
    249 ; speed (460.8K baud) on a 4.77Mhz 8088, making it hard to receive
    250 ; a full 512 byte block.
    251 ;
    252 .readLoop:
    253         stosw                   ; store word in caller's data buffer
    254 
    255         add     bp, ax          ; update Fletcher's checksum
    256         adc     bp, 0
    257         add     si, bp
    258         adc     si, 0
    259 
    260 .readEntry:
    261         mov     dl,bh
    262         in      al,dx
    263         shr     al,1            ; data ready (byte 1)?
    264         mov     dl,bl           ; get ready to read data
    265         jnc     .readTimeout    ; nope not ready, update timeouts
    266 
    267 ;
    268 ; Entry point after initial timeout.  We enter here so that the checksum word
    269 ; is not stored (and is left in AX after the loop is complete).
    270 ;
    271 .readByte1Ready:
    272         in      al, dx          ; read data byte 1
    273 
    274         mov     ah, al          ; store byte in ah for now
    275 
    276 ;
    277 ; note the placement of this reset of dl to bh, and that it is
    278 ; before the return, which is assymetric with where this is done
    279 ; above for byte 1.  The value of dl is used by the timeout routine
    280 ; to know which byte to return to (.read_byte1_ready or
    281 ; .read_byte2_ready)
    282 ;
    283         mov     dl,bh
    284 
    285         in      al,dx
    286         shr     al,1            ; data ready (byte 2)?
    287         jnc     .readTimeout
    288 .readByte2Ready:
    289         mov     dl,bl
    290         in      al, dx          ; read data byte 2
    291 
    292         xchg    al, ah          ; ah was holding byte 1, reverse byte order
    293 
    294         loop    .readLoop
    295 
    296         sti                     ; interrupts back on ASAP, between packets
    297 
    298 ;
    299 ; Compare checksums
    300 ;
    301         xchg    ax,bp
    302         xor     ah,al
    303         mov     cx,si
    304         xor     cl,ch
    305         mov     al,cl
    306         cmp     ax,bp
    307         jnz     SerialCommand_OutputWithParameters_Error
    308 
    309         pop     ax              ; sector count and command byte
    310         dec     al              ; decrement sector count
    311         push    ax              ; save
    312         jz      SerialCommand_OutputWithParameters_ReturnCodeInAL
    313 
    314         cli                     ; interrupts back off for ACK byte to host
    315                                 ; (host could start sending data immediately)
    316         out     dx,al           ; ACK with next sector number
    317 
    318 %if 0
    319 ;;; This code is no longer needed as we do not support more than 128 sectors, and for 128 the pointer
    320 ;;; must be segment aligned.  If we ever do want to support more sectors, the code can help...
    321 
    322 ;
    323 ; Normalize buffer pointer for next go round, if needed.
    324 ;
    325 ; We need to re-normalize the pointer in ES:DI after processing every 7f sectors.  That number could
    326 ; have been 80 if we knew the offset was on a segment boundary, but this may not be the case.
    327 ;
    328 ; We re-normalize based on the sector count (flags from "dec al" above)...
    329 ;    a) we normalize before the first sector goes out, immediately after sending the command packet (above)
    330 ;    b) on transitions from FF to FE, very rare case for writing 255 or 256 sectors
    331 ;    c) on transitions from 80 to 7F, a large read/write
    332 ;    d) on transitions from 00 to FF, very, very rare case of writing 256 sectors
    333 ;       We don't need to renormalize in this case, but it isn't worth the memory/effort to not do
    334 ;       the extra work, and it does no harm.
    335 ;
    336 ; I really don't care much about (d) because I have not seen cases where any OS makes a request
    337 ; for more than 127 sectors.  Back in the day, it appears that some BIOS could not support more than 127
    338 ; sectors, so that may be the practical limit for OS and application developers.  The Extended BIOS
    339 ; function also appear to be capped at 127 sectors.  So although this can support the full 256 sectors
    340 ; if needed, we are optimized for that 1-127 range.
    341 ;
    342 ; Assume we start with 0000:000f, with 256 sectors to write...
    343 ;    After first packet, 0000:020f
    344 ;    First decrement of AL, transition from 00 to FF: renormalize to 0020:000f (unnecessary)
    345 ;    After second packet, 0020:020f
    346 ;    Second derement of AL, transition from FF to FE: renormalize to 0040:000f
    347 ;    After 7f more packets, 0040:fe0f
    348 ;    Decrement of AL, transition from 80 to 7F: renormalize to 1020:000f
    349 ;    After 7f more packets, 1020:fe0f or 2000:000f if normalized
    350 ;    Decrement of AL, from 1 to 0: exit
    351 ;
    352         jge     short .nextSector       ; OF=SF, branch for 1-7e, most common case
    353                                         ; (0 kicked out above for return success)
    354 
    355         add     al,2                    ; 7f-ff moves to 81-01
    356                                         ; (0-7e kicked out before we get here)
    357                                         ; 7f moves to 81 and OF=1, so OF=SF
    358                                         ; fe moves to 0 and OF=0, SF=0, so OF=SF
    359                                         ; ff moves to 1 and OF=0, SF=0, so OF=SF
    360                                         ; 80-fd moves to 82-ff and OF=0, so OF<>SF
    361 
    362         jl      short .nextSector       ; OF<>SF, branch for all cases but 7f, fe, and ff
    363 
    364 ;       jpo     short .nextSector       ; if we really wanted to avoid normalizing for ff, this
    365                                         ; is one way to do it, but it adds more memory and more
    366                                         ; cycles for the 7f and fe cases.  IMHO, given that I've
    367                                         ; never seen a request for more than 7f, this seems unnecessary.
    368 
    369         jmp     short .nextSectorNormalize  ; our two renormalization cases (plus one for ff)
    370 
    371 %else
    372 
    373         jmp     short .nextSector
    374 
    375 %endif
    376 
    377 ;---------------------------------------------------------------------------
    378 ;
    379 ; Cleanup, error reporting, and exit
    380 ;
    381 
    382 ;
    383 ; Used in situations where a call is underway, such as with SerialCommand_WaitAndPoll
    384 ;
    385 ALIGN JUMP_ALIGN
    386 SerialCommand_OutputWithParameters_ErrorAndPop4Words:
    387         add     sp,8
    388 ;;; fall-through
    389 
    390 ALIGN JUMP_ALIGN
    391 SerialCommand_OutputWithParameters_Error:
    392 ;----------------------------------------------------------------------
    393 ;
    394 ; Clear read buffer
    395 ;
    396 ; In case there are extra characters or an error in the FIFO, clear it out.
    397 ; In theory the initialization of the UART registers above should have
    398 ; taken care of this, but I have seen cases where this is not true.
    399 ;
    400         xor     cx,cx                   ; timeout this clearing routine, in case the UART isn't there
    401 .clearBuffer:
    402         mov     dl,bh
    403         in      al,dx
    404         mov     dl,bl
    405         test    al,08fh
    406         jz      .clearBufferComplete
    407         test    al,1
    408         in      al,dx
    409         loopnz  .clearBuffer            ; note ZF from test above
    410 
    411 .clearBufferComplete:
    412         mov     al, 3           ;  error return code and CF (low order bit)
    413 
    414 ALIGN JUMP_ALIGN
    415 SerialCommand_OutputWithParameters_ReturnCodeInAL:
    416 %if 0
    417         sti                     ;  all paths here will already have interrupts turned back on
    418 %endif
    419         mov     ah, al          ;  for success, AL will already be zero
    420 
    421         pop     bx              ;  recover "ax" (command and count) from stack
    422 
    423         pop     bp
    424         pop     di
    425         pop     si
    426 
    427         mov     ch, 0
    428         mov     cl,[bp+IDEPACK.bSectorCount]
    429         sub     cl, bl          ; subtract off the number of sectors that remained
    430        
    431         shr     ah, 1           ; shift down return code and CF
    432 
    433         ret
    434 
    435 ;--------------------------------------------------------------------
    436 ; SerialCommand_WriteProtocol
    437 ;
    438 ; NOTE: As with its read counterpart, this loop is very time sensitive.
    439 ; Although it will still function, adding additional instructions will
    440 ; impact the write throughput, especially on slower machines.
    441 ;
    442 ;   Parameters:
    443 ;       ES:SI:  Ptr to buffer
    444 ;       CX:     Words to write, plus 1
    445 ;       BP/DI:  Initialized for Checksum (-1 in each)
    446 ;       DH:     I/O Port high byte
    447 ;       BX:     LineStatus Register address (BH) and Receive/Transmit Register address (BL)
    448 ;   Returns:
    449 ;       BP/DI:  Checksum for written bytes, compared against ACK from server in .readLoop
    450 ;       CX:     Zero
    451 ;       DL:     Receive/Transmit Register address
    452 ;   Corrupts registers:
    453 ;       AX
    454 ;--------------------------------------------------------------------
    455 ALIGN JUMP_ALIGN
    456 SerialCommand_WriteProtocol:
    457 .writeLoop:
    458         es lodsw                ; fetch next word
    459 
    460         out     dx,al           ; output first byte
    461 
    462         add     bp,ax           ; update checksum
    463         adc     bp,0
    464         add     di,bp
    465         adc     di,0
    466 
    467         mov     dl,bh           ; transmit buffer empty?
    468         in      al,dx
    469         test    al,20h
    470         jz      .writeTimeout2  ; nope, use our polling routine
    471 
    472 .writeByte2Ready:
    473         mov     dl,bl
    474         mov     al,ah           ; output second byte
    475         out     dx,al
    476 
    477 .entry:
    478         mov     dl,bh           ; transmit buffer empty?
    479         in      al,dx
    480         test    al,20h
    481         mov     dl,bl
    482         jz      .writeTimeout1  ; nope, use our polling routine
    483 
    484 .writeByte1Ready:
    485         loop    .writeLoop
    486 
    487         mov     ax,di           ; fold Fletcher's checksum and output
    488         xor     al,ah
    489         out     dx,al           ; byte 1
    490 
    491         call    SerialCommand_WaitAndPoll_Write
    492 
    493         mov     ax,bp
    494         xor     al,ah
    495         out     dx,al           ; byte 2
    496 
    497         ret
    498 
    499 .writeTimeout2:
    500         mov     dl,ah           ; need to preserve AH, but don't need DL (will be reset upon return)
    501         call    SerialCommand_WaitAndPoll_Write
    502         mov     ah,dl
    503         jmp     .writeByte2Ready
    504 
    505 .writeTimeout1:
    506 %ifndef USE_186
    507         mov     ax,.writeByte1Ready
    508         push    ax              ; return address for ret at end of SC_writeTimeout2
    509 %else
    510         push    .writeByte1Ready
    511 %endif
    512 ;;; fall-through
    513 
    514 ;--------------------------------------------------------------------
    515 ; SerialCommand_WaitAndPoll
    516 ;
    517 ;   Parameters:
    518 ;       AH:     UART_LineStatus bit to test (20h for write, or 1h for read)
    519 ;               One entry point fills in AH with 20h for write
    520 ;       DX:     Port address (OK if already incremented to UART_lineStatus)
    521 ;       BX:
    522 ;       Stack:  2 words on the stack below the command/count word
    523 ;   Returns:
    524 ;       Returns when desired UART_LineStatus bit is cleared
    525 ;       Jumps directly to error exit if timeout elapses (and cleans up stack)
    526 ;   Corrupts registers:
    527 ;       AX
    528 ;--------------------------------------------------------------------
    529 
    530 SerialCommand_WaitAndPoll_SoftDelayTicks   EQU   20
    531 
    532 ALIGN JUMP_ALIGN
    533 SerialCommand_WaitAndPoll_Write:
    534         mov     ah,20h
    535 ;;; fall-through
    536 
    537 ALIGN JUMP_ALIGN
    538 SerialCommand_WaitAndPoll_Read:
    539         push    cx
    540         push    dx
    541 
    542 ;
    543 ; We first poll in a tight loop, interrupts off, for the next character to come in/be sent
    544 ;
    545         xor     cx,cx
    546 .readTimeoutLoop:
    547         mov     dl,bh
    548         in      al,dx
    549         test    al,ah
    550         jnz     .readTimeoutComplete
    551         loop    .readTimeoutLoop
    552 
    553 ;
    554 ; If that loop completes, then we assume there is a long delay involved, turn interrupts back on
    555 ; and wait for a given number of timer ticks to pass.
    556 ;
    557         sti
    558         mov     cl,SerialCommand_WaitAndPoll_SoftDelayTicks
    559         call    Timer_InitializeTimeoutWithTicksInCL
    560 .WaitAndPoll:
    561         call    Timer_SetCFifTimeout
    562         jc      SerialCommand_OutputWithParameters_ErrorAndPop4Words
    563         in      al,dx
    564         test    al,ah
    565         jz      .WaitAndPoll
    566         cli
    567 
    568 .readTimeoutComplete:
    569         pop     dx
    570         pop     cx
    571         ret
    57250
    57351;--------------------------------------------------------------------
     
    57957;       CS:BP:  Ptr to IDEVARS
    58058;   Returns:
    581 ;       AH:     INT 13h Error Code
    582 ;               NOTE: Not set (or checked) during drive detection
    58359;       CF:     Cleared if success, Set if error
    58460;   Corrupts registers:
     
    632108;     master scan.
    633109;
    634         mov     cx,1            ; 1 sector to move, 0 for non-scan
    635110        mov     dx,[cs:bp+IDEVARS.wSerialPortAndBaud]
    636111        xor     ax,ax
     112       
    637113        push    si
    638114        call    FindDPT_ToDSDIforSerialDevice
     
    642118;
    643119; If not found above with FindDPT_ToDSDIforSerialDevice, DI will point to the DPT after the last hard disk DPT
     120; So, if there was a previously found floppy disk, DI will point to that DPT and we use that value for the slave.
    644121;
    645122        cmp     byte [RAMVARS.xlateVars+XLATEVARS.bFlopCntAndFirst], 0
     
    647124.founddpt:
    648125%else
    649         jnc     .notfounddpt
     126        jc      .notfounddpt
    650127%endif
    651128        mov     ax, [di+DPT_SERIAL.wSerialPortAndBaud]
     
    656133
    657134        test    ax,ax           ; Take care of the case that is different between master and slave.
    658         jz      .error          ; Because we do this here, the jz after the "or" below will not be taken
     135        jz      .error         
    659136
    660137; fall-through
     
    663140        jnz     .identifyDeviceInDX
    664141
    665         or      dx,ax           ; Since DX is zero, this effectively moves the previously found serial drive
    666                                 ; information to dx, as well as test for zero
    667         jz      .scanSerial
     142        xchg    dx, ax          ;  move ax to dx (move previously found serial drive to dx, could be zero)
    668143
    669 ; fall-through
    670 .identifyDeviceInDX:
    671 
    672         push    bp              ; setup fake IDEREGS_AND_INTPACK
    673 
    674         push    dx
    675 
    676         push    cx
    677 
    678         mov     bl,0a0h         ; protocol command to ah and onto stack with bh
    679         mov     ah,bl
    680 
    681         push    bx
    682 
    683         mov     bp,sp
    684         call    SerialCommand_OutputWithParameters_DeviceInDX
    685 
    686         pop     bx
    687 
    688         pop     cx
    689         pop     dx
    690 
    691         pop     bp
    692 ;
    693 ; place port and baud word in to the return sector, in a vendor specific area,
    694 ; which is read by FinalizeDPT and DetectDrives
    695 ;
    696         mov     [es:si+ATA6.wSerialPortAndBaud],dx
    697 
    698 .notFound:
    699         ret
    700 
    701 ;----------------------------------------------------------------------
    702 ;
    703 ; SerialCommand_AutoSerial
    704 ;
    705 ; When the SerialAuto IDEVARS entry is used, scans the COM ports on the machine for a possible serial connection.
    706 ;
    707 
    708 .scanPortAddresses: db  DEVICE_SERIAL_COM7 >> 2
    709                     db  DEVICE_SERIAL_COM6 >> 2
    710                     db  DEVICE_SERIAL_COM5 >> 2
    711                     db  DEVICE_SERIAL_COM4 >> 2
    712                     db  DEVICE_SERIAL_COM3 >> 2
    713                     db  DEVICE_SERIAL_COM2 >> 2
    714                     db  DEVICE_SERIAL_COM1 >> 2
    715                     db  0
    716 
    717 ALIGN JUMP_ALIGN
    718 .scanSerial:
    719         mov     di,.scanPortAddresses-1
    720         mov     ch,1            ;  tell server that we are scanning
    721 
    722 .nextPort:
    723         inc     di              ; load next port address
    724         xor     dh, dh
    725         mov     dl,[cs:di]
    726         eSHL_IM dx, 2           ; shift from one byte to two
    727         jz      .error
    728 
    729 ;
    730 ; Test for COM port presence, write to and read from registers
    731 ;
    732         push    dx
    733         add     dl,SerialCommand_UART_lineControl
    734         mov     al, 09ah
    735         out     dx, al
    736         in      al, dx
    737         pop     dx
    738         cmp     al, 09ah
    739         jnz     .nextPort
    740 
    741         mov     al, 0ch
    742         out     dx, al
    743         in      al, dx
    744         cmp     al, 0ch
    745         jnz     .nextPort
    746 
    747 ;
    748 ; Begin baud rate scan on this port...
    749 ;
    750 ; On a scan, we support 6 baud rates, starting here and going higher by a factor of two each step, with a
    751 ; small jump between 9600 and 38800.  These 6 were selected since we wanted to support 9600 baud and 115200,
    752 ; *on the server side* if the client side had a 4x clock multiplier, a 2x clock multiplier, or no clock multiplier.
    753 ;
    754 ; Starting with 30h, that means 30h (2400 baud), 18h (4800 baud), 0ch (9600 baud), and
    755 ;                               04h (28800 baud), 02h (57600 baud), 01h (115200 baud)
    756 ;
    757 ; Note: hardware baud multipliers (2x, 4x) will impact the final baud rate and are not known at this level
    758 ;
    759         mov     dh,030h * 2     ; multiply by 2 since we are about to divide by 2
    760         mov     dl,[cs:di]      ; restore single byte port address for scan
    761 
    762 .nextBaud:
    763         shr     dh,1
    764         jz      .nextPort
    765         cmp     dh,6            ; skip from 6 to 4, to move from the top of the 9600 baud range
    766         jnz     .testBaud       ; to the bottom of the 115200 baud range
    767         mov     dh,4
    768 
    769 .testBaud:
    770         call    .identifyDeviceInDX
    771         jc      .nextBaud
    772 
    773         ret
     144.identifyDeviceInDX:   
     145        jmp     SerialServerScan_ScanForServer
    774146
    775147.error:
    776148        stc
    777 %if 0
    778         mov     ah,1        ; setting the error code is unnecessary as this path can only be taken during
    779                             ; drive detection, and drive detection works off CF and does not check AH
    780 %endif
    781149        ret
    782 
    783 
Note: See TracChangeset for help on using the changeset viewer.