Changeset 214 in xtideuniversalbios
- Timestamp:
- Jan 18, 2012, 9:03:22 AM (13 years ago)
- google:author:
- gregli@hotmail.com
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/XTIDE_Universal_BIOS/Src/Device/Serial/SerialCommand.asm
r208 r214 111 111 ; Baud in CH until UART initialization is complete 112 112 ; 113 mov dh, ((DEVICE_SERIAL_PACKEDPORTANDBAUD_STARTINGPORT & 0f00h) >> (8+1)) 114 shl dx, 1 ; port offset already x4, needs one more shift to be x8 113 115 mov cl, dl 114 116 115 and cl, DEVICE_SERIAL_PACKEDPORTANDBAUD_BAUDMASK 116 shl cl, 1 117 and cl, (DEVICE_SERIAL_PACKEDPORTANDBAUD_BAUDMASK << 1) 117 118 mov ch, SerialCommand_UART_divisorLow_startingBaud 118 119 shr ch, cl 119 120 adc ch, 0 120 121 121 and dl, DEVICE_SERIAL_PACKEDPORTANDBAUD_PORTMASK 122 mov dh, 0 123 shl dx, 1 ; port offset already x4, needs one more shift to be x8 124 add dx, DEVICE_SERIAL_PACKEDPORTANDBAUD_STARTINGPORT 125 126 ; 127 ; Buffer is referenced through ES:DI throughout, since we need to store faster than we read 128 ; 129 mov di,si 122 and dl, ((DEVICE_SERIAL_PACKEDPORTANDBAUD_PORTMASK << 1) & 0ffh) 123 add dx, byte (DEVICE_SERIAL_PACKEDPORTANDBAUD_STARTINGPORT & 0ffh) 130 124 131 125 mov al,[bp+IDEPACK.bSectorCount] … … 145 139 ; decided to reprogram the UART 146 140 ; 147 push dx148 141 mov bl,dl ; setup BL with proper values for read/write loops (BH comes later) 142 149 143 mov al,83h 150 144 add dl,SerialCommand_UART_lineControl … … 152 146 153 147 mov al,ch 154 pop dx; divisor low148 mov dl,bl ; divisor low 155 149 out dx,al 156 150 … … 172 166 out dx,al 173 167 168 inc dx ; linestatus (no output now, just setting up BH for later use) 169 mov bh,dl 170 174 171 pop dx ; base, interrupts disabled 175 172 xor ax,ax 176 173 out dx,al 177 dec dx178 179 ;180 ; Start off with a normalized buffer pointer181 ;182 call Registers_NormalizeESDI183 174 184 175 ;---------------------------------------------------------------------- … … 189 180 ; 190 181 push es ; save off real buffer location 191 push di192 193 mov di,bp ; point to IDEREGS for command dispatch;182 push si 183 184 mov si,bp ; point to IDEREGS for command dispatch; 194 185 push ss 195 186 pop es 196 187 197 xor si,si ; initialize checksum for write 198 dec si 199 mov bp,si 200 201 mov bl,03h ; writing 3 words 202 203 call SerialCommand_WriteProtocol 204 205 pop di ; restore real buffer location 188 mov di,0ffffh ; initialize checksum for write 189 mov bp,di 190 191 mov cx,4 ; writing 3 words (plus 1) 192 193 cli ; interrupts off... 194 195 call SerialCommand_WriteProtocol.entry 196 197 pop di ; restore real buffer location (note change from SI to DI) 198 ; Buffer is primarily referenced through ES:DI throughout, since 199 ; we need to store (read sector) faster than we read (write sector) 206 200 pop es 207 201 202 .nextSectorNormalize: 203 204 call Registers_NormalizeESDI 205 208 206 pop ax ; load command byte (done before call to .nextSector on subsequent iterations) 209 207 push ax … … 213 211 ; 214 212 .nextSector: 215 xor si,si ; initialize checksum for read or write 216 dec si 213 mov si,0ffffh ; initialize checksum for read or write 217 214 mov bp,si 218 215 219 mov bx,0100h216 mov cx,0101h ; writing 256 words (plus 1) 220 217 221 218 shr ah,1 ; command byte, are we doing a write? 222 jnc .readSector 223 call SerialCommand_WriteProtocol 224 225 xor bx,bx 226 227 .readSector: 228 mov cx,bx 229 inc cx 230 231 mov bl,dl ; setup bl with proper values for read loop (bh comes later) 219 jnc .readEntry 220 221 xchg si,di 222 call SerialCommand_WriteProtocol.entry 223 xchg si,di 224 225 inc cx ; CX = 1 now (0 out of WriteProtocol) 226 jmp .readEntry 232 227 233 228 ;---------------------------------------------------------------------- … … 235 230 ; Timeout 236 231 ; 237 ; During read, we first poll in a tight loop, interrupts off, for the next character to come in238 ; If that loop completes, then we assume there is a long delay involved, turn interrupts back on239 ; and wait for a given number of timer ticks to pass.240 ;241 232 ; To save code space, we use the contents of DL to decide which byte in the word to return for reading. 242 233 ; 243 234 .readTimeout: 244 push cx 245 xor cx,cx 246 .readTimeoutLoop: 247 push dx 248 or dl,SerialCommand_UART_lineStatus 249 in al,dx 250 pop dx 251 shr al,1 252 jc .readTimeoutComplete 253 loop .readTimeoutLoop 254 sti 255 mov bh,1 256 call SerialCommand_WaitAndPoll_Init 257 cli 258 .readTimeoutComplete: 259 mov bh,bl 260 or bh,SerialCommand_UART_lineStatus 261 262 pop cx 235 push ax ; not only does this push preserve AX (which we need), but it also 236 ; means the stack has the same number of bytes on it as when we are 237 ; sending a packet, important for error cleanup and exit 238 mov ah,1 239 call SerialCommand_WaitAndPoll_Read 240 pop ax 263 241 test dl,1 264 242 jz .readByte1Ready 265 jmp .readByte2Ready 243 jmp .readByte2Ready 266 244 267 245 ;---------------------------------------------------------------------------- … … 282 260 adc si, 0 283 261 262 .readEntry: 284 263 mov dl,bh 285 264 in al,dx … … 317 296 loop .readLoop 318 297 319 sti ; interrupts back on ASAP, if we turned them off298 sti ; interrupts back on ASAP, between packets 320 299 321 300 ; … … 330 309 jnz SerialCommand_OutputWithParameters_Error 331 310 332 ;333 ; Normalize buffer pointer for next go round, if needed334 ;335 test di,di336 jns .clearBuffer337 call Registers_NormalizeESDI338 339 311 ;---------------------------------------------------------------------- 340 312 ; … … 345 317 ; taken care of this, but I have seen cases where this is not true. 346 318 ; 347 348 319 .clearBuffer: 349 320 mov dl,bh … … 368 339 out dx,al ; ACK with next sector number 369 340 370 jmp .nextSector ; all is well, time for next sector 341 ; 342 ; Normalize buffer pointer for next go round, if needed 343 ; 344 test di,di 345 jns short .nextSector 346 jmp short .nextSectorNormalize 371 347 372 348 ;--------------------------------------------------------------------------- … … 378 354 ; Used in situations where a call is underway, such as with SerialCommand_WaitAndPoll 379 355 ; 380 SerialCommand_OutputWithParameters_ErrorAndPop2Words: 381 pop ax 382 pop ax 383 356 ALIGN JUMP_ALIGN 357 SerialCommand_OutputWithParameters_ErrorAndPop4Words: 358 add sp,8 359 360 ALIGN JUMP_ALIGN 384 361 SerialCommand_OutputWithParameters_Error: 385 362 stc 386 363 mov al,1 387 364 365 ALIGN JUMP_ALIGN 388 366 SerialCommand_OutputWithParameters_ReturnCodeInALCF: 389 367 sti 390 368 mov ah,al 391 369 392 pop bp ; recover ax from stack, throw away370 pop bp ; recover ax (command and count) from stack, throw away 393 371 394 372 pop es … … 400 378 401 379 ;-------------------------------------------------------------------- 380 ; SerialCommand_WriteProtocol 381 ; 382 ; NOTE: As with its read counterpart, this loop is very time sensitive. 383 ; Although it will still function, adding additional instructions will 384 ; impact the write througput, especially on slower machines. 385 ; 386 ; Parameters: 387 ; ES:SI: Ptr to buffer 388 ; CX: Words to write, plus 1 389 ; BP/DI: Initialized for Checksum (-1 in each) 390 ; DH: I/O Port high byte 391 ; BX: LineStatus Register address (BH) and Receive/Transmit Register address (BL) 392 ; Returns: 393 ; BP/DI: Checksum for written bytes, compared against ACK from server in .readLoop 394 ; CX: Zero 395 ; DL: Receive/Transmit Register address 396 ; Corrupts registers: 397 ; AX 398 ;-------------------------------------------------------------------- 399 ALIGN JUMP_ALIGN 400 SerialCommand_WriteProtocol: 401 .writeLoop: 402 es lodsw ; fetch next word 403 404 out dx,al ; output first byte 405 406 add bp,ax ; update checksum 407 adc bp,0 408 add di,bp 409 adc di,0 410 411 mov dl,bh ; transmit buffer empty? 412 in al,dx 413 test al,20h 414 jz .writeTimeout2 ; nope, use our polling routine 415 416 .writeByte2Ready: 417 mov dl,bl 418 mov al,ah ; output second byte 419 out dx,al 420 421 .entry: 422 mov dl,bh ; transmit buffer empty? 423 in al,dx 424 test al,20h 425 mov dl,bl 426 jz .writeTimeout1 ; nope, use our polling routine 427 428 .writeByte1Ready: 429 loop .writeLoop 430 431 mov ax,di ; fold Fletcher's checksum and output 432 xor al,ah 433 out dx,al ; byte 1 434 435 call SerialCommand_WaitAndPoll_Write 436 437 mov ax,bp 438 xor al,ah 439 out dx,al ; byte 2 440 441 ret 442 443 .writeTimeout2: 444 mov dl,ah ; need to preserve AH, but don't need DL (will be reset upon return) 445 call SerialCommand_WaitAndPoll_Write 446 mov ah,dl 447 jmp .writeByte2Ready 448 449 .writeTimeout1: 450 mov ax,.writeByte1Ready 451 push ax ; return address for ret at end of SC_writeTimeout2 452 ;;; fall-through 453 454 ;-------------------------------------------------------------------- 402 455 ; SerialCommand_WaitAndPoll 403 456 ; 404 457 ; Parameters: 405 ; BH: UART_LineStatus bit to test (20h for write, or 1h for read) 458 ; AH: UART_LineStatus bit to test (20h for write, or 1h for read) 459 ; One entry point fills in AH with 20h for write 406 460 ; DX: Port address (OK if already incremented to UART_lineStatus) 461 ; BX: 407 462 ; Stack: 2 words on the stack below the command/count word 408 463 ; Returns: … … 410 465 ; Jumps directly to error exit if timeout elapses (and cleans up stack) 411 466 ; Corrupts registers: 412 ; CX, flags467 ; AX 413 468 ;-------------------------------------------------------------------- 414 469 … … 416 471 417 472 ALIGN JUMP_ALIGN 418 SerialCommand_WaitAndPoll_Init: 473 SerialCommand_WaitAndPoll_Write: 474 mov ah,20h 475 ;;; fall-through 476 477 ALIGN JUMP_ALIGN 478 SerialCommand_WaitAndPoll_Read: 479 push cx 480 push dx 481 482 ; 483 ; We first poll in a tight loop, interrupts off, for the next character to come in/be sent 484 ; 485 xor cx,cx 486 .readTimeoutLoop: 487 mov dl,bh 488 in al,dx 489 test al,ah 490 jnz .readTimeoutComplete 491 loop .readTimeoutLoop 492 493 ; 494 ; If that loop completes, then we assume there is a long delay involved, turn interrupts back on 495 ; and wait for a given number of timer ticks to pass. 496 ; 497 sti 419 498 mov cl,SerialCommand_WaitAndPoll_SoftDelayTicks 420 499 call Timer_InitializeTimeoutWithTicksInCL 421 ; fall-through 422 423 SerialCommand_WaitAndPoll: 500 .WaitAndPoll: 424 501 call Timer_SetCFifTimeout 425 jc SerialCommand_OutputWithParameters_ErrorAndPop2Words 426 push dx 427 push ax 428 or dl,SerialCommand_UART_lineStatus 502 jc SerialCommand_OutputWithParameters_ErrorAndPop4Words 429 503 in al,dx 430 test al,bh 431 pop ax 504 test al,ah 505 jz .WaitAndPoll 506 cli 507 508 .readTimeoutComplete: 432 509 pop dx 433 jz SerialCommand_WaitAndPoll 434 ; fall-through 435 436 SerialCommand_WaitAndPoll_Done: 510 pop cx 437 511 ret 438 439 ;--------------------------------------------------------------------440 ; SerialCommand_WriteProtocol441 ;442 ; Parameters:443 ; ES:DI: Ptr to buffer444 ; BL: Words to write (1-255, or 0=256)445 ; BP/SI: Initialized for Checksum (-1 in each)446 ; DX: I/O Port447 ; Returns:448 ; BP/SI: Checksum for written bytes, compared against ACK from server in .readLoop449 ; Corrupts registers:450 ; AX, BX, CX, DI451 ;--------------------------------------------------------------------452 ALIGN JUMP_ALIGN453 SerialCommand_WriteProtocol:454 mov bh,20h455 456 .writeLoop:457 test bh,1458 jnz SerialCommand_WaitAndPoll_Done459 460 mov ax,[es:di] ; fetch next word461 inc di462 inc di463 464 add bp,ax ; update checksum465 adc bp,0466 add si,bp467 adc si,0468 469 .writeLoopChecksum:470 call SerialCommand_WaitAndPoll_Init471 472 out dx,al ; output first byte473 474 call SerialCommand_WaitAndPoll475 476 mov al,ah ; output second byte477 out dx,al478 479 dec bl480 jnz .writeLoop481 482 inc bh483 484 mov ax,bp ; merge checksum for possible write (last loop)485 xor ah,al486 mov cx,si487 xor cl,ch488 mov al,cl489 490 jmp .writeLoopChecksum491 492 512 493 513 ;--------------------------------------------------------------------
Note:
See TracChangeset
for help on using the changeset viewer.