source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialCommand.asm@ 230

Last change on this file since 230 was 226, checked in by gregli@…, 13 years ago

Moved .bSerialPortAndBaud out of the main DPT into a an attached struc DPT_SERIAL, used by the serial port code only

File size: 23.6 KB
Line 
1; Project name : XTIDE Universal BIOS
2; Description : Serial Device Command functions.
3
4; Section containing code
5SECTION .text
6
7;--------------- UART Equates -----------------------------
8;
9; Serial Programming References:
10; http://en.wikibooks.org/wiki/Serial_Programming
11;
12
13SerialCommand_UART_base EQU 0
14SerialCommand_UART_transmitByte EQU 0
15SerialCommand_UART_receiveByte EQU 0
16
17;
18; Values for UART_divisorLow:
19; 60h = 1200, 30h = 2400, 18h = 4800, 0ch = 9600, 6 = 19200, 3 = 38400, 2 = 57600, 1 = 115200
20;
21SerialCommand_UART_divisorLow EQU 0
22
23;
24; We support 4 baud rates, starting here going higher and skipping every other baud rate
25; Starting with 30h, that means 30h (1200 baud), 0ch (9600 baud), 3 (38400 baud), and 1 (115200 baud)
26; Note: hardware baud multipliers (2x, 4x) will impact the final baud rate and are not known at this level
27;
28SerialCommand_UART_divisorLow_startingBaud EQU 030h
29
30SerialCommand_UART_interruptEnable EQU 1
31
32;
33; UART_divisorHigh is zero for all speeds including and above 1200 baud (which is all we do)
34;
35SerialCommand_UART_divisorHigh EQU 1
36
37SerialCommand_UART_interruptIdent EQU 2
38SerialCommand_UART_FIFOControl EQU 2
39
40SerialCommand_UART_lineControl EQU 3
41
42SerialCommand_UART_modemControl EQU 4
43
44SerialCommand_UART_lineStatus EQU 5
45
46SerialCommand_UART_modemStatus EQU 6
47
48SerialCommand_UART_scratch EQU 7
49
50SerialCommand_Protocol_Write EQU 3
51SerialCommand_Protocol_Read EQU 2
52SerialCommand_Protocol_Inquire EQU 0
53SerialCommand_Protocol_Header EQU 0a0h
54
55;--------------------------------------------------------------------
56; SerialCommand_OutputWithParameters
57; Parameters:
58; BH: Non-zero if 48-bit addressing used
59; (ignored at present as 48-bit addressing is not supported)
60; BL: IDE Status Register bit to poll after command
61; (ignored at present, since there is no IDE status register to poll)
62; ES:SI: Ptr to buffer (for data transfer commands)
63; DS:DI: Ptr to DPT (in RAMVARS segment)
64; SS:BP: Ptr to IDEREGS_AND_INTPACK
65; Returns:
66; AH: INT 13h Error Code
67; CF: Cleared if success, Set if error
68; Corrupts registers:
69; AL, BX, CX, DX, (ES:SI for data transfer commands)
70;--------------------------------------------------------------------
71ALIGN JUMP_ALIGN
72SerialCommand_OutputWithParameters:
73
74 mov ah,(SerialCommand_Protocol_Header | SerialCommand_Protocol_Read)
75
76 mov al,[bp+IDEPACK.bCommand]
77
78 cmp al,20h ; Read Sectors IDE command
79 jz .readOrWrite
80 inc ah ; now SerialCommand_Protocol_Write
81 cmp al,30h ; Write Sectors IDE command
82 jz .readOrWrite
83
84; all other commands return success
85; including function 0ech which should return drive information, this is handled with the identify functions
86;
87 xor ah,ah ; also clears carry
88 ret
89
90.readOrWrite:
91 mov [bp+IDEPACK.bFeatures],ah ; store protocol command
92
93 mov dl, byte [di+DPT_SERIAL.bSerialPortAndBaud]
94
95; fall-through
96
97;--------------------------------------------------------------------
98; SerialCommand_OutputWithParameters_DeviceInDL
99; Parameters:
100; AH: Protocol Command
101; DL: Packed I/O port and baud rate
102; ES:SI: Ptr to buffer (for data transfer commands)
103; SS:BP: Ptr to IDEREGS_AND_INTPACK
104; Returns:
105; AH: INT 13h Error Code
106; CF: Cleared if success, Set if error
107; Corrupts registers:
108; AL, BX, CX, DX, (ES:SI for data transfer commands)
109;--------------------------------------------------------------------
110SerialCommand_OutputWithParameters_DeviceInDL:
111
112 push si
113 push di
114 push bp
115
116;
117; Unpack I/O port and baud from DPT
118; Port to DX more or less for the remainder of the routine
119; Baud in CH until UART initialization is complete
120;
121 mov dh, ((DEVICE_SERIAL_PACKEDPORTANDBAUD_STARTINGPORT & 0f00h) >> (8+1))
122 shl dx, 1 ; port offset already x4, needs one more shift to be x8
123 mov cl, dl
124
125 and cl, (DEVICE_SERIAL_PACKEDPORTANDBAUD_BAUDMASK << 1)
126 mov ch, SerialCommand_UART_divisorLow_startingBaud
127 shr ch, cl
128 adc ch, 0
129
130 and dl, ((DEVICE_SERIAL_PACKEDPORTANDBAUD_PORTMASK << 1) & 0ffh)
131 add dx, byte (DEVICE_SERIAL_PACKEDPORTANDBAUD_STARTINGPORT & 0ffh)
132
133 mov al,[bp+IDEPACK.bSectorCount]
134
135;
136; Command byte and sector count live at the top of the stack, pop/push are used to access
137;
138 push ax
139
140%if 0
141 cld ; Shouldn't be needed. DF has already been cleared (line 24, Int13h.asm)
142%endif
143
144;----------------------------------------------------------------------
145;
146; Initialize UART
147;
148; We do this each time since DOS (at boot) or another program may have
149; decided to reprogram the UART
150;
151 mov bl,dl ; setup BL with proper values for read/write loops (BH comes later)
152
153 mov al,83h
154 add dl,SerialCommand_UART_lineControl
155 out dx,al
156
157 mov al,ch
158 mov dl,bl ; divisor low
159 out dx,al
160
161 xor ax,ax
162 inc dx ; divisor high
163 push dx
164 out dx,al
165
166 mov al,047h
167 inc dx ; fifo
168 out dx,al
169
170 mov al,03h
171 inc dx ; linecontrol
172 out dx,al
173
174 mov al,0bh
175 inc dx ; modemcontrol
176 out dx,al
177
178 inc dx ; linestatus (no output now, just setting up BH for later use)
179 mov bh,dl
180
181 pop dx ; base, interrupts disabled
182 xor ax,ax
183 out dx,al
184
185;----------------------------------------------------------------------
186;
187; Send Command
188;
189; Sends first six bytes of IDEREGS_AND_INTPACK as the command
190;
191 push es ; save off real buffer location
192 push si
193
194 mov si,bp ; point to IDEREGS for command dispatch;
195 push ss
196 pop es
197
198 mov di,0ffffh ; initialize checksum for write
199 mov bp,di
200
201 mov cx,4 ; writing 3 words (plus 1)
202
203 cli ; interrupts off...
204
205 call SerialCommand_WriteProtocol.entry
206
207 pop di ; restore real buffer location (note change from SI to DI)
208 ; Buffer is primarily referenced through ES:DI throughout, since
209 ; we need to store (read sector) faster than we read (write sector)
210 pop es
211
212%if 0
213;;; no longer needed, since the pointer is normalized before we are called and we do not support
214;;; more than 128 sectors (and for 128 specifically, the pointer must be segment aligned).
215;;; See comments below at the point this entry point was called for more details...
216.nextSectorNormalize:
217 call Registers_NormalizeESDI
218%endif
219
220 pop ax ; load command byte (done before call to .nextSector on subsequent iterations)
221 push ax
222
223;
224; Top of the read/write loop, one iteration per sector
225;
226.nextSector:
227 mov si,0ffffh ; initialize checksum for read or write
228 mov bp,si
229
230 mov cx,0101h ; writing 256 words (plus 1)
231
232 shr ah,1 ; command byte, are we doing a write?
233 jnc .readEntry
234
235 xchg si,di
236 call SerialCommand_WriteProtocol.entry
237 xchg si,di
238
239 inc cx ; CX = 1 now (0 out of WriteProtocol)
240 jmp .readEntry
241
242;----------------------------------------------------------------------
243;
244; Timeout
245;
246; To save code space, we use the contents of DL to decide which byte in the word to return for reading.
247;
248.readTimeout:
249 push ax ; not only does this push preserve AX (which we need), but it also
250 ; means the stack has the same number of bytes on it as when we are
251 ; sending a packet, important for error cleanup and exit
252 mov ah,1
253 call SerialCommand_WaitAndPoll_Read
254 pop ax
255 test dl,1
256 jz .readByte1Ready
257 jmp .readByte2Ready
258
259;----------------------------------------------------------------------------
260;
261; Read Block (without interrupts, used when there is a FIFO, high speed)
262;
263; NOTE: This loop is very time sensitive. Literally, another instruction
264; cannot be inserted into this loop without us falling behind at high
265; speed (460.8K baud) on a 4.77Mhz 8088, making it hard to receive
266; a full 512 byte block.
267;
268.readLoop:
269 stosw ; store word in caller's data buffer
270
271 add bp, ax ; update Fletcher's checksum
272 adc bp, 0
273 add si, bp
274 adc si, 0
275
276.readEntry:
277 mov dl,bh
278 in al,dx
279 shr al,1 ; data ready (byte 1)?
280 mov dl,bl ; get ready to read data
281 jnc .readTimeout ; nope not ready, update timeouts
282
283;
284; Entry point after initial timeout. We enter here so that the checksum word
285; is not stored (and is left in AX after the loop is complete).
286;
287.readByte1Ready:
288 in al, dx ; read data byte 1
289
290 mov ah, al ; store byte in ah for now
291
292;
293; note the placement of this reset of dl to bh, and that it is
294; before the return, which is assymetric with where this is done
295; above for byte 1. The value of dl is used by the timeout routine
296; to know which byte to return to (.read_byte1_ready or
297; .read_byte2_ready)
298;
299 mov dl,bh
300
301 in al,dx
302 shr al,1 ; data ready (byte 2)?
303 jnc .readTimeout
304.readByte2Ready:
305 mov dl,bl
306 in al, dx ; read data byte 2
307
308 xchg al, ah ; ah was holding byte 1, reverse byte order
309
310 loop .readLoop
311
312 sti ; interrupts back on ASAP, between packets
313
314;
315; Compare checksums
316;
317 xchg ax,bp
318 xor ah,al
319 mov cx,si
320 xor cl,ch
321 mov al,cl
322 cmp ax,bp
323 jnz SerialCommand_OutputWithParameters_Error
324
325 pop ax ; sector count and command byte
326 dec al ; decrement sector count
327 push ax ; save
328 jz SerialCommand_OutputWithParameters_ReturnCodeInALCF ; CF=0 from "cmp ax,bp" returning Zero above
329
330 cli ; interrupts back off for ACK byte to host
331 ; (host could start sending data immediately)
332 out dx,al ; ACK with next sector number
333
334%if 0
335;;; This code is no longer needed as we do not support more than 128 sectors, and for 128 the pointer
336;;; must be segment aligned. If we ever do want to support more sectors, the code can help...
337
338;
339; Normalize buffer pointer for next go round, if needed.
340;
341; We need to re-normalize the pointer in ES:DI after processing every 7f sectors. That number could
342; have been 80 if we knew the offset was on a segment boundary, but this may not be the case.
343;
344; We re-normalize based on the sector count (flags from "dec al" above)...
345; a) we normalize before the first sector goes out, immediately after sending the command packet (above)
346; b) on transitions from FF to FE, very rare case for writing 255 or 256 sectors
347; c) on transitions from 80 to 7F, a large read/write
348; d) on transitions from 00 to FF, very, very rare case of writing 256 sectors
349; We don't need to renormalize in this case, but it isn't worth the memory/effort to not do
350; the extra work, and it does no harm.
351;
352; I really don't care much about (d) because I have not seen cases where any OS makes a request
353; for more than 127 sectors. Back in the day, it appears that some BIOS could not support more than 127
354; sectors, so that may be the practical limit for OS and application developers. The Extended BIOS
355; function also appear to be capped at 127 sectors. So although this can support the full 256 sectors
356; if needed, we are optimized for that 1-127 range.
357;
358; Assume we start with 0000:000f, with 256 sectors to write...
359; After first packet, 0000:020f
360; First decrement of AL, transition from 00 to FF: renormalize to 0020:000f (unnecessary)
361; After second packet, 0020:020f
362; Second derement of AL, transition from FF to FE: renormalize to 0040:000f
363; After 7f more packets, 0040:fe0f
364; Decrement of AL, transition from 80 to 7F: renormalize to 1020:000f
365; After 7f more packets, 1020:fe0f or 2000:000f if normalized
366; Decrement of AL, from 1 to 0: exit
367;
368 jge short .nextSector ; OF=SF, branch for 1-7e, most common case
369 ; (0 kicked out above for return success)
370
371 add al,2 ; 7f-ff moves to 81-01
372 ; (0-7e kicked out before we get here)
373 ; 7f moves to 81 and OF=1, so OF=SF
374 ; fe moves to 0 and OF=0, SF=0, so OF=SF
375 ; ff moves to 1 and OF=0, SF=0, so OF=SF
376 ; 80-fd moves to 82-ff and OF=0, so OF<>SF
377
378 jl short .nextSector ; OF<>SF, branch for all cases but 7f, fe, and ff
379
380; jpo short .nextSector ; if we really wanted to avoid normalizing for ff, this
381 ; is one way to do it, but it adds more memory and more
382 ; cycles for the 7f and fe cases. IMHO, given that I've
383 ; never seen a request for more than 7f, this seems unnecessary.
384
385 jmp short .nextSectorNormalize ; our two renormalization cases (plus one for ff)
386
387%else
388
389 jmp short .nextSector
390
391%endif
392
393;---------------------------------------------------------------------------
394;
395; Cleanup, error reporting, and exit
396;
397
398;
399; Used in situations where a call is underway, such as with SerialCommand_WaitAndPoll
400;
401ALIGN JUMP_ALIGN
402SerialCommand_OutputWithParameters_ErrorAndPop4Words:
403 add sp,8
404;;; fall-through
405
406ALIGN JUMP_ALIGN
407SerialCommand_OutputWithParameters_Error:
408;----------------------------------------------------------------------
409;
410; Clear read buffer
411;
412; In case there are extra characters or an error in the FIFO, clear it out.
413; In theory the initialization of the UART registers above should have
414; taken care of this, but I have seen cases where this is not true.
415;
416.clearBuffer:
417 mov dl,bh
418 in al,dx
419 mov dl,bl
420 test al,08fh
421 jz .clearBufferComplete
422 shr al,1
423 in al,dx
424 jc .clearBuffer ; note CF from shr above
425
426.clearBufferComplete:
427 stc
428 mov al,1
429
430ALIGN JUMP_ALIGN
431SerialCommand_OutputWithParameters_ReturnCodeInALCF:
432%if 0
433 sti ; all paths here will already have interrupts turned back on
434%endif
435 mov ah,al
436
437 pop bp ; recover ax (command and count) from stack, throw away
438
439 pop bp
440 pop di
441 pop si
442
443 ret
444
445;--------------------------------------------------------------------
446; SerialCommand_WriteProtocol
447;
448; NOTE: As with its read counterpart, this loop is very time sensitive.
449; Although it will still function, adding additional instructions will
450; impact the write throughput, especially on slower machines.
451;
452; Parameters:
453; ES:SI: Ptr to buffer
454; CX: Words to write, plus 1
455; BP/DI: Initialized for Checksum (-1 in each)
456; DH: I/O Port high byte
457; BX: LineStatus Register address (BH) and Receive/Transmit Register address (BL)
458; Returns:
459; BP/DI: Checksum for written bytes, compared against ACK from server in .readLoop
460; CX: Zero
461; DL: Receive/Transmit Register address
462; Corrupts registers:
463; AX
464;--------------------------------------------------------------------
465ALIGN JUMP_ALIGN
466SerialCommand_WriteProtocol:
467.writeLoop:
468 es lodsw ; fetch next word
469
470 out dx,al ; output first byte
471
472 add bp,ax ; update checksum
473 adc bp,0
474 add di,bp
475 adc di,0
476
477 mov dl,bh ; transmit buffer empty?
478 in al,dx
479 test al,20h
480 jz .writeTimeout2 ; nope, use our polling routine
481
482.writeByte2Ready:
483 mov dl,bl
484 mov al,ah ; output second byte
485 out dx,al
486
487.entry:
488 mov dl,bh ; transmit buffer empty?
489 in al,dx
490 test al,20h
491 mov dl,bl
492 jz .writeTimeout1 ; nope, use our polling routine
493
494.writeByte1Ready:
495 loop .writeLoop
496
497 mov ax,di ; fold Fletcher's checksum and output
498 xor al,ah
499 out dx,al ; byte 1
500
501 call SerialCommand_WaitAndPoll_Write
502
503 mov ax,bp
504 xor al,ah
505 out dx,al ; byte 2
506
507 ret
508
509.writeTimeout2:
510 mov dl,ah ; need to preserve AH, but don't need DL (will be reset upon return)
511 call SerialCommand_WaitAndPoll_Write
512 mov ah,dl
513 jmp .writeByte2Ready
514
515.writeTimeout1:
516%ifndef USE_186
517 mov ax,.writeByte1Ready
518 push ax ; return address for ret at end of SC_writeTimeout2
519%else
520 push .writeByte1Ready
521%endif
522;;; fall-through
523
524;--------------------------------------------------------------------
525; SerialCommand_WaitAndPoll
526;
527; Parameters:
528; AH: UART_LineStatus bit to test (20h for write, or 1h for read)
529; One entry point fills in AH with 20h for write
530; DX: Port address (OK if already incremented to UART_lineStatus)
531; BX:
532; Stack: 2 words on the stack below the command/count word
533; Returns:
534; Returns when desired UART_LineStatus bit is cleared
535; Jumps directly to error exit if timeout elapses (and cleans up stack)
536; Corrupts registers:
537; AX
538;--------------------------------------------------------------------
539
540SerialCommand_WaitAndPoll_SoftDelayTicks EQU 20
541
542ALIGN JUMP_ALIGN
543SerialCommand_WaitAndPoll_Write:
544 mov ah,20h
545;;; fall-through
546
547ALIGN JUMP_ALIGN
548SerialCommand_WaitAndPoll_Read:
549 push cx
550 push dx
551
552;
553; We first poll in a tight loop, interrupts off, for the next character to come in/be sent
554;
555 xor cx,cx
556.readTimeoutLoop:
557 mov dl,bh
558 in al,dx
559 test al,ah
560 jnz .readTimeoutComplete
561 loop .readTimeoutLoop
562
563;
564; If that loop completes, then we assume there is a long delay involved, turn interrupts back on
565; and wait for a given number of timer ticks to pass.
566;
567 sti
568 mov cl,SerialCommand_WaitAndPoll_SoftDelayTicks
569 call Timer_InitializeTimeoutWithTicksInCL
570.WaitAndPoll:
571 call Timer_SetCFifTimeout
572 jc SerialCommand_OutputWithParameters_ErrorAndPop4Words
573 in al,dx
574 test al,ah
575 jz .WaitAndPoll
576 cli
577
578.readTimeoutComplete:
579 pop dx
580 pop cx
581 ret
582
583;--------------------------------------------------------------------
584; SerialCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH
585; Parameters:
586; BH: Drive Select byte for Drive and Head Select Register
587; DS: Segment to RAMVARS
588; ES:SI: Ptr to buffer to receive 512-byte IDE Information
589; CS:BP: Ptr to IDEVARS
590; Returns:
591; AH: INT 13h Error Code
592; NOTE: Not set (or checked) during drive detection
593; CF: Cleared if success, Set if error
594; Corrupts registers:
595; AL, BL, CX, DX, SI, DI, ES
596;--------------------------------------------------------------------
597ALIGN JUMP_ALIGN
598SerialCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH:
599;
600; To improve boot time, we do our best to avoid looking for slave serial drives when we already know the results
601; from the looking for a master. This is particularly true when doing a COM port scan, as we will end up running
602; through all the COM ports and baud rates a second time.
603;
604; But drive detection isn't the only case - we also need to get the right drive when called on int13h/25h.
605;
606; The decision tree:
607;
608; Master:
609; bSerialPackedPortAndBaud Non-Zero: -> Continue with bSerialPackedAndBaud (1)
610; bSerialPackedPortAndBaud Zero:
611; bLastSerial Zero: -> Scan (2)
612; bLastSerial Non-Zero: -> Continue with bLastSerial (3)
613;
614; Slave:
615; bSerialPackedPortAndBaud Non-Zero:
616; bLastSerial Zero: -> Error - Not Found (4)
617; bLastSerial Non-Zero: -> Continue with bSerialPackedAndBaud (5)
618; bSerialPackedPortAndBaud Zero:
619; bLastSerial Zero: -> Error - Not Found (4)
620; bLastSerial Non-Zero: -> Continue with bLastSerial (6)
621;
622; (1) This was a port/baud that was explicitly set with the configurator. In the drive detection case, as this
623; is the Master, we are checking out a new controller, and so don't care about the value of bLastSerial.
624; And as with the int13h/25h case, we just go off and get the needed information using the user's setting.
625; (2) We are using the special .ideVarsSerialAuto structure. During drive detection, we would only be here
626; if bLastSerial is zero (since we only scan if no explicit drives are set), so we go off to scan.
627; (3) We are using the special .ideVarsSerialAuto structure. We won't get here during drive detection, but
628; we might get here on an int13h/25h call. If we have scanned COM drives, they are the ONLY serial drives
629; in use, and so bLastSerial will reflect the port/baud setting for the scanned COM drives.
630; (4) No master has been found yet, therefore no slave should be found. Avoiding the slave reduces boot time,
631; especially in the full COM port scan case. Note that this is different from the hardware IDE, where we
632; will scan for a slave even if a master is not present. Note that if ANY master had been previously found,
633; we will do the slave scan, which isn't harmful, it just wastes time. But the most common case (by a wide
634; margin) will be just one serial controller.
635; (5) A COM port scan for a master had been previously completed, and a drive was found. In a multiple serial
636; controller scenario being called with int13h/25h, we need to use the value in bSerialPackedPortAndBaud
637; to make sure we get the proper drive.
638; (6) A COM port scan for a master had been previously completed, and a drive was found. We would only get here
639; if no serial drive was explicitly set by the user in the configurator or that drive had not been found.
640; Instead of performing the full COM port scan for the slave, use the port/baud value stored during the
641; master scan.
642;
643 mov dl,[cs:bp+IDEVARS.bSerialPackedPortAndBaud]
644 mov al, byte [RAMVARS.xlateVars+XLATEVARS.bLastSerial]
645
646 test bh, FLG_DRVNHEAD_DRV
647 jz .master
648
649 test al,al ; Take care of the case that is different between master and slave.
650 jz .error ; Because we do this here, the jz after the "or" below will not be taken
651
652; fall-through
653.master:
654 test dl,dl
655 jnz .identifyDeviceInDL
656
657 or dl,al ; Move bLast into position in dl, as well as test for zero
658 jz .scanSerial
659
660; fall-through
661.identifyDeviceInDL:
662
663 push bp ; setup fake IDEREGS_AND_INTPACK
664
665 push dx
666
667 mov cl,1 ; 1 sector to move
668 push cx
669
670 mov bl,0a0h ; protocol command to ah and onto stack with bh
671 mov ah,bl
672
673 push bx
674
675 mov bp,sp
676 call SerialCommand_OutputWithParameters_DeviceInDL
677
678 pop bx
679
680 pop cx
681 pop dx
682
683 pop bp
684;
685; place packed port/baud in RAMVARS, read by FinalizeDPT and DetectDrives
686;
687; Note that this will be set during an int13h/25h call as well. Which is OK since it is only used (at the
688; top of this routine) for drives found during a COM scan, and we only COM scan if there were no other
689; COM drives found. So we will only reaffirm the port/baud for the one COM port/baud that has a drive.
690;
691 jc .notFound ; only store bLastSerial if success
692 mov byte [RAMVARS.xlateVars+XLATEVARS.bLastSerial], dl
693
694.notFound:
695 ret
696
697;----------------------------------------------------------------------
698;
699; SerialCommand_AutoSerial
700;
701; When the SerialAuto IDEVARS entry is used, scans the COM ports on the machine for a possible serial connection.
702;
703
704.scanPortAddresses: db DEVICE_SERIAL_COM7 >> 2
705 db DEVICE_SERIAL_COM6 >> 2
706 db DEVICE_SERIAL_COM5 >> 2
707 db DEVICE_SERIAL_COM4 >> 2
708 db DEVICE_SERIAL_COM3 >> 2
709 db DEVICE_SERIAL_COM2 >> 2
710 db DEVICE_SERIAL_COM1 >> 2
711 db 0
712
713ALIGN JUMP_ALIGN
714.scanSerial:
715 mov di,.scanPortAddresses-1
716
717.nextPort:
718 inc di ; load next port address
719 xor dh, dh
720 mov dl,[cs:di]
721 eSHL_IM dx, 2 ; shift from one byte to two
722 jz .error
723
724;
725; Test for COM port presence, write to and read from registers
726;
727 push dx
728 add dl,SerialCommand_UART_lineControl
729 mov al, 09ah
730 out dx, al
731 in al, dx
732 pop dx
733 cmp al, 09ah
734 jnz .nextPort
735
736 mov al, 0ch
737 out dx, al
738 in al, dx
739 cmp al, 0ch
740 jnz .nextPort
741
742;
743; Pack into dl, baud rate starts at 0
744;
745 add dx,-(DEVICE_SERIAL_PACKEDPORTANDBAUD_STARTINGPORT)
746 shr dx,1 ; dh is zero at this point, and will be sent to the server,
747 ; so we know this is an auto detect
748
749 jmp .testFirstBaud
750
751;
752; Walk through 4 possible baud rates
753;
754.nextBaud:
755 inc dx
756 test dl,3
757 jz .nextPort
758
759.testFirstBaud:
760 call .identifyDeviceInDL
761 jc .nextBaud
762
763 ret
764
765.error:
766 stc
767%if 0
768 mov ah,1 ; setting the error code is unnecessary as this path can only be taken during
769 ; drive detection, and drive detection works off CF and does not check AH
770%endif
771 ret
772
773
Note: See TracBrowser for help on using the repository browser.