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

Last change on this file since 375 was 370, checked in by krille_n_@…, 13 years ago

Changes:

  • Added some missing PIO mode timings to ATA_ID.inc (based on info from http://www.singlix.net/specs/cfspc4_0.pdf)
  • Updated Configuration_FullMode.txt but it may need additional changes as the Tandy info doesn't match the wiki.
  • Optimizations.
  • Excluded some unused code from XTIDECFG.
File size: 11.4 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:
[370]104%ifdef USE_386
105 movzx cx, [bp+PIOVARS.bSectorsDone]
106%else
[363]107 mov cl, [bp+PIOVARS.bSectorsDone]
108 mov ch, 0 ; Preserve CF
[370]109%endif
[242]110 ret
111
112
[150]113;--------------------------------------------------------------------
[242]114; WriteToDrive
[150]115; Parameters:
[242]116; AH: Number of sectors to transfer (1...128)
117; DS:DI: Ptr to DPT (in RAMVARS segment)
118; ES:SI: Normalized ptr to buffer containing data
[150]119; SS:BP: Ptr to PIOVARS
120; Returns:
121; AH: BIOS Error code
[218]122; CX: Number of successfully transferred sectors
[294]123; CF: 0 if transfer successful
[150]124; 1 if any error
125; Corrupts registers:
[218]126; AL, BX, DX, SI, ES
[150]127;--------------------------------------------------------------------
128ALIGN JUMP_ALIGN
[242]129WriteToDrive:
130 ; Prepare to write data from ESSI
131 mov bx, g_rgfnPioWrite
132 call InitializePiovarsInSSBPwithSectorCountInAH
133
134 ; Always poll when writing first block (IRQs are generated for following blocks)
135 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
136 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[218]137 jc SHORT ReturnWithTransferErrorInAH
[150]138
[363]139 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
[242]140
[218]141ALIGN JUMP_ALIGN
[242]142.WriteNextBlockToDrive:
[150]143 mov dx, [bp+PIOVARS.wDataPort]
[363]144 cmp [bp+PIOVARS.bSectorsLeft], cl
[242]145 jbe SHORT .WriteLastBlockToDrive
[218]146 call [bp+PIOVARS.fnXfer]
[169]147
[218]148 ; Wait until ready for next block and check for errors
149 call IdeWait_IRQorDRQ ; Wait until ready to transfer
150 jc SHORT ReturnWithTransferErrorInAH
[150]151
[363]152 ; Increment number of successfully written sectors
153 mov cx, [bp+PIOVARS.wSectorsInBlock]
154 sub [bp+PIOVARS.bSectorsLeft], cl
155 add [bp+PIOVARS.bSectorsDone], cl
[242]156 jmp SHORT .WriteNextBlockToDrive
[169]157
[150]158ALIGN JUMP_ALIGN
[242]159.WriteLastBlockToDrive:
[363]160 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
[242]161%ifdef USE_186
162 push CheckErrorsAfterTransferringLastBlock
163 jmp [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
164%else
[150]165 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
[242]166 jmp SHORT CheckErrorsAfterTransferringLastBlock
167%endif
[218]168
[150]169
170;--------------------------------------------------------------------
[218]171; InitializePiovarsInSSBPwithSectorCountInAH
[150]172; Parameters:
[218]173; AH: Number of sectors to transfer (1...128)
[150]174; BX: Offset to transfer function lookup table
175; DS:DI: Ptr to DPT (in RAMVARS segment)
[169]176; SS:BP: Ptr to PIOVARS
[167]177; Returns:
[169]178; Nothing
[150]179; Corrupts registers:
[242]180; AX, BX, DX
[150]181;--------------------------------------------------------------------
182ALIGN JUMP_ALIGN
[218]183InitializePiovarsInSSBPwithSectorCountInAH:
184 ; Store sizes
[363]185 mov [bp+PIOVARS.bSectorsLeft], ah
[370]186 eMOVZX ax, [di+DPT_ATA.bBlockSize]
[363]187 mov [bp+PIOVARS.wSectorsInBlock], ax
188 mov [bp+PIOVARS.bSectorsDone], ah ; Zero
[150]189
190 ; Get transfer function based on bus type
[158]191 xchg ax, bx ; Lookup table offset to AX
[242]192 mov bl, [di+DPT.bIdevarsOffset] ; CS:BX now points to IDEVARS
[150]193 mov dx, [cs:bx+IDEVARS.wPort] ; Load IDE Data port address
[363]194%ifdef MODULE_ADVANCED_ATA
[364]195 mov bl, [di+DPT_ADVANCED_ATA.bDevice]
[363]196%else
[150]197 mov bl, [cs:bx+IDEVARS.bDevice] ; Load device type to BX
[363]198%endif
[150]199 add bx, ax
[363]200
[242]201 mov [bp+PIOVARS.wDataPort], dx
[150]202 mov ax, [cs:bx] ; Load offset to transfer function
203 mov [bp+PIOVARS.fnXfer], ax
204 ret
205
206
207;--------------------------------------------------------------------
[361]208; ReadBlockFromXtideRev1 XTIDE rev 1
209; ReadBlockFromXtideRev2 XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
210; ReadBlockFrom16bitDataPort Normal 16-bit IDE
211; ReadBlockFrom32bitDataPort VLB/PCI 32-bit IDE
[150]212; Parameters:
[363]213; CX: Block size in 512 byte sectors
[150]214; DX: IDE Data port address
[242]215; ES:DI: Normalized ptr to buffer to receive data
[150]216; Returns:
217; Nothing
218; Corrupts registers:
219; AX, BX, CX
220;--------------------------------------------------------------------
221ALIGN JUMP_ALIGN
[361]222ReadBlockFromXtideRev1:
[363]223 UNROLL_SECTORS_IN_CX_TO_QWORDS
[370]224 mov bl, 8 ; Bit mask for toggling data low/high reg
[150]225ALIGN JUMP_ALIGN
226.InswLoop:
[152]227 XTIDE_INSW
228 XTIDE_INSW
229 XTIDE_INSW
230 XTIDE_INSW
[150]231 loop .InswLoop
232 ret
233
[361]234;--------------------------------------------------------------------
235%ifndef USE_186 ; 8086/8088 compatible WORD read
[150]236ALIGN JUMP_ALIGN
[361]237ReadBlockFromXtideRev2:
[363]238 UNROLL_SECTORS_IN_CX_TO_QWORDS
[152]239ALIGN JUMP_ALIGN
240.ReadNextQword:
241 in ax, dx ; Read 1st WORD
242 stosw ; Store 1st WORD to [ES:DI]
243 in ax, dx
244 stosw ; 2nd
245 in ax, dx
246 stosw ; 3rd
247 in ax, dx
248 stosw ; 4th
249 loop .ReadNextQword
250 ret
251%endif
[150]252
[361]253;--------------------------------------------------------------------
[152]254ALIGN JUMP_ALIGN
[361]255ReadBlockFrom16bitDataPort:
[363]256 xchg cl, ch ; Sectors to WORDs
[152]257 rep
258 db 6Dh ; INSW (we want this in XT build)
259 ret
260
[361]261;--------------------------------------------------------------------
[152]262ALIGN JUMP_ALIGN
[361]263ReadBlockFrom32bitDataPort:
[363]264 db 0C1h ; SHL
265 db 0E1h ; CX
266 db 7 ; 7 (Sectors to DWORDs)
[152]267 rep
268 db 66h ; Override operand size to 32-bit
269 db 6Dh ; INSW/INSD
270 ret
271
272
[150]273;--------------------------------------------------------------------
[361]274; WriteBlockToXtideRev1 XTIDE rev 1
275; WriteBlockToXtideRev2 XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
276; WriteBlockToFastXtide Fast XTIDE (CPLD v2 project)
277; WriteBlockTo16bitDataPort Normal 16-bit IDE
278; WriteBlockTo32bitDataPort VLB/PCI 32-bit IDE
[150]279; Parameters:
[363]280; CX: Block size in 512-byte sectors
[150]281; DX: IDE Data port address
282; ES:SI: Normalized ptr to buffer containing data
283; Returns:
284; Nothing
285; Corrupts registers:
286; AX, CX
287;--------------------------------------------------------------------
288ALIGN JUMP_ALIGN
[361]289WriteBlockToXtideRev1:
[150]290 push ds
291 push bx
[363]292 UNROLL_SECTORS_IN_CX_TO_QWORDS
[370]293 mov bl, 8 ; Bit mask for toggling data low/high reg
[152]294 push es ; Copy ES...
295 pop ds ; ...to DS
[150]296ALIGN JUMP_ALIGN
297.OutswLoop:
[152]298 XTIDE_OUTSW
299 XTIDE_OUTSW
300 XTIDE_OUTSW
301 XTIDE_OUTSW
[150]302 loop .OutswLoop
303 pop bx
304 pop ds
305 ret
306
[361]307;--------------------------------------------------------------------
[150]308ALIGN JUMP_ALIGN
[361]309WriteBlockToXtideRev2:
[363]310 UNROLL_SECTORS_IN_CX_TO_QWORDS
[152]311 push ds
312 push es ; Copy ES...
313 pop ds ; ...to DS
314ALIGN JUMP_ALIGN
315.WriteNextQword:
316 XTIDE_MOD_OUTSW
317 XTIDE_MOD_OUTSW
318 XTIDE_MOD_OUTSW
319 XTIDE_MOD_OUTSW
320 loop .WriteNextQword
321 pop ds
322 ret
[150]323
[361]324;--------------------------------------------------------------------
325%ifndef USE_186 ; 8086/8088 compatible WORD write
[152]326ALIGN JUMP_ALIGN
[361]327WriteBlockToFastXtide:
[363]328 UNROLL_SECTORS_IN_CX_TO_QWORDS
[361]329 push ds
330 push es
331 pop ds
332ALIGN JUMP_ALIGN
333.ReadNextQword:
334 lodsw ; Load 1st WORD from [DS:SI]
335 out dx, ax ; Write 1st WORD
336 lodsw
337 out dx, ax ; 2nd
338 lodsw
339 out dx, ax ; 3rd
340 lodsw
341 out dx, ax ; 4th
342 loop .ReadNextQword
343 pop ds
344 ret
345%endif
346
347;--------------------------------------------------------------------
348ALIGN JUMP_ALIGN
349WriteBlockTo16bitDataPort:
[363]350 xchg cl, ch ; Sectors to WORDs
[223]351 es ; Source is ES segment
[152]352 rep
[155]353 db 6Fh ; OUTSW (we want this in XT build)
[152]354 ret
355
[361]356;--------------------------------------------------------------------
[152]357ALIGN JUMP_ALIGN
[361]358WriteBlockTo32bitDataPort:
[363]359 db 0C1h ; SHL
360 db 0E1h ; CX
361 db 7 ; 7 (Sectors to DWORDs)
[223]362 es ; Source is ES segment
[152]363 rep
364 db 66h ; Override operand size to 32-bit
365 db 6Fh ; OUTSW/OUTSD
366 ret
367
368
[361]369
[150]370; Lookup tables to get transfer function based on bus type
371ALIGN WORD_ALIGN
372g_rgfnPioRead:
[361]373 dw ReadBlockFromXtideRev1 ; DEVICE_XTIDE_REV1
[152]374%ifdef USE_186
[361]375 dw ReadBlockFrom16bitDataPort ; DEVICE_XTIDE_REV2
376 dw ReadBlockFrom16bitDataPort ; DEVICE_FAST_XTIDE
[152]377%else
[361]378 dw ReadBlockFromXtideRev2 ; DEVICE_XTIDE_REV2
379 dw ReadBlockFromXtideRev2 ; DEVICE_FAST_XTIDE
[152]380%endif
[361]381 dw ReadBlockFrom16bitDataPort ; DEVICE_16BIT_ATA
382 dw ReadBlockFrom32bitDataPort ; DEVICE_32BIT_ATA
[152]383
[150]384g_rgfnPioWrite:
[361]385 dw WriteBlockToXtideRev1 ; DEVICE_XTIDE_REV1
386 dw WriteBlockToXtideRev2 ; DEVICE_XTIDE_REV2
387%ifdef USE_186
388 dw WriteBlockTo16bitDataPort ; DEVICE_FAST_XTIDE
389%else
390 dw WriteBlockToFastXtide ; DEVICE_FAST_XTIDE
391%endif
392 dw WriteBlockTo16bitDataPort ; DEVICE_16BIT_ATA
393 dw WriteBlockTo32bitDataPort ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.