Changeset 179 in xtideuniversalbios for trunk/XTIDE_Universal_BIOS/Src/Device
- Timestamp:
- Oct 25, 2011, 7:11:38 AM (13 years ago)
- google:author:
- gregli@hotmail.com
- Location:
- trunk/XTIDE_Universal_BIOS/Src/Device/Serial
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialCommand.asm
r150 r179 4 4 ; Section containing code 5 5 SECTION .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 SerialCommand_UART_divisorLow EQU 0 17 ; Values for UART_divisorLow: 18 ; 60h = 1200, 30h = 2400, 18h = 4800, 0ch = 9600, 6 = 19200, 3 = 38400, 2 = 57600, 1 = 115200 19 20 SerialCommand_UART_divisorLow_startingBaud EQU 030h 21 ; We support 4 baud rates, starting here going higher and skipping every other baud rate 22 ; Starting with 30h, that means 30h (1200 baud), 0ch (9600 baud), 3 (38400 baud), and 1 (115200 baud) 23 ; Note: hardware baud multipliers (2x, 4x) will impact the final baud rate and are not known at this level 24 25 SerialCommand_UART_interruptEnable EQU 1 26 SerialCommand_UART_divisorHigh EQU 1 27 ; UART_divisorHigh is zero for all speeds including and above 1200 baud 28 29 SerialCommand_UART_interruptIdent EQU 2 30 SerialCommand_UART_FIFOControl EQU 2 31 32 SerialCommand_UART_lineControl EQU 3 33 34 SerialCommand_UART_modemControl EQU 4 35 36 SerialCommand_UART_lineStatus EQU 5 37 38 SerialCommand_UART_modemStatus EQU 6 39 40 SerialCommand_UART_scratch EQU 7 41 42 SerialCommand_PackedPortAndBaud_StartingPort EQU 240h 43 SerialCommand_PackedPortAndBaud_PortMask EQU 0fch ; upper 6 bits - 240h through 438h 44 SerialCommand_PackedPortAndBaud_BaudMask EQU 3 ; lower 2 bits - 4 baud rates 45 46 SerialCommand_Protocol_Write EQU 3 47 SerialCommand_Protocol_Read EQU 2 48 SerialCommand_Protocol_Inquire EQU 0 49 SerialCommand_Protocol_Header EQU 0a0h 50 51 ;-------------------------------------------------------------------- 52 ; SerialCommand_OutputWithParameters 53 ; Parameters: 54 ; BH: Non-zero if 48-bit addressing used 55 ; (ignored at present as 48-bit addressing is not supported) 56 ; BL: IDE Status Register bit to poll after command 57 ; (ignored at present, since there is no IDE status register to poll) 58 ; ES:SI: Ptr to buffer (for data transfer commands) 59 ; DS:DI: Ptr to DPT (in RAMVARS segment) 60 ; SS:BP: Ptr to IDEREGS_AND_INTPACK 61 ; Returns: 62 ; AH: INT 13h Error Code 63 ; CF: Cleared if success, Set if error 64 ; Corrupts registers: 65 ; AL, BX, CX, DX, (ES:SI for data transfer commands) 66 ;-------------------------------------------------------------------- 67 68 ALIGN JUMP_ALIGN 69 SerialCommand_OutputWithParameters: 70 71 mov ah,(SerialCommand_Protocol_Header | SerialCommand_Protocol_Read) 72 73 mov al,[bp+IDEPACK.bCommand] 74 75 cmp al,20h ; Read Sectors IDE command 76 jz .readOrWrite 77 inc ah ; now SerialCommand_Protocol_Write 78 cmp al,30h ; Write Sectors IDE command 79 jz .readOrWrite 80 81 ; all other commands return success 82 ; including function 0ech which should return drive information, this is handled with the identify functions 83 xor ah,ah ; also clears carry 84 ret 85 86 .readOrWrite: 87 mov [bp+IDEPACK.bFeatures],ah ; store protocol command 88 89 mov dl, byte [ds:di+DPT.bSerialPortAndBaud] 90 91 ; fall-through 92 93 ;-------------------------------------------------------------------- 94 ; SerialCommand_OutputWithParameters_DeviceInDL 95 ; Parameters: 96 ; AH: Protocol Command 97 ; DL: Packed I/O port and baud rate 98 ; ES:SI: Ptr to buffer (for data transfer commands) 99 ; SS:BP: Ptr to IDEREGS_AND_INTPACK 100 ; Returns: 101 ; AH: INT 13h Error Code 102 ; CF: Cleared if success, Set if error 103 ; Corrupts registers: 104 ; AL, BX, CX, DX, (ES:SI for data transfer commands) 105 ;-------------------------------------------------------------------- 106 SerialCommand_OutputWithParameters_DeviceInDL: 107 108 push si 109 push di 110 push bp 111 push es 112 113 ; 114 ; Unpack I/O port and baud from DPT 115 ; Port to DX more or less for the remainder of the routine 116 ; Baud in CH until UART initialization is complete 117 ; 118 mov cl, dl 119 120 and cl, SerialCommand_PackedPortAndBaud_BaudMask 121 shl cl, 1 122 mov ch, SerialCommand_UART_divisorLow_startingBaud 123 shr ch, cl 124 adc ch, 0 125 126 and dl, SerialCommand_PackedPortAndBaud_PortMask 127 mov dh, 0 128 shl dx, 1 129 add dx, SerialCommand_PackedPortAndBaud_StartingPort 130 131 ; 132 ; Buffer is referenced through ES:DI throughout, since we need to store faster than we read 133 ; 134 mov di,si 135 136 mov al,[bp+IDEPACK.bSectorCount] 137 138 ; 139 ; Command byte and sector count live at the top of the stack, pop/push are used to access 140 ; 141 push ax 142 143 cld 144 145 ;---------------------------------------------------------------------- 146 ; 147 ; Initialize UART 148 ; 149 ; We do this each time since DOS (at boot) or another program may have 150 ; decided to reprogram the UART 151 ; 152 push dx 153 154 mov al,83h 155 add dl,SerialCommand_UART_lineControl 156 out dx,al 157 158 mov al,ch 159 pop dx ; divisor low 160 out dx,al 161 162 xor ax,ax 163 inc dx ; divisor high 164 push dx 165 out dx,al 166 167 mov al,047h 168 inc dx ; fifo 169 out dx,al 170 171 mov al,03h 172 inc dx ; linecontrol 173 out dx,al 174 175 mov al,0bh 176 inc dx ; modemcontrol 177 out dx,al 178 179 pop dx ; base, interrupts disabled 180 xor ax,ax 181 out dx,al 182 dec dx 183 184 ;---------------------------------------------------------------------- 185 ; 186 ; Send Command 187 ; 188 ; Sends first six bytes of IDEREGS_AND_INTPACK as the command 189 ; 190 call Registers_NormalizeESDI 191 192 push es ; save off real buffer location 193 push di 194 195 mov di,bp ; point to IDEREGS for command dispatch; 196 push ss 197 pop es 198 199 xor si,si ; initialize checksum for write 200 dec si 201 mov bp,si 202 203 mov bl,03h ; writing 3 words 204 205 call SerialCommand_WriteProtocol 206 207 pop di ; restore real buffer location 208 pop es 209 210 pop ax ; load command byte (done before call to .nextSector on subsequent iterations) 211 push ax 212 213 ; 214 ; Top of the read/write loop, one iteration per sector 215 ; 216 .nextSector: 217 xor si,si ; initialize checksum for read or write 218 dec si 219 mov bp,si 220 221 mov bx,0100h 222 223 shr ah,1 ; command byte, are we doing a write? 224 jnc .readSector 225 call SerialCommand_WriteProtocol 226 227 xor bx,bx 228 229 .readSector: 230 mov cx,bx 231 inc cx 232 233 mov bl,dl ; setup bl with proper values for read loop (bh comes later) 234 235 ;---------------------------------------------------------------------- 236 ; 237 ; Timeout 238 ; 239 ; During read, we first poll in a tight loop, interrupts off, for the next character to come in 240 ; If that loop completes, then we assume there is a long delay involved, turn interrupts back on 241 ; and wait for a given number of timer ticks to pass. 242 ; 243 ; To save code space, we use the contents of DL to decide which byte in the word to return for reading. 244 ; 245 .readTimeout: 246 push cx 247 xor cx,cx 248 .readTimeoutLoop: 249 push dx 250 or dl,SerialCommand_UART_lineStatus 251 in al,dx 252 pop dx 253 shr al,1 254 jc .readTimeoutComplete 255 loop .readTimeoutLoop 256 sti 257 mov bh,1 258 call SerialCommand_WaitAndPoll_Init 259 cli 260 .readTimeoutComplete: 261 mov bh,bl 262 or bh,SerialCommand_UART_lineStatus 263 264 pop cx 265 test dl,1 266 jz .readByte1Ready 267 jmp .readByte2Ready 268 269 ;---------------------------------------------------------------------------- 270 ; 271 ; Read Block (without interrupts, used when there is a FIFO, high speed) 272 ; 273 ; NOTE: This loop is very time sensitive. Literally, another instruction 274 ; 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 276 ; a full 512 byte block. 277 ; 278 .readLoop: 279 add bp, ax ; update Fletcher's checksum 280 adc bp, 0 281 add si, bp 282 adc si, 0 283 284 stosw ; store word in caller's data buffer 285 286 mov dl,bh 287 in al,dx 288 shr al,1 ; data ready (byte 1)? 289 mov dl,bl ; get ready to read data 290 jnc .readTimeout ; nope not ready, update timeouts 291 292 ; 293 ; Entry point after initial timeout. We enter here so that the checksum word 294 ; is not stored (and is left in AX after the loop is complete). 295 ; 296 .readByte1Ready: 297 in al, dx ; read data byte 1 298 299 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 306 ; .read_byte2_ready) 307 ; 308 mov dl,bh 309 310 in al,dx 311 shr al,1 ; data ready (byte 2)? 312 jnc .readTimeout 313 .readByte2Ready: 314 mov dl,bl 315 in al, dx ; read data byte 2 316 317 xchg al, ah ; ah was holding byte 1, reverse byte order 318 319 loop .readLoop 320 321 ; 322 ; Compare checksums 323 ; 324 xor bp,si 325 cmp ax,bp 326 jnz SerialCommand_OutputWithParameters_Error 327 328 sti ; interrupts back on ASAP, if we turned them off 329 330 ;---------------------------------------------------------------------- 331 ; 332 ; Clear read buffer 333 ; 334 ; 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 336 ; taken care of this, but I have seen cases where this is not true. 337 ; 338 .clearBuffer: 339 mov dl,bh 340 in al,dx 341 mov dl,bl 342 test al,08fh 343 jz .clearBufferComplete 344 shr al,1 345 in al,dx 346 jc .clearBuffer ; note CF from shr above 347 jmp SerialCommand_OutputWithParameters_Error 348 349 .clearBufferComplete: 350 pop ax ; sector count and command byte 351 dec al ; decrememnt sector count 352 push ax ; save 353 jz SerialCommand_OutputWithParameters_ReturnCodeInALCF ; CF clear from .clearBuffer test above 354 355 cli ; interrupts back off for ACK byte to host 356 ; (host could start sending data immediately) 357 out dx,al ; ACK with next sector number 358 359 jmp .nextSector ; all is well, time for next sector 360 361 ;--------------------------------------------------------------------------- 362 ; 363 ; Cleanup, error reporting, and exit 364 ; 365 366 ; 367 ; Used in situations where a call is underway, such as with SerialCommand_WaitAndPoll 368 ; 369 SerialCommand_OutputWithParameters_ErrorAndPop2Words: 370 pop ax 371 pop ax 372 373 SerialCommand_OutputWithParameters_Error: 374 mov al,1 375 stc 376 377 SerialCommand_OutputWithParameters_ReturnCodeInALCF: 378 mov ah,al 379 sti 380 381 pop bp ; recover ax from stack, throw away 382 383 pop es 384 pop bp 385 pop di 386 pop si 387 388 ret 389 390 ;-------------------------------------------------------------------- 391 ; SerialCommand_WaitAndPoll 392 ; 393 ; Parameters: 394 ; BH: UART_LineStatus bit to test (20h for write, or 1h for read) 395 ; DX: Port address (OK if already incremented to UART_lineStatus) 396 ; Stack: 2 words on the stack below the command/count word 397 ; Returns: 398 ; Returns when desired UART_LineStatus bit is cleared 399 ; Jumps directly to error exit if timeout elapses (and cleans up stack) 400 ; Corrupts registers: 401 ; CX, flags 402 ;-------------------------------------------------------------------- 403 404 SerialCommand_WaitAndPoll_SoftDelayTicks EQU 20 405 406 ALIGN JUMP_ALIGN 407 SerialCommand_WaitAndPoll_Init: 408 mov cl,SerialCommand_WaitAndPoll_SoftDelayTicks 409 call Timer_InitializeTimeoutWithTicksInCL 410 ; fall-through 411 412 SerialCommand_WaitAndPoll: 413 call Timer_SetCFifTimeout 414 jc SerialCommand_OutputWithParameters_ErrorAndPop2Words 415 push dx 416 push ax 417 or dl,SerialCommand_UART_lineStatus 418 in al,dx 419 test al,bh 420 pop ax 421 pop dx 422 jz SerialCommand_WaitAndPoll 423 ; fall-through 424 425 SerialCommand_WaitAndPoll_Done: 426 ret 427 428 ;-------------------------------------------------------------------- 429 ; SerialCommand_WriteProtocol 430 ; 431 ; Parameters: 432 ; ES:DI: Ptr to buffer 433 ; BL: Words to write (1-255, or 0=256) 434 ; BP/SI: Initialized for Checksum (-1 in each) 435 ; DX: I/O Port 436 ; Returns: 437 ; BP/SI: Checksum for written bytes, compared against ACK from server in .readLoop 438 ; Corrupts registers: 439 ; AX, BX, CX, DI 440 ;-------------------------------------------------------------------- 441 ALIGN JUMP_ALIGN 442 SerialCommand_WriteProtocol: 443 mov bh,20h 444 445 .writeLoop: 446 test bh,1 447 jnz SerialCommand_WaitAndPoll_Done 448 449 mov ax,[es:di] ; fetch next word 450 inc di 451 inc di 452 453 add bp,ax ; update checksum 454 adc bp,0 455 add si,bp 456 adc si,0 457 458 .writeLoopChecksum: 459 call SerialCommand_WaitAndPoll_Init 460 461 out dx,al ; output first byte 462 463 call SerialCommand_WaitAndPoll 464 465 mov al,ah ; output second byte 466 out dx,al 467 468 dec bl 469 jnz .writeLoop 470 471 inc bh 472 473 mov ax,bp ; merge checksum for possible write (last loop) 474 xor ax,si 475 476 jmp .writeLoopChecksum 477 478 479 ; To return the port number and baud rate to the FinalizeDPT routine, we 480 ; stuff the value in a "vendor" specific area of the 512-byte IdentifyDevice 481 ; sector. 482 ; 483 SerialCommand_IdentifyDevice_PackedPortAndBaud equ (157*2) 6 484 7 485 ;-------------------------------------------------------------------- … … 21 499 SerialCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH: 22 500 23 24 ;-------------------------------------------------------------------- 25 ; SerialCommand_OutputWithParameters 26 ; Parameters: 27 ; BH: Non-zero if 48-bit addressing used 28 ; BL: IDE Status Register bit to poll after command 29 ; ES:SI: Ptr to buffer (for data transfer commands) 30 ; DS:DI: Ptr to DPT (in RAMVARS segment) 31 ; SS:BP: Ptr to IDEREGS_AND_INTPACK 32 ; Returns: 33 ; AH: INT 13h Error Code 34 ; CF: Cleared if success, Set if error 35 ; Corrupts registers: 36 ; AL, BX, CX, DX, (ES:SI for data transfer commands) 37 ;-------------------------------------------------------------------- 38 ALIGN JUMP_ALIGN 39 SerialCommand_OutputWithParameters: 40 41 501 mov dx,[cs:bp+IDEVARS.wPortCtrl] 502 inc dx 503 dec dx 504 jz SerialCommand_AutoSerial 505 506 ; fall-through 507 SerialCommand_IdentifyDeviceInDL_DriveInBH: 508 509 push bp ; setup fake IDEREGS_AND_INTPACK 510 511 push dx 512 513 mov cl,1 ; 1 sector to move 514 push cx 515 516 mov bl,0a0h ; protocol command to ah and onto stack with bh 517 mov ah,bl 518 519 push bx 520 521 mov bp,sp 522 523 call SerialCommand_OutputWithParameters_DeviceInDL 524 525 pop bx 526 527 pop cx 528 pop dx 529 530 pop bp 531 532 ; place packed port/baud in vendor area of packet, read by FinalizeDPT 533 mov byte [es:si+SerialCommand_IdentifyDevice_PackedPortAndBaud], dl 534 535 ret 536 537 ;---------------------------------------------------------------------- 538 ; 539 ; SerialCommand_AutoSerial 540 ; 541 ; When the SerialAuto IDEVARS entry is used, scans the COM ports on the machine for a possible serial connection. 542 ; 543 544 SerialCommand_ScanPortAddresses: db 0b8h, 0f8h, 0bch, 0bah, 0fah, 0beh, 0feh, 0 545 ; Corresponds to I/O port: 3f8, 2f8, 3e8, 2e8, 2f0, 3e0, 2e0, 260, 368, 268, 360, 270 546 ; COM Assignments: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 547 548 ALIGN JUMP_ALIGN 549 SerialCommand_AutoSerial: 550 mov di,SerialCommand_ScanPortAddresses-1 551 552 .nextPort: 553 inc di ; load next port address 554 mov dl,[cs:di] 555 556 mov dh,0 ; shift from one byte to two 557 shl dx,1 558 shl dx,1 559 jz .exitNotFound 560 561 ; 562 ; Test for COM port presence, write to and read from registers 563 ; 564 push dx 565 add dl,SerialCommand_UART_lineControl 566 mov al, 09ah 567 out dx, al 568 in al, dx 569 pop dx 570 cmp al, 09ah 571 jnz .nextPort 572 573 mov al, 0ch 574 out dx, al 575 in al, dx 576 cmp al, 0ch 577 jnz .nextPort 578 579 ; 580 ; Pack into dl, baud rate starts at 0 581 ; 582 add dx,-(SerialCommand_PackedPortAndBaud_StartingPort) 583 shr dx,1 584 585 jmp .testFirstBaud 586 587 ; 588 ; Walk through 4 possible baud rates 589 ; 590 .nextBaud: 591 inc dx 592 test dl,3 593 jz .nextPort 594 595 .testFirstBaud: 596 call SerialCommand_IdentifyDeviceInDL_DriveInBH 597 jc .nextBaud 598 599 ret 600 601 .exitNotFound: 602 mov ah,1 603 stc 604 605 ret -
trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialDPT.asm
r150 r179 16 16 ;-------------------------------------------------------------------- 17 17 SerialDPT_Finalize: 18 or byte [di+DPT.bFlagsHigh], FLGH_DPT_SERIAL_DEVICE 19 mov al, byte [es:si+SerialCommand_IdentifyDevice_PackedPortAndBaud] 20 mov byte [ds:di+DPT.bSerialPortAndBaud], al 21 ret 22 23
Note:
See TracChangeset
for help on using the changeset viewer.