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

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

Changes to XTIDE Universal BIOS:

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