source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm@ 366

Last change on this file since 366 was 365, checked in by aitotat@…, 13 years ago

Changes to XTIDE Universal BIOS:

  • Errors from AH=9h are stored to DPTs again.
  • XT build fits in 8k again.
File size: 11.3 KB
RevLine 
[150]1; Project name : XTIDE Universal BIOS
2; Description : IDE Device transfer functions.
3
4; Structure containing variables for PIO transfer functions.
5; This struct must not be larger than IDEPACK without INTPACK.
6struc PIOVARS
[363]7 .wDataPort resb 2 ; 0, IDE Data Port
8 .fnXfer resb 2 ; 2, Offset to transfer function
9 .wSectorsInBlock resb 2 ; 4, Block size in sectors
10 .bSectorsLeft resb 1 ; 6, Sectors left to transfer
[218]11 resb 1 ; 7, IDEPACK.bDeviceControl
[363]12 .bSectorsDone resb 1 ; 8, Number of sectors xferred
[150]13endstruc
14
15
16; Section containing code
17SECTION .text
18
19;--------------------------------------------------------------------
20; IdeTransfer_StartWithCommandInAL
21; Parameters:
22; AL: IDE command that was used to start the transfer
[171]23; (all PIO read and write commands including Identify Device)
[218]24; ES:SI: Ptr to normalized data buffer
[150]25; DS:DI: Ptr to DPT (in RAMVARS segment)
26; SS:BP: Ptr to IDEPACK
27; Returns:
28; AH: INT 13h Error Code
[218]29; CX: Number of successfully transferred sectors
[150]30; CF: Cleared if success, Set if error
31; Corrupts registers:
[218]32; AL, BX, DX, SI, ES
[150]33;--------------------------------------------------------------------
34ALIGN JUMP_ALIGN
35IdeTransfer_StartWithCommandInAL:
[157]36 ; Are we reading or writing?
[171]37 test al, 16 ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
[242]38 mov ah, [bp+IDEPACK.bSectorCount]
39 jnz SHORT WriteToDrive
[171]40 cmp al, COMMAND_WRITE_MULTIPLE
[242]41 je SHORT WriteToDrive
42 ; Fall to ReadFromDrive
[150]43
44;--------------------------------------------------------------------
[242]45; ReadFromDrive
[150]46; Parameters:
[242]47; AH: Number of sectors to transfer (1...128)
48; ES:SI: Normalized ptr to buffer to receive data
[150]49; DS:DI: Ptr to DPT (in RAMVARS segment)
50; SS:BP: Ptr to PIOVARS
51; Returns:
[242]52; DS:DI: Ptr to DPT (in RAMVARS segment)
[150]53; AH: BIOS Error code
[218]54; CX: Number of successfully transferred sectors
[294]55; CF: 0 if transfer successful
[150]56; 1 if any error
57; Corrupts registers:
[218]58; AL, BX, DX, SI, ES
[150]59;--------------------------------------------------------------------
[242]60ReadFromDrive:
61 ; Prepare to read data to ESSI
62 mov bx, g_rgfnPioRead
63 call InitializePiovarsInSSBPwithSectorCountInAH
64
65 ; Wait until drive is ready to transfer
66 call IdeWait_IRQorDRQ ; Wait until ready to transfer
[218]67 jc SHORT ReturnWithTransferErrorInAH
[242]68 xchg si, di ; ES:DI now points buffer
[218]69
[363]70 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
[242]71
[150]72ALIGN JUMP_ALIGN
[242]73.ReadNextBlockFromDrive:
[150]74 mov dx, [bp+PIOVARS.wDataPort]
[363]75 cmp [bp+PIOVARS.bSectorsLeft], cl
[242]76 jbe SHORT .ReadLastBlockFromDrive
[218]77 call [bp+PIOVARS.fnXfer]
[169]78
[218]79 ; Wait until ready for next block and check for errors
[242]80 xchg di, si ; DS:DI now points DPT
[218]81 call IdeWait_IRQorDRQ ; Wait until ready to transfer
82 jc SHORT ReturnWithTransferErrorInAH
[242]83 xchg si, di ; ES:DI now points buffer
[169]84
[363]85 ; Increment number of successfully read sectors
86 mov cx, [bp+PIOVARS.wSectorsInBlock]
87 sub [bp+PIOVARS.bSectorsLeft], cl
88 add [bp+PIOVARS.bSectorsDone], cl
[242]89 jmp SHORT .ReadNextBlockFromDrive
[150]90
91ALIGN JUMP_ALIGN
[242]92.ReadLastBlockFromDrive:
[363]93 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
[150]94 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
95
[242]96 ; Check for errors in last block
97 mov di, si ; DS:DI now points DPT
98CheckErrorsAfterTransferringLastBlock:
99 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
100 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[150]101
[242]102 ; Return number of successfully read sectors
103ReturnWithTransferErrorInAH:
[363]104 mov cl, [bp+PIOVARS.bSectorsDone]
105 mov ch, 0 ; Preserve CF
[242]106 ret
107
108
[150]109;--------------------------------------------------------------------
[242]110; WriteToDrive
[150]111; Parameters:
[242]112; AH: Number of sectors to transfer (1...128)
113; DS:DI: Ptr to DPT (in RAMVARS segment)
114; ES:SI: Normalized ptr to buffer containing data
[150]115; SS:BP: Ptr to PIOVARS
116; Returns:
117; AH: BIOS Error code
[218]118; CX: Number of successfully transferred sectors
[294]119; CF: 0 if transfer successful
[150]120; 1 if any error
121; Corrupts registers:
[218]122; AL, BX, DX, SI, ES
[150]123;--------------------------------------------------------------------
124ALIGN JUMP_ALIGN
[242]125WriteToDrive:
126 ; Prepare to write data from ESSI
127 mov bx, g_rgfnPioWrite
128 call InitializePiovarsInSSBPwithSectorCountInAH
129
130 ; Always poll when writing first block (IRQs are generated for following blocks)
131 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
132 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[218]133 jc SHORT ReturnWithTransferErrorInAH
[150]134
[363]135 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
[242]136
[218]137ALIGN JUMP_ALIGN
[242]138.WriteNextBlockToDrive:
[150]139 mov dx, [bp+PIOVARS.wDataPort]
[363]140 cmp [bp+PIOVARS.bSectorsLeft], cl
[242]141 jbe SHORT .WriteLastBlockToDrive
[218]142 call [bp+PIOVARS.fnXfer]
[169]143
[218]144 ; Wait until ready for next block and check for errors
145 call IdeWait_IRQorDRQ ; Wait until ready to transfer
146 jc SHORT ReturnWithTransferErrorInAH
[150]147
[363]148 ; Increment number of successfully written sectors
149 mov cx, [bp+PIOVARS.wSectorsInBlock]
150 sub [bp+PIOVARS.bSectorsLeft], cl
151 add [bp+PIOVARS.bSectorsDone], cl
[242]152 jmp SHORT .WriteNextBlockToDrive
[169]153
[150]154ALIGN JUMP_ALIGN
[242]155.WriteLastBlockToDrive:
[363]156 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
[242]157%ifdef USE_186
158 push CheckErrorsAfterTransferringLastBlock
159 jmp [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
160%else
[150]161 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
[242]162 jmp SHORT CheckErrorsAfterTransferringLastBlock
163%endif
[218]164
[150]165
166;--------------------------------------------------------------------
[218]167; InitializePiovarsInSSBPwithSectorCountInAH
[150]168; Parameters:
[218]169; AH: Number of sectors to transfer (1...128)
[150]170; BX: Offset to transfer function lookup table
171; DS:DI: Ptr to DPT (in RAMVARS segment)
[169]172; SS:BP: Ptr to PIOVARS
[167]173; Returns:
[169]174; Nothing
[150]175; Corrupts registers:
[242]176; AX, BX, DX
[150]177;--------------------------------------------------------------------
178ALIGN JUMP_ALIGN
[218]179InitializePiovarsInSSBPwithSectorCountInAH:
180 ; Store sizes
[363]181 mov [bp+PIOVARS.bSectorsLeft], ah
[365]182 eMOVZX ax, BYTE [di+DPT_ATA.bBlockSize]
[363]183 mov [bp+PIOVARS.wSectorsInBlock], ax
184 mov [bp+PIOVARS.bSectorsDone], ah ; Zero
[150]185
186 ; Get transfer function based on bus type
[158]187 xchg ax, bx ; Lookup table offset to AX
[242]188 mov bl, [di+DPT.bIdevarsOffset] ; CS:BX now points to IDEVARS
[150]189 mov dx, [cs:bx+IDEVARS.wPort] ; Load IDE Data port address
[363]190%ifdef MODULE_ADVANCED_ATA
[364]191 mov bl, [di+DPT_ADVANCED_ATA.bDevice]
[363]192%else
[150]193 mov bl, [cs:bx+IDEVARS.bDevice] ; Load device type to BX
[363]194%endif
[150]195 add bx, ax
[363]196
[242]197 mov [bp+PIOVARS.wDataPort], dx
[150]198 mov ax, [cs:bx] ; Load offset to transfer function
199 mov [bp+PIOVARS.fnXfer], ax
200 ret
201
202
203;--------------------------------------------------------------------
[361]204; ReadBlockFromXtideRev1 XTIDE rev 1
205; ReadBlockFromXtideRev2 XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
206; ReadBlockFrom16bitDataPort Normal 16-bit IDE
207; ReadBlockFrom32bitDataPort VLB/PCI 32-bit IDE
[150]208; Parameters:
[363]209; CX: Block size in 512 byte sectors
[150]210; DX: IDE Data port address
[242]211; ES:DI: Normalized ptr to buffer to receive data
[150]212; Returns:
213; Nothing
214; Corrupts registers:
215; AX, BX, CX
216;--------------------------------------------------------------------
217ALIGN JUMP_ALIGN
[361]218ReadBlockFromXtideRev1:
[363]219 UNROLL_SECTORS_IN_CX_TO_QWORDS
[152]220 mov bx, 8 ; Bit mask for toggling data low/high reg
[150]221ALIGN JUMP_ALIGN
222.InswLoop:
[152]223 XTIDE_INSW
224 XTIDE_INSW
225 XTIDE_INSW
226 XTIDE_INSW
[150]227 loop .InswLoop
228 ret
229
[361]230;--------------------------------------------------------------------
231%ifndef USE_186 ; 8086/8088 compatible WORD read
[150]232ALIGN JUMP_ALIGN
[361]233ReadBlockFromXtideRev2:
[363]234 UNROLL_SECTORS_IN_CX_TO_QWORDS
[152]235ALIGN JUMP_ALIGN
236.ReadNextQword:
237 in ax, dx ; Read 1st WORD
238 stosw ; Store 1st WORD to [ES:DI]
239 in ax, dx
240 stosw ; 2nd
241 in ax, dx
242 stosw ; 3rd
243 in ax, dx
244 stosw ; 4th
245 loop .ReadNextQword
246 ret
247%endif
[150]248
[361]249;--------------------------------------------------------------------
[152]250ALIGN JUMP_ALIGN
[361]251ReadBlockFrom16bitDataPort:
[363]252 xchg cl, ch ; Sectors to WORDs
[152]253 rep
254 db 6Dh ; INSW (we want this in XT build)
255 ret
256
[361]257;--------------------------------------------------------------------
[152]258ALIGN JUMP_ALIGN
[361]259ReadBlockFrom32bitDataPort:
[363]260 db 0C1h ; SHL
261 db 0E1h ; CX
262 db 7 ; 7 (Sectors to DWORDs)
[152]263 rep
264 db 66h ; Override operand size to 32-bit
265 db 6Dh ; INSW/INSD
266 ret
267
268
[150]269;--------------------------------------------------------------------
[361]270; WriteBlockToXtideRev1 XTIDE rev 1
271; WriteBlockToXtideRev2 XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
272; WriteBlockToFastXtide Fast XTIDE (CPLD v2 project)
273; WriteBlockTo16bitDataPort Normal 16-bit IDE
274; WriteBlockTo32bitDataPort VLB/PCI 32-bit IDE
[150]275; Parameters:
[363]276; CX: Block size in 512-byte sectors
[150]277; DX: IDE Data port address
278; ES:SI: Normalized ptr to buffer containing data
279; Returns:
280; Nothing
281; Corrupts registers:
282; AX, CX
283;--------------------------------------------------------------------
284ALIGN JUMP_ALIGN
[361]285WriteBlockToXtideRev1:
[150]286 push ds
287 push bx
[363]288 UNROLL_SECTORS_IN_CX_TO_QWORDS
[152]289 mov bx, 8 ; Bit mask for toggling data low/high reg
290 push es ; Copy ES...
291 pop ds ; ...to DS
[150]292ALIGN JUMP_ALIGN
293.OutswLoop:
[152]294 XTIDE_OUTSW
295 XTIDE_OUTSW
296 XTIDE_OUTSW
297 XTIDE_OUTSW
[150]298 loop .OutswLoop
299 pop bx
300 pop ds
301 ret
302
[361]303;--------------------------------------------------------------------
[150]304ALIGN JUMP_ALIGN
[361]305WriteBlockToXtideRev2:
[363]306 UNROLL_SECTORS_IN_CX_TO_QWORDS
[152]307 push ds
308 push es ; Copy ES...
309 pop ds ; ...to DS
310ALIGN JUMP_ALIGN
311.WriteNextQword:
312 XTIDE_MOD_OUTSW
313 XTIDE_MOD_OUTSW
314 XTIDE_MOD_OUTSW
315 XTIDE_MOD_OUTSW
316 loop .WriteNextQword
317 pop ds
318 ret
[150]319
[361]320;--------------------------------------------------------------------
321%ifndef USE_186 ; 8086/8088 compatible WORD write
[152]322ALIGN JUMP_ALIGN
[361]323WriteBlockToFastXtide:
[363]324 UNROLL_SECTORS_IN_CX_TO_QWORDS
[361]325 push ds
326 push es
327 pop ds
328ALIGN JUMP_ALIGN
329.ReadNextQword:
330 lodsw ; Load 1st WORD from [DS:SI]
331 out dx, ax ; Write 1st WORD
332 lodsw
333 out dx, ax ; 2nd
334 lodsw
335 out dx, ax ; 3rd
336 lodsw
337 out dx, ax ; 4th
338 loop .ReadNextQword
339 pop ds
340 ret
341%endif
342
343;--------------------------------------------------------------------
344ALIGN JUMP_ALIGN
345WriteBlockTo16bitDataPort:
[363]346 xchg cl, ch ; Sectors to WORDs
[223]347 es ; Source is ES segment
[152]348 rep
[155]349 db 6Fh ; OUTSW (we want this in XT build)
[152]350 ret
351
[361]352;--------------------------------------------------------------------
[152]353ALIGN JUMP_ALIGN
[361]354WriteBlockTo32bitDataPort:
[363]355 db 0C1h ; SHL
356 db 0E1h ; CX
357 db 7 ; 7 (Sectors to DWORDs)
[223]358 es ; Source is ES segment
[152]359 rep
360 db 66h ; Override operand size to 32-bit
361 db 6Fh ; OUTSW/OUTSD
362 ret
363
364
[361]365
[150]366; Lookup tables to get transfer function based on bus type
367ALIGN WORD_ALIGN
368g_rgfnPioRead:
[361]369 dw ReadBlockFromXtideRev1 ; DEVICE_XTIDE_REV1
[152]370%ifdef USE_186
[361]371 dw ReadBlockFrom16bitDataPort ; DEVICE_XTIDE_REV2
372 dw ReadBlockFrom16bitDataPort ; DEVICE_FAST_XTIDE
[152]373%else
[361]374 dw ReadBlockFromXtideRev2 ; DEVICE_XTIDE_REV2
375 dw ReadBlockFromXtideRev2 ; DEVICE_FAST_XTIDE
[152]376%endif
[361]377 dw ReadBlockFrom16bitDataPort ; DEVICE_16BIT_ATA
378 dw ReadBlockFrom32bitDataPort ; DEVICE_32BIT_ATA
[152]379
[150]380g_rgfnPioWrite:
[361]381 dw WriteBlockToXtideRev1 ; DEVICE_XTIDE_REV1
382 dw WriteBlockToXtideRev2 ; DEVICE_XTIDE_REV2
383%ifdef USE_186
384 dw WriteBlockTo16bitDataPort ; DEVICE_FAST_XTIDE
385%else
386 dw WriteBlockToFastXtide ; DEVICE_FAST_XTIDE
387%endif
388 dw WriteBlockTo16bitDataPort ; DEVICE_16BIT_ATA
389 dw WriteBlockTo32bitDataPort ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.