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

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

Changes to XTIDE Universal BIOS:

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