2 Copyright © 2004-2008, The AROS Development Team. All rights reserved
12 * ---------- ------------------ -------------------------------------------------------------------
13 * 2006-12-20 T. Wiszkowski Updated ATA Packet Interface to handle ATAPI/SCSI Commands
14 * 2008-01-06 T. Wiszkowski Corrected and completed ATA Packet Interface handling. PIO transfers fully operational.
15 * 2008-01-07 T. Wiszkowski Added initial DMA support for Direct SCSI commands. Corrected atapi
16 * READ and WRITE commands to pass proper transfer size to the atapi_SendPacket
17 * as discovered by mschulz
18 * 2008-01-25 T. Wiszkowski Rebuilt, rearranged and partially fixed 60% of the code here
19 * Enabled implementation to scan for other PCI IDE controllers
20 * Implemented ATAPI Packet Support for both read and write
21 * Corrected ATAPI DMA handling
22 * Fixed major IDE enumeration bugs severely handicapping transfers with more than one controller
23 * Compacted source and implemented major ATA support procedure
24 * Improved DMA and Interrupt management
25 * Removed obsolete code
26 * 2008-01-26 T. Wiszkowski Restored 32bit io
27 * Removed memory dump upon RequestSense
28 * 2008-02-08 T. Wiszkowski Fixed DMA accesses for direct scsi devices,
29 * Corrected IO Areas to allow ATA to talk to PCI controllers
30 * 2008-03-03 T. Wiszkowski Added drive reselection + setup delay on Init
31 * 2008-03-29 T. Wiszkowski Restored error on 64bit R/W access to non-64bit capable atapi devices
33 * 2008-03-30 T. Wiszkowski Added workaround for interrupt collision handling; fixed SATA in LEGACY mode.
34 * nForce and Intel SATA chipsets should now be operational (nForce confirmed)
35 * 2008-03-31 M. Schulz The ins/outs function definitions used only in case of x86 and x86_64 architectures.
36 * Otherwise, function declaratons are emitted.
37 * 2008-04-01 M. Schulz Use C functions ata_ins[wl] ata_outs[wl]
38 * 2008-04-03 T. Wiszkowski Fixed IRQ flood issue, eliminated and reduced obsolete / redundant code
39 * 2008-04-05 T. Wiszkowski Improved IRQ management
40 * 2008-04-07 T. Wiszkowski Changed bus timeout mechanism
41 * increased failure timeout values to cover rainy day scenarios
42 * 2008-04-20 T. Wiszkowski Corrected the flaw in drive identification routines leading to ocassional system hangups
43 * 2008-05-11 T. Wiszkowski Remade the ata trannsfers altogether, corrected the pio/irq handling
44 * medium removal, device detection, bus management and much more
45 * 2008-05-12 P. Fedin Explicitly enable multisector transfers on the drive
46 * 2008-05-18 T. Wiszkowski Added extra checks to prevent duplicating drive0 in drive0 only configs
47 * 2008-05-18 T. Wiszkowski Replaced static C/H/S with more accurate calcs, should make HDTB and other tools see right capacity
48 * 2008-05-19 T. Wiszkowski Updated ATA DMA handling and transfer wait operation to allow complete transfer before dma_StopDMA()
49 * 2008-05-30 T. Wiszkowski Corrected CHS calculation for larger disks
50 * 2008-06-03 K. Smiechowicz Added 400ns delay in ata_WaitBusyTO before read of device status.
51 * 2008-06-25 P. Fedin Added "nomulti" flag
52 * PIO works correctly again
53 * 2008-11-28 T. Wiszkowski updated test unit ready to suit individual taste of hw manufacturers
57 * - put a critical section around DMA transfers (shared dma channels)
61 // use #define xxx(a) D(a) to enable particular sections.
69 #include <aros/debug.h>
70 #include <exec/types.h>
71 #include <exec/exec.h>
72 #include <exec/resident.h>
73 #include <utility/utility.h>
78 #include <proto/exec.h>
79 #include <devices/timer.h>
88 Prototypes of static functions from lowlevel.c. I do not want to make them
89 non-static as I'd like to remove as much symbols from global table as possible.
90 Besides some of this functions could conflict with old ide.device or any other
93 static ULONG
ata_ReadSector32(struct ata_Unit
*, ULONG
, ULONG
, APTR
, ULONG
*);
94 static ULONG
ata_ReadSector64(struct ata_Unit
*, UQUAD
, ULONG
, APTR
, ULONG
*);
95 static ULONG
ata_ReadMultiple32(struct ata_Unit
*, ULONG
, ULONG
, APTR
, ULONG
*);
96 static ULONG
ata_ReadMultiple64(struct ata_Unit
*, UQUAD
, ULONG
, APTR
, ULONG
*);
97 static ULONG
ata_ReadDMA32(struct ata_Unit
*, ULONG
, ULONG
, APTR
, ULONG
*);
98 static ULONG
ata_ReadDMA64(struct ata_Unit
*, UQUAD
, ULONG
, APTR
, ULONG
*);
99 static ULONG
ata_WriteSector32(struct ata_Unit
*, ULONG
, ULONG
, APTR
, ULONG
*);
100 static ULONG
ata_WriteSector64(struct ata_Unit
*, UQUAD
, ULONG
, APTR
, ULONG
*);
101 static ULONG
ata_WriteMultiple32(struct ata_Unit
*, ULONG
, ULONG
, APTR
, ULONG
*);
102 static ULONG
ata_WriteMultiple64(struct ata_Unit
*, UQUAD
, ULONG
, APTR
, ULONG
*);
103 static ULONG
ata_WriteDMA32(struct ata_Unit
*, ULONG
, ULONG
, APTR
, ULONG
*);
104 static ULONG
ata_WriteDMA64(struct ata_Unit
*, UQUAD
, ULONG
, APTR
, ULONG
*);
105 static ULONG
ata_Eject(struct ata_Unit
*);
106 static BOOL
ata_WaitBusyTO(struct ata_Unit
*unit
, UWORD tout
, BOOL irq
, UBYTE
*stout
);
108 static ULONG
atapi_EndCmd(struct ata_Unit
*unit
);
110 static ULONG
atapi_Read(struct ata_Unit
*, ULONG
, ULONG
, APTR
, ULONG
*);
111 static ULONG
atapi_Write(struct ata_Unit
*, ULONG
, ULONG
, APTR
, ULONG
*);
112 static ULONG
atapi_Eject(struct ata_Unit
*);
114 static void common_SetBestXferMode(struct ata_Unit
* unit
);
117 Again piece of code which shouldn't be here. Geee. After removing all this
118 asm constrictuins this ata.device will really deserve for location in
122 * having an x86 assembly here i dare to assume that this is meant to be
123 * an x86[_64] device only.
127 * This functions will stay here for some time *IF* and only if the code is compiled for
128 * x86 or x86_64 architecture. Otherwise, function declarations will be emitted and the
129 * one who ports the driver will be reponsible for adding the missing code.
133 * the outsl and insl commands improperly assumed that every transfer is sized to multiple of four
135 #if defined(__i386__) || defined(__x86_64__)
137 static VOID
ata_insw(APTR address
, UWORD port
, ULONG count
)
139 insw(port
, address
, count
>> 1);
142 static VOID
ata_insl(APTR address
, UWORD port
, ULONG count
)
145 insw(port
, address
, count
>> 1);
147 insl(port
, address
, count
>> 2);
150 static VOID
ata_outsw(APTR address
, UWORD port
, ULONG count
)
152 outsw(port
, address
, count
>> 1);
155 static VOID
ata_outsl(APTR address
, UWORD port
, ULONG count
)
158 outsw(port
, address
, count
>> 1);
160 outsl(port
, address
, count
>> 2);
164 * Very short delay (TM) by someone who assumes slow data ports.
165 * well, glad it works anyways.
169 ata_in(ata_AltControl
, 0x3f6);
170 ata_in(ata_AltControl
, 0x3f6);
171 ata_in(ata_AltControl
, 0x3f6);
172 ata_in(ata_AltControl
, 0x3f6);
176 extern VOID
ata_insw(APTR address
, UWORD port
, ULONG count
);
177 extern VOID
ata_insl(APTR address
, UWORD port
, ULONG count
);
178 extern VOID
ata_outsw(APTR address
, UWORD port
, ULONG count
);
179 extern VOID
ata_outsl(APTR address
, UWORD port
, ULONG count
);
180 extern void ata_400ns();
183 static void dump(APTR mem
, ULONG len
)
186 for (j
=0; j
<(len
+15)>>4; ++j
)
188 bug("[ATA ] %06lx: ", j
<<4);
190 for (i
=0; i
<len
-(j
<<4); i
++)
192 bug("%02lx ", ((unsigned char*)mem
)[(j
<<4)|i
]);
197 for (i
=0; i
<len
-(j
<<4); i
++)
199 unsigned char c
= ((unsigned char*)mem
)[(j
<<4)|i
];
201 bug("%c", c
>= 0x20 ? c
<=0x7f ? c
: '.' : '.');
209 static void ata_strcpy(const UBYTE
*str1
, UBYTE
*str2
, ULONG size
)
211 register int i
= size
;
215 str2
[size
^1] = str1
[size
];
227 * a STUB function for commands not supported by this particular device
229 static ULONG
ata_STUB(struct ata_Unit
*au
)
231 bug("[ATA%02ld] CALLED STUB FUNCTION. THIS OPERATION IS NOT SUPPORTED BY DEVICE\n", au
->au_UnitNum
);
235 static ULONG
ata_STUB_IO32(struct ata_Unit
*au
, ULONG blk
, ULONG len
, APTR buf
, ULONG
* act
)
237 bug("[ATA%02ld] CALLED STUB FUNCTION. THIS OPERATION IS NOT SUPPORTED BY DEVICE\n", au
->au_UnitNum
);
241 static ULONG
ata_STUB_IO64(struct ata_Unit
*au
, UQUAD blk
, ULONG len
, APTR buf
, ULONG
* act
)
243 bug("[ATA%02ld] CALLED STUB FUNCTION -- IO ACCESS TO BLOCK %08lx:%08lx, LENGTH %08lx. THIS OPERATION IS NOT SUPPORTED BY DEVICE\n", au
->au_UnitNum
, (blk
>> 32), (blk
& 0xffffffff), len
);
247 static ULONG
ata_STUB_SCSI(struct ata_Unit
*au
, struct SCSICmd
* cmd
)
249 bug("[ATA%02ld] CALLED STUB FUNCTION. THIS OPERATION IS NOT SUPPORTED BY DEVICE\n", au
->au_UnitNum
);
253 inline BOOL
ata_SelectUnit(struct ata_Unit
* unit
)
255 ata_out(unit
->au_DevMask
, ata_DevHead
, unit
->au_Bus
->ab_Port
);
261 while (0 != (ATAF_BUSY
& ata_ReadStatus(unit
->au_Bus
)));
266 inline struct ata_Unit
* ata_GetSelectedUnit(struct ata_Bus
* bus
)
268 register int id
= (ata_in(ata_DevHead
, bus
->ab_Port
) & 0x10) >> 4;
269 return bus
->ab_Units
[id
];
272 UBYTE
ata_ReadStatus(struct ata_Bus
*bus
)
274 return ata_in(ata_Status
, bus
->ab_Port
);
278 * enable / disable IRQ; this manages interrupt requests more effectively in case of legacy emulation
279 * as little code as there can be. and keep it that way.
281 void ata_EnableIRQ(struct ata_Bus
*bus
, BOOL enable
)
283 enable
&= (bus
->ab_Dev
[0] > DEV_UNKNOWN
) || (bus
->ab_Dev
[1] > DEV_UNKNOWN
);
284 bug("[ATA ] IRQ: Setting IRQ flag for bus %ld to %s\n", bus
->ab_BusNum
, enable
? "ENABLED" : "DISABLED");
285 bus
->ab_IRQ
= enable
;
286 ata_out(enable
? 0x0 : 0x02, ata_AltControl
, bus
->ab_Alt
);
290 * handle IRQ; still fast and efficient, supposed to verify if this irq is for us and take adequate steps
291 * part of code moved here from ata.c to reduce containment
293 void ata_IRQSignalTask(struct ata_Bus
*bus
)
296 Signal(bus
->ab_Task
, 1UL << bus
->ab_SleepySignal
);
299 void ata_HandleIRQ(struct ata_Bus
*bus
)
301 struct ata_Unit
*u
= ata_GetSelectedUnit(bus
);
302 UBYTE status
= ata_ReadStatus(bus
);
304 * don't waste your time on checking other devices.
305 * pass irq ONLY if task is expecting one;
308 if (0 != bus
->ab_HandleIRQ
)
311 * ok, we have a routine to handle any form of transmission etc
313 DIRQ(bug("[ATA ] IRQ: Calling dedicated handler... \n"));
314 bus
->ab_HandleIRQ(u
, status
);
320 * if we got *here* then device is most likely not expected to have an irq.
322 bug("[ATA%02ld] IRQ: Checking busy flag: ", u
->au_UnitNum
);
324 if (0 == (ATAF_BUSY
& status
))
326 bug("device ready. Dumping details:\n");
328 bug("[ATA ] STATUS: %02lx\n", status
);
329 bug("[ATA ] ALT STATUS: %02lx\n", ata_in(ata_AltStatus
, bus
->ab_Alt
));
330 bug("[ATA ] ERROR: %02lx\n", ata_in(ata_Error
, bus
->ab_Port
));
331 bug("[ATA ] IRQ: REASON: %02lx\n", ata_in(atapi_Reason
, bus
->ab_Port
));
335 bug("device still busy. ignoring irq.\n");
340 void ata_IRQSetHandler(struct ata_Unit
*unit
, void (*handler
)(struct ata_Unit
*, UBYTE
), APTR piomem
, ULONG blklen
, ULONG piolen
)
343 unit
->au_cmd_error
= 0;
345 unit
->au_cmd_data
= piomem
;
346 unit
->au_cmd_length
= (piolen
< blklen
) ? piolen
: blklen
;
347 unit
->au_cmd_total
= piolen
;
348 unit
->au_Bus
->ab_HandleIRQ
= handler
;
351 void ata_IRQNoData(struct ata_Unit
*unit
, UBYTE status
)
353 if (status
& ATAF_BUSY
)
356 if ((unit
->au_cmd_error
== 0) && (status
& ATAF_ERROR
))
357 unit
->au_cmd_error
= HFERR_BadStatus
;
359 DIRQ(bug("[ATA%02ld] IRQ: NoData - done; status %02lx.\n", unit
->au_UnitNum
, status
));
360 ata_IRQSetHandler(unit
, NULL
, NULL
, 0, 0);
361 ata_IRQSignalTask(unit
->au_Bus
);
364 void ata_IRQPIORead(struct ata_Unit
*unit
, UBYTE status
)
366 if (status
& ATAF_DATAREQ
) {
367 DIRQ(bug("[ATA ] IRQ: PIOReadData - DRQ.\n"));
368 unit
->au_ins(unit
->au_cmd_data
, unit
->au_Bus
->ab_Port
, unit
->au_cmd_length
);
371 * indicate it's all done here
373 unit
->au_cmd_data
+= unit
->au_cmd_length
;
374 unit
->au_cmd_total
-= unit
->au_cmd_length
;
375 if (unit
->au_cmd_total
) {
376 if (unit
->au_cmd_length
> unit
->au_cmd_total
)
377 unit
->au_cmd_length
= unit
->au_cmd_total
;
380 DIRQ(bug("[ATA ] IRQ: PIOReadData - transfer completed.\n"));
382 ata_IRQNoData(unit
, status
);
385 void ata_PIOWriteBlk(struct ata_Unit
*unit
)
387 unit
->au_outs(unit
->au_cmd_data
, unit
->au_Bus
->ab_Port
, unit
->au_cmd_length
);
390 * indicate it's all done here
392 unit
->au_cmd_data
+= unit
->au_cmd_length
;
393 unit
->au_cmd_total
-= unit
->au_cmd_length
;
394 if (unit
->au_cmd_length
> unit
->au_cmd_total
)
395 unit
->au_cmd_length
= unit
->au_cmd_total
;
398 void ata_IRQPIOWrite(struct ata_Unit
*unit
, UBYTE status
)
400 if (status
& ATAF_DATAREQ
) {
401 DIRQ(bug("[ATA ] IRQ: PIOWriteData - DRQ.\n"));
402 ata_PIOWriteBlk(unit
);
405 DIRQ(bug("[ATA ] IRQ: PIOWriteData - done.\n"));
406 ata_IRQNoData(unit
, status
);
409 void ata_IRQDMAReadWrite(struct ata_Unit
*au
, UBYTE status
)
411 UBYTE stat
= ata_in(dma_Status
, au
->au_DMAPort
);
412 DIRQ(bug("[ATA%02ld] IRQ: IO status %02lx, DMA status %02lx\n", au
->au_UnitNum
, status
, stat
));
414 if (0 == (stat
& DMAF_Interrupt
))
416 bug("[ATA ] IRQ: Fake IRQ.\n");
418 else if ((status
& ATAF_ERROR
) || (stat
& DMAF_Error
))
420 /* This is turned on in order to help Phantom - Pavel Fedin <sonic_amiga@rambler.ru> */
421 bug("[ATA%02ld] IRQ: IO status %02lx, DMA status %02lx\n", au
->au_UnitNum
, status
, stat
);
422 bug("[ATA%02ld] IRQ: ERROR %02lx\n", au
->au_UnitNum
, ata_in(atapi_Error
, au
->au_Bus
->ab_Port
));
423 bug("[ATA ] IRQ: DMA Failed.\n");
424 au
->au_cmd_error
= HFERR_DMA
;
425 ata_IRQNoData(au
, status
);
427 else if (0 == (status
& (ATAF_BUSY
| ATAF_DATAREQ
)))
429 DIRQ(bug("[ATA ] IRQ: DMA Done.\n"));
430 ata_IRQNoData(au
, status
);
434 void ata_IRQPIOReadAtapi(struct ata_Unit
*unit
, UBYTE status
)
436 ULONG port
= unit
->au_Bus
->ab_Port
;
438 UBYTE reason
= ata_in(atapi_Reason
, port
);
439 DIRQ(bug("[DSCSI] Current status: %ld during READ\n", reason
));
441 /* have we failed yet? */
442 if (0 == (status
& (ATAF_BUSY
| ATAF_DATAREQ
)))
443 ata_IRQNoData(unit
, status
);
444 if (status
& ATAF_ERROR
)
445 ata_IRQNoData(unit
, status
);
447 /* anything for us please? */
448 if (ATAPIF_READ
!= (reason
& ATAPIF_MASK
))
451 size
= ata_in(atapi_ByteCntH
, port
) << 8 | ata_in(atapi_ByteCntL
, port
);
452 DIRQ(bug("[ATAPI] IRQ: data available for read (%ld bytes, max: %ld bytes)\n", size
, unit
->au_cmd_total
));
454 if (size
> unit
->au_cmd_total
)
456 bug("[ATAPI] IRQ: CRITICAL! MORE DATA OFFERED THAN STORAGE CAN TAKE: %ld bytes vs %ld bytes left!\n", size
, unit
->au_cmd_total
);
457 size
= unit
->au_cmd_total
;
460 unit
->au_ins(unit
->au_cmd_data
, port
, size
);
461 unit
->au_cmd_data
= &((UBYTE
*)unit
->au_cmd_data
)[size
];
462 unit
->au_cmd_total
-= size
;
464 DIRQ(bug("[ATAPI] IRQ: %lu bytes read.\n", size
));
466 if (unit
->au_cmd_total
== 0)
467 ata_IRQNoData(unit
, status
);
470 void ata_IRQPIOWriteAtapi(struct ata_Unit
*unit
, UBYTE status
)
472 ULONG port
= unit
->au_Bus
->ab_Port
;
474 UBYTE reason
= ata_in(atapi_Reason
, port
);
475 DIRQ(bug("[ATAPI] IRQ: Current status: %ld during WRITE\n", reason
));
477 /* have we failed yet? */
478 if (0 == (status
& (ATAF_BUSY
| ATAF_DATAREQ
)))
479 ata_IRQNoData(unit
, status
);
480 if (status
& ATAF_ERROR
)
481 ata_IRQNoData(unit
, status
);
483 /* anything for us please? */
484 if (ATAPIF_READ
!= (reason
& ATAPIF_MASK
))
487 size
= ata_in(atapi_ByteCntH
, port
) << 8 | ata_in(atapi_ByteCntL
, port
);
488 DIRQ(bug("[ATAPI] IRQ: data requested for write (%ld bytes, max: %ld bytes)\n", size
, unit
->au_cmd_total
));
490 if (size
> unit
->au_cmd_total
)
492 bug("[ATAPI] IRQ: CRITICAL! MORE DATA REQUESTED THAN STORAGE CAN GIVE: %ld bytes vs %ld bytes left!\n", size
, unit
->au_cmd_total
);
493 size
= unit
->au_cmd_total
;
496 unit
->au_outs(unit
->au_cmd_data
, port
, size
);
497 unit
->au_cmd_data
= &((UBYTE
*)unit
->au_cmd_data
)[size
];
498 unit
->au_cmd_total
-= size
;
500 DIRQ(bug("[ATAPI] IRQ: %lu bytes written.\n", size
));
502 if (unit
->au_cmd_total
== 0)
503 ata_IRQNoData(unit
, status
);
507 * wait for timeout or drive ready
508 * polling-in-a-loop, but it should be safe to remove this already
510 BOOL
ata_WaitBusyTO(struct ata_Unit
*unit
, UWORD tout
, BOOL irq
, UBYTE
*stout
)
513 ULONG sigs
= SIGBREAKF_CTRL_C
;
517 if (irq
&& !unit
->au_Bus
->ab_IRQ
)
519 bug("[ATA ] Requested IRQ wait, but IRQ is not enabled\n");
522 irq
&= unit
->au_Bus
->ab_IRQ
;
523 sigs
|= (irq
? (1 << unit
->au_Bus
->ab_SleepySignal
) : 0);
526 * clear up all old signals
531 * set up bus timeout and irq
534 unit
->au_Bus
->ab_Timeout
= tout
;
538 * this loop may experience one of two scenarios
539 * 1) we get a valid irq and the drive wanted to let us know that it's ready
540 * 2) we get an invalid irq due to some collissions. We may still want to go ahead and get some extra irq breaks
541 * this would reduce system load a little
548 * delay the check - this was found needed for some hardware
554 * lets check if the drive is already good
556 status
= ata_in(ata_Status
, unit
->au_Bus
->ab_Port
);
557 if (0 == (status
& (ATAF_DATAREQ
| ATAF_BUSY
)))
561 * so we're stuck in a loop?
563 DIRQ(bug("[ATA%02ld] Waiting (Current status: %02lx)...\n", unit
->au_UnitNum
, status
));
566 * if IRQ wait is requested then allow either timeout or irq;
567 * then clear irq flag so we dont keep receiving more of these (especially when system suffers collissions)
572 * wait for either IRQ or TIMEOUT
577 * now if we did reach timeout, then there's no point in going ahead.
579 if (SIGBREAKF_CTRL_C
& step
)
581 bug("[ATA%02ld] Timeout while waiting for device to complete operation\n", unit
->au_UnitNum
);
586 * if we get as far as this, there's no more signals to expect
587 * but we still want the status
589 status
= ata_in(ata_Status
, unit
->au_Bus
->ab_Port
);
595 * device not ready just yet. lets set whether we want an IRQ and move on - to polling or irq wait
600 * every 16n rounds do some extra stuff
602 if ((step
& 16) == 0)
605 * huhm. so it's been 16n rounds already. any timeout yet?
607 if (SetSignal(0, SIGBREAKF_CTRL_C
) & SIGBREAKF_CTRL_C
)
609 DIRQ(bug("[ATA%02ld] Device still busy after timeout. Aborting\n", unit
->au_UnitNum
));
615 * no timeout just yet, but it's not a good idea to keep spinning like that.
616 * let's give the system some time.
619 // TODO: Put some delay here!
622 } while(status
& ATAF_BUSY
);
625 * be nice to frustrated developer
627 DIRQ(bug("[ATA%02ld] WaitBusy status: %lx / %ld\n", unit
->au_UnitNum
, status
, res
));
630 * clear up all our expectations
633 unit
->au_Bus
->ab_Timeout
= -1;
642 * and say it went fine (i mean it)
650 * just wait for timeout
652 void ata_Wait(struct ata_Unit
*unit
, UWORD tout
)
654 SetSignal(0, SIGBREAKF_CTRL_C
);
657 unit
->au_Bus
->ab_Timeout
= tout
;
660 Wait(SIGBREAKF_CTRL_C
);
664 * Procedure for sending ATA command blocks
665 * it appears LARGE but there's a lot of COMMENTS here :)
666 * handles *all* ata commands (no data, pio and dma)
667 * naturally could be splitted at some point in the future
668 * depends if anyone believes that the change for 50 lines
669 * would make slow ATA transfers any faster
671 static ULONG
ata_exec_cmd(struct ata_Unit
* au
, ata_CommandBlock
*block
)
673 ULONG port
= au
->au_Bus
->ab_Port
;
675 APTR mem
= block
->buffer
;
678 if (FALSE
== ata_SelectUnit(au
))
679 return IOERR_UNITBUSY
;
684 if (block
->sectors
> 256)
686 bug("[ATA%02ld] ERROR: Transfer length (%ld) exceeds 256 sectors. Aborting.\n", au
->au_UnitNum
, block
->sectors
);
687 return IOERR_BADLENGTH
;
691 * we want the above to fall in here!
692 * we really do (checking for secmul)
696 if (block
->sectors
> 65536)
698 bug("[ATA%02ld] ERROR: Transfer length (%ld) exceeds 65536 sectors. Aborting.\n", au
->au_UnitNum
, block
->sectors
);
699 return IOERR_BADLENGTH
;
701 if (block
->secmul
== 0)
703 bug("[ATA%02ld] ERROR: Invalid transfer multiplier. Should be at least set to 1 (correcting)\n", au
->au_UnitNum
);
712 bug("[ATA%02ld] ERROR: Invalid command type %lx. Aborting.\n", au
->au_UnitNum
, block
->type
);
717 D(bug("[ATA%02ld] Executing command %02lx\n", au
->au_UnitNum
, block
->command
));
719 if (block
->feature
!= 0)
720 ata_out(block
->feature
, ata_Feature
, port
);
723 * - set LBA and sector count
728 DATA(bug("[ATA%02ld] Command uses 28bit LBA addressing (OLD)\n", au
->au_UnitNum
));
729 ata_out(((block
->blk
>> 24) & 0x0f) | 0x40 | au
->au_DevMask
, ata_DevHead
, port
);
730 ata_out(block
->blk
>> 16, ata_LBAHigh
, port
);
731 ata_out(block
->blk
>> 8, ata_LBAMid
, port
);
732 ata_out(block
->blk
, ata_LBALow
, port
);
733 ata_out(block
->sectors
, ata_Count
, port
);
737 DATA(bug("[ATA%02ld] Command uses 48bit LBA addressing (NEW)\n", au
->au_UnitNum
));
738 ata_out(block
->blk
>> 40, ata_LBAHigh
, port
);
739 ata_out(block
->blk
>> 32, ata_LBAMid
, port
);
740 ata_out(block
->blk
>> 24, ata_LBALow
, port
);
742 ata_out(block
->blk
>> 16, ata_LBAHigh
, port
);
743 ata_out(block
->blk
>> 8, ata_LBAMid
, port
);
744 ata_out(block
->blk
, ata_LBALow
, port
);
746 ata_out(block
->sectors
>> 8, ata_Count
, port
);
747 ata_out(block
->sectors
, ata_Count
, port
);
751 DATA(bug("[ATA%02ld] Command does not address any block\n", au
->au_UnitNum
));
756 switch (block
->method
)
759 ata_IRQSetHandler(au
, &ata_IRQPIOWrite
, mem
, block
->secmul
<< au
->au_SectorShift
, block
->length
);
763 ata_IRQSetHandler(au
, &ata_IRQPIORead
, mem
, block
->secmul
<< au
->au_SectorShift
, block
->length
);
767 if (FALSE
== dma_SetupPRDSize(au
, mem
, block
->length
, TRUE
))
768 return IOERR_ABORTED
;
769 ata_IRQSetHandler(au
, &ata_IRQDMAReadWrite
, NULL
, 0, 0);
774 if (FALSE
== dma_SetupPRDSize(au
, mem
, block
->length
, FALSE
))
775 return IOERR_ABORTED
;
776 ata_IRQSetHandler(au
, &ata_IRQDMAReadWrite
, NULL
, 0, 0);
781 ata_IRQSetHandler(au
, &ata_IRQNoData
, NULL
, 0, 0);
791 * let drive propagate its signals
793 DATA(bug("[ATA%02ld] Sending command\n", au
->au_UnitNum
));
794 ata_out(block
->command
, ata_Command
, port
);
798 * In case of PIO write the drive won't issue an IRQ before first
799 * data transfer, so we should poll the status and send the firs
800 * block upon request.
802 if (block
->method
== CM_PIOWrite
) {
803 if (FALSE
== ata_WaitBusyTO(au
, 300, FALSE
, &status
)) {
804 D(bug("[ATA%02ld] PIOWrite - no response from device\n", au
->au_UnitNum
));
805 return IOERR_UNITBUSY
;
807 if (status
& ATAF_DATAREQ
) {
808 DATA(bug("[ATA%02ld] PIOWrite - DRQ.\n", au
->au_UnitNum
));
813 D(bug("[ATA%02ld] PIOWrite - bad status: %02X\n", status
));
814 return HFERR_BadStatus
;
819 * wait for drive to complete what it has to do
821 if (FALSE
== ata_WaitBusyTO(au
, 300, TRUE
, NULL
))
823 bug("[ATA%02ld] Device is late - no response\n", au
->au_UnitNum
);
824 err
= IOERR_UNITBUSY
;
827 err
= au
->au_cmd_error
;
829 DATA(bug("[ATA%02ld] Command done\n", au
->au_UnitNum
));
832 * don't use 'mem' pointer here as it's already invalid.
834 if (block
->method
== CM_DMARead
)
837 dma_Cleanup(block
->buffer
, block
->length
, TRUE
);
839 else if (block
->method
== CM_DMAWrite
)
842 dma_Cleanup(block
->buffer
, block
->length
, FALSE
);
845 D(bug("[ATA%02ld] return code %ld\n", au
->au_UnitNum
, err
));
852 int atapi_SendPacket(struct ata_Unit
*unit
, APTR packet
, APTR data
, LONG datalen
, BOOL
*dma
, BOOL write
)
854 *dma
&= (unit
->au_XferModes
& AF_XFER_DMA
) ? TRUE
: FALSE
;
860 register int t
=5,l
=0;
861 ULONG port
= unit
->au_Bus
->ab_Port
;
863 if (((UBYTE
*)packet
)[0] > 0x1f)
865 if (((UBYTE
*)packet
)[0] > 0x5f)
868 switch (((UBYTE
*)packet
)[0])
873 case 0xb9: // readcdmsf
876 case 0xaa: // write12
877 case 0x2e: // writeverify
885 cmd
[l
] = ((UBYTE
*)packet
)[l
];
890 bug("[ATA%02lx] Sending %s ATA packet: ", unit
->au_UnitNum
, (*dma
) ? "DMA" : "PIO");
894 bug("%02lx ", ((UBYTE
*)cmd
)[l
]);
900 bug("[ATAPI] ERROR: DATA LENGTH NOT EVEN! Rounding Up! (%ld bytes requested)\n", datalen
);
903 datalen
= (datalen
+1)&~1;
905 if (FALSE
== ata_SelectUnit(unit
))
907 DATAPI(bug("[ATAPI] WaitBusy failed at first check\n"));
908 return IOERR_UNITBUSY
;
912 * tell device if whether we want to read or write and if we want a dma transfer
914 ata_out(((*dma
) ? 1 : 0) | ((write
) ? 4 : 0), atapi_Features
, port
);
915 ata_out((datalen
& 0xff), atapi_ByteCntL
, port
);
916 ata_out((datalen
>> 8) & 0xff, atapi_ByteCntH
, port
);
919 * once we're done with that, we can go ahead and inform device that we're about to send atapi packet
920 * after command is dispatched, we are obliged to give 400ns for the unit to parse command and set status
922 DATAPI(bug("[ATAPI] Issuing ATA_PACKET command.\n"));
923 ata_out(ATA_PACKET
, atapi_Command
, port
);
926 ata_WaitBusyTO(unit
, 30, FALSE
, NULL
);
927 if (0 == (ata_ReadStatus(unit
->au_Bus
) & ATAF_DATAREQ
))
928 return HFERR_BadStatus
;
931 * setup appropriate hooks. not really the best way.
934 ata_IRQSetHandler(unit
, &ata_IRQNoData
, 0, 0, 0);
936 ata_IRQSetHandler(unit
, &ata_IRQDMAReadWrite
, NULL
, 0, 0);
938 ata_IRQSetHandler(unit
, &ata_IRQPIOWriteAtapi
, data
, 0, datalen
);
940 ata_IRQSetHandler(unit
, &ata_IRQPIOReadAtapi
, data
, 0, datalen
);
942 DATAPI(bug("[ATAPI] Sending packet\n"));
943 unit
->au_outs(cmd
, unit
->au_Bus
->ab_Port
, 12);
944 ata_400ns(); /* give drive time to think about what we just said, then move on */
945 /* how much time could it take for drive to raise DMARQ signal?? */
947 DATAPI(bug("[ATAPI] Status after packet: %lx\n", ata_ReadStatus(unit
->au_Bus
)));
951 DATAPI(bug("[ATAPI] Preparing for DMA\n"));
952 while (0 == ((t
= ata_ReadStatus(unit
->au_Bus
)) & (ATAF_BUSY
| ATAF_DATAREQ
)))
959 DATAPI(bug("[ATAPI] status %02lx\n", ata_ReadStatus(unit
->au_Bus
)));
963 DATAPI(bug("[ATAPI] status %02lx\n", ata_ReadStatus(unit
->au_Bus
)));
967 DATAPI(bug("[ATAPI] Starting DMA\n"));
972 if ((0 == err
) && (ata_WaitBusyTO(unit
, 300, TRUE
, NULL
) == FALSE
))
974 DATAPI(bug("[DSCSI] Command timed out.\n"));
975 err
= IOERR_UNITBUSY
;
978 err
= atapi_EndCmd(unit
);
983 dma_Cleanup(data
, datalen
, !write
);
986 D(bug("[ATAPI] Error code %ld\n", err
));
990 ULONG
atapi_DirectSCSI(struct ata_Unit
*unit
, struct SCSICmd
*cmd
)
992 APTR buffer
= cmd
->scsi_Data
;
993 ULONG length
= cmd
->scsi_Length
;
999 cmd
->scsi_Actual
= 0;
1001 DATAPI(bug("[DSCSI] Sending packet!\n"));
1005 * setup DMA & push command
1006 * it does not really mean we will use dma here btw
1008 if ((unit
->au_XferModes
& AF_XFER_DMA
) && (length
!=0) && (buffer
!= 0))
1011 if ((cmd
->scsi_Flags
& SCSIF_READ
) != 0)
1014 if (FALSE
== dma_SetupPRDSize(unit
, buffer
, length
, TRUE
))
1019 if (FALSE
== dma_SetupPRDSize(unit
, buffer
, length
, FALSE
))
1024 err
= atapi_SendPacket(unit
, cmd
->scsi_Command
, cmd
->scsi_Data
, cmd
->scsi_Length
, &dma
, (cmd
->scsi_Flags
& SCSIF_READ
) == 0);
1026 DUMP({ if (cmd
->scsi_Data
!= 0) dump(cmd
->scsi_Data
, cmd
->scsi_Length
); });
1029 * on check condition - grab sense data
1031 DATAPI(bug("[ATA%02lx] SCSI Flags: %02lx / Error: %ld\n", unit
->au_UnitNum
, cmd
->scsi_Flags
, err
));
1032 if ((err
!= 0) && (cmd
->scsi_Flags
& SCSIF_AUTOSENSE
))
1034 atapi_RequestSense(unit
, cmd
->scsi_SenseData
, cmd
->scsi_SenseLength
);
1035 DUMP(dump(cmd
->scsi_SenseData
, cmd
->scsi_SenseLength
));
1042 * chops the large transfers into set of smaller transfers
1043 * specifically useful when requested transfer size is >256 sectors for 28bit commands
1045 static ULONG
ata_exec_blk(struct ata_Unit
*unit
, ata_CommandBlock
*blk
)
1050 ULONG count
=blk
->sectors
;
1052 if (blk
->type
== CT_LBA48
)
1055 DATA(bug("[ATA%02ld] Accessing %ld sectors starting from %lx\n", unit
->au_UnitNum
, count
, blk
->blk
));
1056 while ((count
> 0) && (err
== 0))
1058 part
= (count
> max
) ? max
: count
;
1059 blk
->sectors
= part
;
1060 blk
->length
= part
<< unit
->au_SectorShift
;
1062 err
= ata_exec_cmd(unit
, blk
);
1065 blk
->buffer
= &((char*)blk
->buffer
)[part
<< unit
->au_SectorShift
];
1072 * Initial device configuration that suits *all* cases
1074 BOOL
ata_init_unit(struct ata_Bus
*bus
, UBYTE u
)
1076 struct ata_Unit
*unit
=NULL
;
1078 DINIT(bug("[ATA ] Initializing unit %ld\n", u
));
1080 unit
= bus
->ab_Units
[u
];
1085 unit
->au_Drive
= AllocPooled(bus
->ab_Base
->ata_MemPool
, sizeof(struct DriveIdent
));
1086 unit
->au_UnitNum
= bus
->ab_BusNum
<< 1 | u
; // b << 8 | u
1087 unit
->au_DevMask
= 0xa0 | (u
<< 4);
1088 if (bus
->ab_Base
->ata_32bit
)
1090 unit
->au_ins
= ata_insl
;
1091 unit
->au_outs
= ata_outsl
;
1095 unit
->au_ins
= ata_insw
;
1096 unit
->au_outs
= ata_outsw
;
1098 unit
->au_SectorShift
= 9; /* this really has to be set here. */
1101 NEWLIST(&unit
->au_SoftList
);
1104 * since the stack is always handled by caller
1105 * it's safe to stub all calls with one function
1107 unit
->au_Read32
= ata_STUB_IO32
;
1108 unit
->au_Read64
= ata_STUB_IO64
;
1109 unit
->au_Write32
= ata_STUB_IO32
;
1110 unit
->au_Write64
= ata_STUB_IO64
;
1111 unit
->au_Eject
= ata_STUB
;
1112 unit
->au_DirectSCSI
= ata_STUB_SCSI
;
1113 unit
->au_Identify
= ata_STUB
;
1117 BOOL
ata_setup_unit(struct ata_Bus
*bus
, UBYTE u
)
1119 struct ata_Unit
*unit
=NULL
;
1122 * this stuff always goes along the same way
1123 * WARNING: NO INTERRUPTS AT THIS POINT!
1125 DINIT(bug("[ATA ] setting up unit %ld\n", u
));
1127 unit
= bus
->ab_Units
[u
];
1131 ata_SelectUnit(unit
);
1133 if (FALSE
== ata_WaitBusyTO(unit
, 1, FALSE
, NULL
))
1135 DINIT(bug("[ATA%02ld] ERROR: Drive not ready for use. Keeping functions stubbed\n", unit
->au_UnitNum
));
1136 FreePooled(bus
->ab_Base
->ata_MemPool
, unit
->au_Drive
, sizeof(struct DriveIdent
));
1141 switch (bus
->ab_Dev
[u
])
1144 * safe fallback settings
1148 unit
->au_Identify
= atapi_Identify
;
1153 unit
->au_Identify
= ata_Identify
;
1158 DINIT(bug("[ATA%02ld] Unsupported device %lx. All functions will remain stubbed.\n", unit
->au_UnitNum
, bus
->ab_Dev
[u
]));
1159 FreePooled(bus
->ab_Base
->ata_MemPool
, unit
->au_Drive
, sizeof(struct DriveIdent
));
1164 bug("[ATA ] Enabling Bus IRQs\n");
1165 ata_EnableIRQ(bus
, TRUE
);
1167 * now make unit self diagnose
1169 if (unit
->au_Identify(unit
) != 0)
1171 FreePooled(bus
->ab_Base
->ata_MemPool
, unit
->au_Drive
, sizeof(struct DriveIdent
));
1184 static void common_SetXferMode(struct ata_Unit
* unit
, ata_XferMode mode
)
1188 ata_CommandBlock acb
=
1203 if ((unit
->au_DMAPort
== 0) && (mode
> AB_XFER_PIO7
))
1205 DINIT(bug("[ATA%02ld] This controller does not own DMA port! Will set best PIO\n", unit
->au_UnitNum
));
1206 common_SetBestXferMode(unit
);
1212 * first, ONLY for ATA devices, set new commands
1214 if (0 == (unit
->au_XferModes
& AF_XFER_PACKET
))
1216 if ((mode
>= AB_XFER_PIO0
) & (mode
<= AB_XFER_PIO7
))
1218 if ((!unit
->au_Bus
->ab_Base
->ata_NoMulti
) && (unit
->au_XferModes
& AF_XFER_RWMULTI
))
1220 ata_out(unit
->au_Drive
->id_RWMultipleSize
& 0xFF, ata_Count
, unit
->au_Bus
->ab_Port
);
1221 ata_out(ATA_SET_MULTIPLE
, ata_Command
, unit
->au_Bus
->ab_Port
);
1222 ata_WaitBusyTO(unit
, -1, FALSE
, NULL
);
1224 unit
->au_Read32
= ata_ReadMultiple32
;
1225 unit
->au_Write32
= ata_WriteMultiple32
;
1226 if (unit
->au_XferModes
& AF_XFER_48BIT
)
1228 unit
->au_Read64
= ata_ReadMultiple64
;
1229 unit
->au_Write64
= ata_WriteMultiple64
;
1234 unit
->au_Read32
= ata_ReadSector32
;
1235 unit
->au_Write32
= ata_WriteSector32
;
1236 if (unit
->au_XferModes
& AF_XFER_48BIT
)
1238 unit
->au_Read64
= ata_ReadSector64
;
1239 unit
->au_Write64
= ata_WriteSector64
;
1243 else if ((mode
>= AB_XFER_MDMA0
) & (mode
<= AB_XFER_MDMA7
))
1245 unit
->au_Read32
= ata_ReadDMA32
;
1246 unit
->au_Write32
= ata_WriteDMA32
;
1247 if (unit
->au_XferModes
& AF_XFER_48BIT
)
1249 unit
->au_Read64
= ata_ReadDMA64
;
1250 unit
->au_Write64
= ata_WriteDMA64
;
1253 else if ((mode
>= AB_XFER_UDMA0
) & (mode
<= AB_XFER_UDMA7
))
1255 unit
->au_Read32
= ata_ReadDMA32
;
1256 unit
->au_Write32
= ata_WriteDMA32
;
1257 if (unit
->au_XferModes
& AF_XFER_48BIT
)
1259 unit
->au_Read64
= ata_ReadDMA64
;
1260 unit
->au_Write64
= ata_WriteDMA64
;
1265 unit
->au_Read32
= ata_ReadSector32
;
1266 unit
->au_Write32
= ata_WriteSector32
;
1267 if (unit
->au_XferModes
& AF_XFER_48BIT
)
1269 unit
->au_Read64
= ata_ReadSector64
;
1270 unit
->au_Write64
= ata_WriteSector64
;
1275 if ((mode
>= AB_XFER_PIO0
) & (mode
<= AB_XFER_PIO7
))
1277 type
= 8 + (mode
- AB_XFER_PIO0
);
1279 else if ((mode
>= AB_XFER_MDMA0
) & (mode
<= AB_XFER_MDMA7
))
1281 type
= 32 + (mode
- AB_XFER_MDMA7
);
1284 else if ((mode
>= AB_XFER_UDMA0
) & (mode
<= AB_XFER_UDMA7
))
1286 type
= 64 + (mode
- AB_XFER_MDMA7
);
1295 if (0 != ata_exec_cmd(unit
, &acb
))
1297 DINIT(bug("[ATA%02ld] ERROR: Failed to apply new xfer mode.\n", unit
->au_UnitNum
));
1300 if (unit
->au_DMAPort
)
1302 type
= ata_in(dma_Status
, unit
->au_DMAPort
);
1306 type
|= 1 << (5 + (unit
->au_UnitNum
& 1));
1310 type
&= ~(1 << (5 + (unit
->au_UnitNum
& 1)));
1313 DINIT(bug("[DSCSI] Trying to apply new DMA (%lx) status: %02lx (unit %ld)\n", unit
->au_DMAPort
, type
, unit
->au_UnitNum
& 1));
1315 ata_SelectUnit(unit
);
1316 ata_out(type
, dma_Status
, unit
->au_DMAPort
);
1317 if (type
== (ata_in(dma_Status
, unit
->au_DMAPort
) & 0x60))
1319 DINIT(bug("[DSCSI] New DMA Status: %02lx\n", type
));
1323 DINIT(bug("[DSCSI] Failed to modify DMA state for this device\n"));
1329 unit
->au_XferModes
|= AF_XFER_DMA
;
1331 unit
->au_XferModes
&=~AF_XFER_DMA
;
1334 static void common_SetBestXferMode(struct ata_Unit
* unit
)
1337 int max
= AB_XFER_UDMA7
;
1339 if (unit
->au_DMAPort
== 0)
1342 * make sure you reduce scan search to pio here!
1343 * otherwise this and above function will fall into infinite loop
1345 DINIT(bug("[ATA%02ld] This controller does not own DMA port\n", unit
->au_UnitNum
));
1349 for (iter
=max
; iter
>=AB_XFER_PIO0
; --iter
)
1351 if (unit
->au_XferModes
& (1<<iter
))
1353 common_SetXferMode(unit
, iter
);
1357 bug("[ATA%02ld] ERROR: device never reported any valid xfer modes. will continue at default\n", unit
->au_UnitNum
);
1358 common_SetXferMode(unit
, AB_XFER_PIO0
);
1361 void common_DetectXferModes(struct ata_Unit
* unit
)
1365 DINIT(bug("[ATA%02ld] Supports\n", unit
->au_UnitNum
));
1367 if (unit
->au_Drive
->id_Commands4
& (1 << 4))
1369 DINIT(bug("[ATA%02ld] - Packet interface\n", unit
->au_UnitNum
));
1370 unit
->au_XferModes
|= AF_XFER_PACKET
;
1371 unit
->au_DirectSCSI
= atapi_DirectSCSI
;
1373 else if (unit
->au_Drive
->id_Commands5
& (1 << 10))
1375 /* ATAPI devices do not use this bit. */
1376 DINIT(bug("[ATA%02ld] - 48bit I/O\n", unit
->au_UnitNum
));
1377 unit
->au_XferModes
|= AF_XFER_48BIT
;
1380 if ((unit
->au_XferModes
& AF_XFER_PACKET
) || (unit
->au_Drive
->id_Capabilities
& (1<< 9)))
1382 DINIT(bug("[ATA%02ld] - LBA Addressing\n", unit
->au_UnitNum
));
1383 unit
->au_XferModes
|= AF_XFER_LBA
;
1387 DINIT(bug("[ATA%02ld] - DEVICE DOES NOT SUPPORT LBA ADDRESSING >> THIS IS A POTENTIAL PROBLEM <<\n", unit
->au_UnitNum
));
1390 if (unit
->au_Drive
->id_RWMultipleSize
& 0xff)
1392 DINIT(bug("[ATA%02ld] - R/W Multiple (%ld sectors per xfer)\n", unit
->au_UnitNum
, unit
->au_Drive
->id_RWMultipleSize
& 0xff));
1393 unit
->au_XferModes
|= AF_XFER_RWMULTI
;
1396 if (unit
->au_Drive
->id_PIOSupport
& 0xff)
1398 DINIT(bug("[ATA%02ld] - ", unit
->au_UnitNum
));
1399 for (iter
=0; iter
<8; iter
++)
1401 if (unit
->au_Drive
->id_MWDMASupport
& (1 << iter
))
1403 DINIT(bug("PIO%ld ", iter
));
1404 unit
->au_XferModes
|= AF_XFER_PIO(iter
);;
1410 if (unit
->au_Drive
->id_Capabilities
& (1<<8))
1412 DINIT(bug("[ATA%02ld] DMA:\n", unit
->au_UnitNum
));
1413 if (unit
->au_Drive
->id_MWDMASupport
& 0xff)
1415 DINIT(bug("[ATA%02ld] - ", unit
->au_UnitNum
));
1416 for (iter
=0; iter
<8; iter
++)
1418 if (unit
->au_Drive
->id_MWDMASupport
& (1 << iter
))
1420 unit
->au_XferModes
|= AF_XFER_MDMA(iter
);;
1421 if (unit
->au_Drive
->id_MWDMASupport
& (256 << iter
))
1423 DINIT(bug("[MDMA%ld] ", iter
));
1427 DINIT(bug("MDMA%ld ", iter
));
1434 if (unit
->au_Drive
->id_UDMASupport
& 0xff)
1436 DINIT(bug("[ATA%02ld] - ", unit
->au_UnitNum
));
1437 for (iter
=0; iter
<8; iter
++)
1439 if (unit
->au_Drive
->id_UDMASupport
& (1 << iter
))
1441 unit
->au_XferModes
|= AF_XFER_MDMA(iter
);;
1442 if (unit
->au_Drive
->id_UDMASupport
& (256 << iter
))
1444 DINIT(bug("[UDMA%ld] ", iter
));
1448 DINIT(bug("UDMA%ld ", iter
));
1457 #define SWAP_LE_WORD(x) (x) = AROS_LE2WORD((x))
1458 #define SWAP_LE_LONG(x) (x) = AROS_LE2LONG((x))
1459 #define SWAP_LE_QUAD(x) (x) = AROS_LE2LONG((x)>>32) | AROS_LE2LONG((x) & 0xffffffff) << 32
1461 ULONG
atapi_Identify(struct ata_Unit
* unit
)
1463 ata_CommandBlock acb
=
1472 sizeof(struct DriveIdent
),
1478 ata_SelectUnit(unit
);
1480 if (ata_exec_cmd(unit
, &acb
))
1482 return IOERR_OPENFAIL
;
1485 #if (AROS_BIG_ENDIAN != 0)
1486 SWAP_LE_WORD(unit
->au_Drive
->id_General
);
1487 SWAP_LE_WORD(unit
->au_Drive
->id_OldCylinders
);
1488 SWAP_LE_WORD(unit
->au_Drive
->id_SpecificConfig
);
1489 SWAP_LE_WORD(unit
->au_Drive
->id_OldHeads
);
1490 SWAP_LE_WORD(unit
->au_Drive
->id_OldSectors
);
1491 SWAP_LE_WORD(unit
->au_Drive
->id_RWMultipleSize
);
1492 SWAP_LE_WORD(unit
->au_Drive
->id_Capabilities
);
1493 SWAP_LE_WORD(unit
->au_Drive
->id_OldCaps
);
1494 SWAP_LE_WORD(unit
->au_Drive
->id_OldPIO
);
1495 SWAP_LE_WORD(unit
->au_Drive
->id_ConfigAvailable
);
1496 SWAP_LE_WORD(unit
->au_Drive
->id_OldLCylinders
);
1497 SWAP_LE_WORD(unit
->au_Drive
->id_OldLHeads
);
1498 SWAP_LE_WORD(unit
->au_Drive
->id_OldLSectors
);
1499 SWAP_LE_WORD(unit
->au_Drive
->id_RWMultipleTrans
);
1500 SWAP_LE_WORD(unit
->au_Drive
->id_MWDMASupport
);
1501 SWAP_LE_WORD(unit
->au_Drive
->id_PIOSupport
);
1502 SWAP_LE_WORD(unit
->au_Drive
->id_MWDMA_MinCycleTime
);
1503 SWAP_LE_WORD(unit
->au_Drive
->id_MWDMA_DefCycleTime
);
1504 SWAP_LE_WORD(unit
->au_Drive
->id_PIO_MinCycleTime
);
1505 SWAP_LE_WORD(unit
->au_Drive
->id_PIO_MinCycleTImeIORDY
);
1506 SWAP_LE_WORD(unit
->au_Drive
->id_QueueDepth
);
1507 SWAP_LE_WORD(unit
->au_Drive
->id_ATAVersion
);
1508 SWAP_LE_WORD(unit
->au_Drive
->id_ATARevision
);
1509 SWAP_LE_WORD(unit
->au_Drive
->id_Commands1
);
1510 SWAP_LE_WORD(unit
->au_Drive
->id_Commands2
);
1511 SWAP_LE_WORD(unit
->au_Drive
->id_Commands3
);
1512 SWAP_LE_WORD(unit
->au_Drive
->id_Commands4
);
1513 SWAP_LE_WORD(unit
->au_Drive
->id_Commands5
);
1514 SWAP_LE_WORD(unit
->au_Drive
->id_Commands6
);
1515 SWAP_LE_WORD(unit
->au_Drive
->id_UDMASupport
);
1516 SWAP_LE_WORD(unit
->au_Drive
->id_SecurityEraseTime
);
1517 SWAP_LE_WORD(unit
->au_Drive
->id_EnchSecurityEraseTime
);
1518 SWAP_LE_WORD(unit
->au_Drive
->id_CurrentAdvowerMode
);
1519 SWAP_LE_WORD(unit
->au_Drive
->id_MasterPwdRevision
);
1520 SWAP_LE_WORD(unit
->au_Drive
->id_HWResetResult
);
1521 SWAP_LE_WORD(unit
->au_Drive
->id_AcousticManagement
);
1522 SWAP_LE_WORD(unit
->au_Drive
->id_StreamMinimunReqSize
);
1523 SWAP_LE_WORD(unit
->au_Drive
->id_StreamingTimeDMA
);
1524 SWAP_LE_WORD(unit
->au_Drive
->id_StreamingLatency
);
1525 SWAP_LE_WORD(unit
->au_Drive
->id_StreamingTimePIO
);
1526 SWAP_LE_WORD(unit
->au_Drive
->id_PhysSectorSize
);
1527 SWAP_LE_WORD(unit
->au_Drive
->id_RemMediaStatusNotificationFeatures
);
1528 SWAP_LE_WORD(unit
->au_Drive
->id_SecurityStatus
);
1530 SWAP_LE_LONG(unit
->au_Drive
->id_WordsPerLogicalSector
);
1531 SWAP_LE_LONG(unit
->au_Drive
->id_LBASectors
);
1532 SWAP_LE_LONG(unit
->au_Drive
->id_StreamingGranularity
);
1534 SWAP_LE_QUAD(unit
->au_Drive
->id_LBA48Sectors
);
1538 DUMP(dump(unit
->au_Drive
, sizeof(struct DriveIdent
)));
1540 unit
->au_SectorShift
= 11;
1541 unit
->au_Read32
= atapi_Read
;
1542 unit
->au_Write32
= atapi_Write
;
1543 unit
->au_DirectSCSI
= atapi_DirectSCSI
;
1544 unit
->au_Eject
= atapi_Eject
;
1545 unit
->au_Flags
= AF_DiscChanged
;
1546 unit
->au_DevType
= (unit
->au_Drive
->id_General
>>8) & 0x1f;
1547 unit
->au_XferModes
= AF_XFER_PACKET
;
1549 ata_strcpy(unit
->au_Drive
->id_Model
, unit
->au_Model
, 40);
1550 ata_strcpy(unit
->au_Drive
->id_SerialNumber
, unit
->au_SerialNumber
, 20);
1551 ata_strcpy(unit
->au_Drive
->id_FirmwareRev
, unit
->au_FirmwareRev
, 8);
1553 bug("[ATA%02ld] Unit info: %s / %s / %s\n", unit
->au_UnitNum
, unit
->au_Model
, unit
->au_SerialNumber
, unit
->au_FirmwareRev
);
1554 common_DetectXferModes(unit
);
1555 common_SetBestXferMode(unit
);
1557 if (unit
->au_Drive
->id_General
& 0x80)
1559 DINIT(bug("[ATA%02ld] Device is removable.\n", unit
->au_UnitNum
));
1560 unit
->au_Flags
|= AF_Removable
;
1563 unit
->au_Capacity
= unit
->au_Drive
->id_LBASectors
;
1564 unit
->au_Capacity48
= unit
->au_Drive
->id_LBA48Sectors
;
1565 bug("[ATA%02ld] Unit info: %07lx 28bit / %04lx:%08lx 48bit addressable blocks\n", unit
->au_UnitNum
, unit
->au_Capacity
, (ULONG
)(unit
->au_Capacity48
>> 32), (ULONG
)(unit
->au_Capacity48
& 0xfffffffful
));
1568 * ok, this is not very original, but quite compatible :P
1570 switch (unit
->au_DevType
)
1574 case DG_OPTICAL_DISK
:
1575 unit
->au_SectorShift
= 11;
1577 unit
->au_Sectors
= 75;
1578 unit
->au_Cylinders
= 4440;
1581 case DG_DIRECT_ACCESS
:
1582 unit
->au_SectorShift
= 9;
1583 if (!strcmp("LS-120", &unit
->au_Model
[0]))
1586 unit
->au_Sectors
= 18;
1587 unit
->au_Cylinders
= 6848;
1589 else if (!strcmp("ZIP 100 ", &unit
->au_Model
[8]))
1592 unit
->au_Sectors
= 64;
1593 unit
->au_Cylinders
= 3072;
1598 atapi_TestUnitOK(unit
);
1603 ULONG
ata_Identify(struct ata_Unit
* unit
)
1605 ata_CommandBlock acb
=
1607 ATA_IDENTIFY_DEVICE
,
1614 sizeof(struct DriveIdent
),
1620 if (ata_exec_cmd(unit
, &acb
))
1622 return IOERR_OPENFAIL
;
1625 #if (AROS_BIG_ENDIAN != 0)
1626 SWAP_LE_WORD(unit
->au_Drive
->id_General
);
1627 SWAP_LE_WORD(unit
->au_Drive
->id_OldCylinders
);
1628 SWAP_LE_WORD(unit
->au_Drive
->id_SpecificConfig
);
1629 SWAP_LE_WORD(unit
->au_Drive
->id_OldHeads
);
1630 SWAP_LE_WORD(unit
->au_Drive
->id_OldSectors
);
1631 SWAP_LE_WORD(unit
->au_Drive
->id_RWMultipleSize
);
1632 SWAP_LE_WORD(unit
->au_Drive
->id_Capabilities
);
1633 SWAP_LE_WORD(unit
->au_Drive
->id_OldCaps
);
1634 SWAP_LE_WORD(unit
->au_Drive
->id_OldPIO
);
1635 SWAP_LE_WORD(unit
->au_Drive
->id_ConfigAvailable
);
1636 SWAP_LE_WORD(unit
->au_Drive
->id_OldLCylinders
);
1637 SWAP_LE_WORD(unit
->au_Drive
->id_OldLHeads
);
1638 SWAP_LE_WORD(unit
->au_Drive
->id_OldLSectors
);
1639 SWAP_LE_WORD(unit
->au_Drive
->id_RWMultipleTrans
);
1640 SWAP_LE_WORD(unit
->au_Drive
->id_MWDMASupport
);
1641 SWAP_LE_WORD(unit
->au_Drive
->id_PIOSupport
);
1642 SWAP_LE_WORD(unit
->au_Drive
->id_MWDMA_MinCycleTime
);
1643 SWAP_LE_WORD(unit
->au_Drive
->id_MWDMA_DefCycleTime
);
1644 SWAP_LE_WORD(unit
->au_Drive
->id_PIO_MinCycleTime
);
1645 SWAP_LE_WORD(unit
->au_Drive
->id_PIO_MinCycleTImeIORDY
);
1646 SWAP_LE_WORD(unit
->au_Drive
->id_QueueDepth
);
1647 SWAP_LE_WORD(unit
->au_Drive
->id_ATAVersion
);
1648 SWAP_LE_WORD(unit
->au_Drive
->id_ATARevision
);
1649 SWAP_LE_WORD(unit
->au_Drive
->id_Commands1
);
1650 SWAP_LE_WORD(unit
->au_Drive
->id_Commands2
);
1651 SWAP_LE_WORD(unit
->au_Drive
->id_Commands3
);
1652 SWAP_LE_WORD(unit
->au_Drive
->id_Commands4
);
1653 SWAP_LE_WORD(unit
->au_Drive
->id_Commands5
);
1654 SWAP_LE_WORD(unit
->au_Drive
->id_Commands6
);
1655 SWAP_LE_WORD(unit
->au_Drive
->id_UDMASupport
);
1656 SWAP_LE_WORD(unit
->au_Drive
->id_SecurityEraseTime
);
1657 SWAP_LE_WORD(unit
->au_Drive
->id_EnchSecurityEraseTime
);
1658 SWAP_LE_WORD(unit
->au_Drive
->id_CurrentAdvowerMode
);
1659 SWAP_LE_WORD(unit
->au_Drive
->id_MasterPwdRevision
);
1660 SWAP_LE_WORD(unit
->au_Drive
->id_HWResetResult
);
1661 SWAP_LE_WORD(unit
->au_Drive
->id_AcousticManagement
);
1662 SWAP_LE_WORD(unit
->au_Drive
->id_StreamMinimunReqSize
);
1663 SWAP_LE_WORD(unit
->au_Drive
->id_StreamingTimeDMA
);
1664 SWAP_LE_WORD(unit
->au_Drive
->id_StreamingLatency
);
1665 SWAP_LE_WORD(unit
->au_Drive
->id_StreamingTimePIO
);
1666 SWAP_LE_WORD(unit
->au_Drive
->id_PhysSectorSize
);
1667 SWAP_LE_WORD(unit
->au_Drive
->id_RemMediaStatusNotificationFeatures
);
1668 SWAP_LE_WORD(unit
->au_Drive
->id_SecurityStatus
);
1670 SWAP_LE_LONG(unit
->au_Drive
->id_WordsPerLogicalSector
);
1671 SWAP_LE_LONG(unit
->au_Drive
->id_LBASectors
);
1672 SWAP_LE_LONG(unit
->au_Drive
->id_StreamingGranularity
);
1674 SWAP_LE_QUAD(unit
->au_Drive
->id_LBA48Sectors
);
1677 DUMP(dump(unit
->au_Drive
, sizeof(struct DriveIdent
)));
1679 unit
->au_SectorShift
= 9;
1680 unit
->au_DevType
= DG_DIRECT_ACCESS
;
1681 unit
->au_Read32
= ata_ReadSector32
;
1682 unit
->au_Write32
= ata_WriteSector32
;
1683 unit
->au_DirectSCSI
= atapi_DirectSCSI
;
1684 unit
->au_Eject
= ata_Eject
;
1685 unit
->au_XferModes
= 0;
1686 unit
->au_Flags
|= AF_DiscPresent
| AF_DiscChanged
;
1687 unit
->au_DevType
= DG_DIRECT_ACCESS
;
1689 ata_strcpy(unit
->au_Drive
->id_Model
, unit
->au_Model
, 40);
1690 ata_strcpy(unit
->au_Drive
->id_SerialNumber
, unit
->au_SerialNumber
, 20);
1691 ata_strcpy(unit
->au_Drive
->id_FirmwareRev
, unit
->au_FirmwareRev
, 8);
1693 bug("[ATA%02ld] Unit info: %s / %s / %s\n", unit
->au_UnitNum
, unit
->au_Model
, unit
->au_SerialNumber
, unit
->au_FirmwareRev
);
1694 common_DetectXferModes(unit
);
1695 common_SetBestXferMode(unit
);
1697 if (unit
->au_Drive
->id_General
& 0x80)
1699 DINIT(bug("[ATA%02ld] Device is removable.\n", unit
->au_UnitNum
));
1700 unit
->au_Flags
|= AF_Removable
;
1703 unit
->au_Capacity
= unit
->au_Drive
->id_LBASectors
;
1704 unit
->au_Capacity48
= unit
->au_Drive
->id_LBA48Sectors
;
1705 bug("[ATA%02ld] Unit info: %07lx 28bit / %04lx:%08lx 48bit addressable blocks\n", unit
->au_UnitNum
, unit
->au_Capacity
, (ULONG
)(unit
->au_Capacity48
>> 32), (ULONG
)(unit
->au_Capacity48
& 0xfffffffful
));
1708 For drive capacities > 8.3GB assume maximal possible layout.
1709 It really doesn't matter here, as BIOS will not handle them in
1711 i guess this just solves that weirdo div-by-zero crash, if anything else...
1713 if ((unit
->au_Drive
->id_LBA48Sectors
> (63 * 255 * 1024)) ||
1714 (unit
->au_Drive
->id_LBASectors
> (63 * 255 * 1024)))
1718 * TODO: this shouldn't be casted down here.
1720 ULONG sec
= unit
->au_Capacity48
;
1722 if (sec
< unit
->au_Capacity48
)
1725 if (sec
< unit
->au_Capacity
)
1726 sec
= unit
->au_Capacity
;
1728 unit
->au_Sectors
= 63;
1731 * keep dividing by 2
1735 if (((sec
>> 1) << 1) != sec
)
1737 if ((div
<< 1) > 255)
1745 if (((sec
/ 3) * 3) != sec
)
1747 if ((div
* 3) > 255)
1753 unit
->au_Cylinders
= sec
;
1754 unit
->au_Heads
= div
;
1758 unit
->au_Cylinders
= unit
->au_Drive
->id_OldLCylinders
;
1759 unit
->au_Heads
= unit
->au_Drive
->id_OldLHeads
;
1760 unit
->au_Sectors
= unit
->au_Drive
->id_OldLSectors
;
1767 * ata read32 commands
1769 static ULONG
ata_ReadSector32(struct ata_Unit
*unit
, ULONG block
, ULONG count
, APTR buffer
, ULONG
*act
)
1771 ata_CommandBlock acb
=
1780 count
<< unit
->au_SectorShift
,
1788 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
1791 *act
= count
<< unit
->au_SectorShift
;
1795 static ULONG
ata_ReadMultiple32(struct ata_Unit
*unit
, ULONG block
, ULONG count
, APTR buffer
, ULONG
*act
)
1797 ata_CommandBlock acb
=
1801 unit
->au_Drive
->id_RWMultipleSize
& 0xff,
1806 count
<< unit
->au_SectorShift
,
1814 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
1817 *act
= count
<< unit
->au_SectorShift
;
1821 static ULONG
ata_ReadDMA32(struct ata_Unit
*unit
, ULONG block
, ULONG count
, APTR buffer
, ULONG
*act
)
1824 ata_CommandBlock acb
=
1833 count
<< unit
->au_SectorShift
,
1840 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
1843 *act
= count
<< unit
->au_SectorShift
;
1849 * ata read64 commands
1851 static ULONG
ata_ReadSector64(struct ata_Unit
*unit
, UQUAD block
, ULONG count
, APTR buffer
, ULONG
*act
)
1853 ata_CommandBlock acb
=
1862 count
<< unit
->au_SectorShift
,
1867 register ULONG err
= 0;
1870 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
1873 *act
= count
<< unit
->au_SectorShift
;
1877 static ULONG
ata_ReadMultiple64(struct ata_Unit
*unit
, UQUAD block
, ULONG count
, APTR buffer
, ULONG
*act
)
1879 ata_CommandBlock acb
=
1881 ATA_READ_MULTIPLE64
,
1883 unit
->au_Drive
->id_RWMultipleSize
& 0xff,
1888 count
<< unit
->au_SectorShift
,
1896 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
1899 *act
= count
<< unit
->au_SectorShift
;
1903 static ULONG
ata_ReadDMA64(struct ata_Unit
*unit
, UQUAD block
, ULONG count
, APTR buffer
, ULONG
*act
)
1905 ata_CommandBlock acb
=
1914 count
<< unit
->au_SectorShift
,
1922 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
1925 *act
= count
<< unit
->au_SectorShift
;
1931 * ata write32 commands
1933 static ULONG
ata_WriteSector32(struct ata_Unit
*unit
, ULONG block
, ULONG count
, APTR buffer
, ULONG
*act
)
1935 ata_CommandBlock acb
=
1944 count
<< unit
->au_SectorShift
,
1952 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
1955 *act
= count
<< unit
->au_SectorShift
;
1959 static ULONG
ata_WriteMultiple32(struct ata_Unit
*unit
, ULONG block
, ULONG count
, APTR buffer
, ULONG
*act
)
1961 ata_CommandBlock acb
=
1965 unit
->au_Drive
->id_RWMultipleSize
& 0xff,
1970 count
<< unit
->au_SectorShift
,
1978 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
1981 *act
= count
<< unit
->au_SectorShift
;
1985 static ULONG
ata_WriteDMA32(struct ata_Unit
*unit
, ULONG block
, ULONG count
, APTR buffer
, ULONG
*act
)
1987 ata_CommandBlock acb
=
1996 count
<< unit
->au_SectorShift
,
2004 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
2007 *act
= count
<< unit
->au_SectorShift
;
2013 * ata write64 commands
2015 static ULONG
ata_WriteSector64(struct ata_Unit
*unit
, UQUAD block
, ULONG count
, APTR buffer
, ULONG
*act
)
2017 ata_CommandBlock acb
=
2026 count
<< unit
->au_SectorShift
,
2034 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
2037 *act
= count
<< unit
->au_SectorShift
;
2041 static ULONG
ata_WriteMultiple64(struct ata_Unit
*unit
, UQUAD block
, ULONG count
, APTR buffer
, ULONG
*act
)
2043 ata_CommandBlock acb
=
2045 ATA_WRITE_MULTIPLE64
,
2047 unit
->au_Drive
->id_RWMultipleSize
& 0xff,
2052 count
<< unit
->au_SectorShift
,
2060 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
2063 *act
= count
<< unit
->au_SectorShift
;
2067 static ULONG
ata_WriteDMA64(struct ata_Unit
*unit
, UQUAD block
, ULONG count
, APTR buffer
, ULONG
*act
)
2069 ata_CommandBlock acb
=
2078 count
<< unit
->au_SectorShift
,
2086 if (0 != (err
= ata_exec_blk(unit
, &acb
)))
2089 *act
= count
<< unit
->au_SectorShift
;
2094 * ata miscellaneous commands
2096 static ULONG
ata_Eject(struct ata_Unit
*unit
)
2098 ata_CommandBlock acb
=
2113 return ata_exec_cmd(unit
, &acb
);
2119 int atapi_TestUnitOK(struct ata_Unit
*unit
)
2127 struct SCSICmd sc
= {
2131 sc
.scsi_Command
= (void*) &cmd
;
2132 sc
.scsi_CmdLength
= sizeof(cmd
);
2133 sc
.scsi_SenseData
= (void*)&sense
;
2134 sc
.scsi_SenseLength
= sizeof(sense
);
2135 sc
.scsi_Flags
= SCSIF_AUTOSENSE
;
2137 unit
->au_DirectSCSI(unit
, &sc
);
2138 unit
->au_SenseKey
= sense
[2];
2141 * we may have just lost the disc...?
2144 * per MMC, drives are expected to return 02-3a-0# status, when disc is not present
2145 * that would translate into following code:
2146 * int p1 = ((sense[2] == 2) && (sense[12] == 0x3a)) ? 1 : 0;
2147 * unfortunately, it's what MMC says, not what vendors code.
2149 int p1
= (sense
[2] == 2) ? 1 : 0;
2150 int p2
= (0 != (AF_DiscPresent
& unit
->au_Flags
)) ? 1 : 0;
2154 //unit->au_Flags ^= AF_DiscPresent;
2156 unit
->au_Flags
|= AF_DiscPresent
;
2158 unit
->au_Flags
&= ~AF_DiscPresent
;
2160 unit
->au_Flags
|= AF_DiscChanged
;
2163 DATAPI(bug("[ATA%02ld] Test Unit Ready sense: %02lx, Media %s\n", unit
->au_UnitNum
, sense
[2], unit
->au_Flags
& AF_DiscPresent
? "PRESENT" : "ABSENT"));
2167 static ULONG
atapi_Read(struct ata_Unit
*unit
, ULONG block
, ULONG count
, APTR buffer
, ULONG
*act
)
2170 SCSI_READ10
, 0, block
>>24, block
>>16, block
>>8, block
, 0, count
>>8, count
, 0
2172 struct SCSICmd sc
= {
2176 sc
.scsi_Command
= (void*) &cmd
;
2177 sc
.scsi_CmdLength
= sizeof(cmd
);
2178 sc
.scsi_Data
= buffer
;
2179 sc
.scsi_Length
= count
<< unit
->au_SectorShift
;
2180 sc
.scsi_Flags
= SCSIF_READ
;
2182 return unit
->au_DirectSCSI(unit
, &sc
);
2185 static ULONG
atapi_Write(struct ata_Unit
*unit
, ULONG block
, ULONG count
, APTR buffer
, ULONG
*act
)
2188 SCSI_WRITE10
, 0, block
>>24, block
>>16, block
>>8, block
, 0, count
>>8, count
, 0
2190 struct SCSICmd sc
= {
2194 sc
.scsi_Command
= (void*) &cmd
;
2195 sc
.scsi_CmdLength
= sizeof(cmd
);
2196 sc
.scsi_Data
= buffer
;
2197 sc
.scsi_Length
= count
<< unit
->au_SectorShift
;
2198 sc
.scsi_Flags
= SCSIF_WRITE
;
2200 return unit
->au_DirectSCSI(unit
, &sc
);
2203 static ULONG
atapi_Eject(struct ata_Unit
*unit
)
2205 struct atapi_StartStop cmd
= {
2206 command
: SCSI_STARTSTOP
,
2208 flags
: ATAPI_SS_EJECT
,
2211 struct SCSICmd sc
= {
2215 sc
.scsi_Command
= (void*) &cmd
;
2216 sc
.scsi_CmdLength
= sizeof(cmd
);
2217 sc
.scsi_Flags
= SCSIF_READ
;
2219 return unit
->au_DirectSCSI(unit
, &sc
);
2222 ULONG
atapi_RequestSense(struct ata_Unit
* unit
, UBYTE
* sense
, ULONG senselen
)
2225 3, 0, 0, 0, senselen
& 0xfe, 0
2227 struct SCSICmd sc
= {
2231 if ((senselen
== 0) || (sense
== 0))
2235 sc
.scsi_Data
= (void*)sense
;
2236 sc
.scsi_Length
= senselen
& 0xfe;
2237 sc
.scsi_Command
= (void*)&cmd
;
2238 sc
.scsi_CmdLength
= 6;
2239 sc
.scsi_Flags
= SCSIF_READ
;
2241 unit
->au_DirectSCSI(unit
, &sc
);
2243 DATAPI(dump(sense
, senselen
));
2244 DATAPI(bug("[SENSE] sensed data: %lx %lx %lx\n", sense
[2]&0xf, sense
[12], sense
[13]));
2245 return ((sense
[2]&0xf)<<16) | (sense
[12]<<8) | (sense
[13]);
2248 ULONG
ata_ReadSignature(struct ata_Bus
*bus
, int unit
)
2250 ULONG port
= bus
->ab_Port
;
2253 /* Check basic signature. All live devices should provide it */
2254 tmp1
= ata_in(ata_Count
, port
);
2255 tmp2
= ata_in(ata_LBALow
, port
);
2256 DINIT(bug("[ATA ] Checking Count / LBA against expected values (%d:%d)\n", tmp1
, tmp2
));
2258 DINIT(bug("[ATA ] Status %08lx Device %08lx\n", ata_in(ata_Status
, port
), ata_in(ata_DevHead
, port
)));
2260 if ((tmp1
== 0x01) && (tmp2
== 0x01))
2262 /* Ok, ATA/ATAPI device. Get detailed signature */
2263 DINIT(bug("[ATA ] Found an ATA[PI] Device. Attempting to detect specific subtype\n"));
2265 tmp1
= ata_in(ata_LBAMid
, port
);
2266 tmp2
= ata_in(ata_LBAHigh
, port
);
2268 DINIT(bug("[ATA ] Subtype check returned %02lx:%02lx (%04lx)\n", tmp1
, tmp2
, (tmp1
<< 8) | tmp2
));
2271 switch ((tmp1
<< 8) | tmp2
)
2274 if (0 == (ata_ReadStatus(bus
) & 0xfe))
2276 ata_out(0xa0 | (unit
<< 4), ata_DevHead
, port
);
2277 ata_out(ATA_EXECUTE_DIAG
, ata_Command
, port
);
2278 ata_out(0xa0 | (unit
<< 4), ata_DevHead
, port
);
2280 while (ata_ReadStatus(bus
) & ATAF_BUSY
)
2283 DINIT(bug("[ATA ] Further validating ATA signature: %lx & 0x7f = 1, %lx & 0x10 = unit\n", ata_in(ata_Error
, port
), ata_in(ata_DevHead
, port
)));
2285 if ((1 == (0x7f & ata_in(ata_Error
, port
))) &&
2286 (unit
== ((ata_in(ata_DevHead
, port
) >> 4) & 1)))
2288 DINIT(bug("[ATA ] Found *valid* signature for ATA device\n"));
2294 DINIT(bug("[ATA ] Found signature for ATAPI device\n"));
2298 DINIT(bug("[ATA ] Found signature for SATA device\n"));
2302 DINIT(bug("[ATA ] Found signature for SATAPI device\n"));
2306 if (((tmp1
| tmp2
) == 0xff) &&
2307 ((tmp1
& tmp2
) == 0x00))
2309 bug("[ATA ] Found valid subtype, but don't know how to handle this device: %02lx %02lx\n", tmp1
, tmp2
);
2313 bug("[ATA ] Invalid signature: %02lx %02lx\n", tmp1
, tmp2
);
2322 void ata_ResetBus(struct timerequest
*tr
, struct ata_Bus
*bus
)
2324 ULONG alt
= bus
->ab_Alt
;
2325 ULONG port
= bus
->ab_Port
;
2329 * issue and clear the software reset signal
2331 /* at this time both devices should report ready immediately */
2332 for (id
= 0; id
< 2; id
++)
2334 if (DEV_NONE
!= bus
->ab_Dev
[id
])
2336 ata_out(0xa0 | (id
<< 4), ata_DevHead
, port
);
2339 ata_out(0x04, ata_AltControl
, alt
);
2340 ata_usleep(tr
, 10); /* minimum required: 5us */
2341 ata_out(0x02, ata_AltControl
, alt
);
2342 ata_usleep(tr
, 20000); /* minimum required: 2ms */
2344 ata_out(0xa0 | (id
<< 4), ata_DevHead
, port
);
2347 while (0 != (ata_in(ata_Status
, port
) & ATAF_BUSY
))
2348 ata_usleep(tr
, 200);
2350 bus
->ab_Dev
[id
] = ata_ReadSignature(bus
, id
);
2356 * --------------------------------------------------------------
2357 * - here ends the code that makes any sense. rest to be removed -
2358 * --------------------------------------------------------------
2362 void ata_usleep(struct timerequest
*tr
, ULONG usec
)
2364 tr
->tr_node
.io_Command
= TR_ADDREQUEST
;
2365 tr
->tr_time
.tv_micro
= usec
% 1000000;
2366 tr
->tr_time
.tv_secs
= usec
/ 1000000;
2368 DoIO((struct IORequest
*)tr
);
2372 Device scan routines - TO BE REPLACED
2377 void ata_InitBus(struct ata_Bus
*bus
)
2379 ULONG port
= bus
->ab_Port
;
2382 struct MsgPort
*p
= CreateMsgPort();
2383 struct timerequest
*tr
= (struct timerequest
*)CreateIORequest((struct MsgPort
*)p
,
2384 sizeof(struct timerequest
));
2385 OpenDevice("timer.device", UNIT_MICROHZ
, (struct IORequest
*)tr
, 0);
2387 bus
->ab_Dev
[0] = DEV_NONE
;
2388 bus
->ab_Dev
[1] = DEV_NONE
;
2390 /* Disable IDE IRQ */
2391 ata_EnableIRQ(bus
, FALSE
);
2393 /* Select device 0 */
2394 ata_out(0xa0, ata_DevHead
, port
);
2395 ata_usleep(tr
, 100);
2397 /* Write some pattern to registers */
2398 ata_out(0x55, ata_Count
, port
);
2399 ata_out(0xaa, ata_LBALow
, port
);
2400 ata_out(0xaa, ata_Count
, port
);
2401 ata_out(0x55, ata_LBALow
, port
);
2402 ata_out(0x55, ata_Count
, port
);
2403 ata_out(0xaa, ata_LBALow
, port
);
2405 tmp1
= ata_in(ata_Count
, port
);
2406 tmp2
= ata_in(ata_LBALow
, port
);
2408 if ((tmp1
== 0x55) && (tmp2
== 0xaa))
2409 bus
->ab_Dev
[0] = DEV_UNKNOWN
;
2411 /* Select device 1 */
2412 ata_out(0xb0, ata_DevHead
, port
);
2413 ata_usleep(tr
, 100);
2415 /* Write some pattern to registers */
2416 ata_out(0x55, ata_Count
, port
);
2417 ata_out(0xaa, ata_LBALow
, port
);
2418 ata_out(0xaa, ata_Count
, port
);
2419 ata_out(0x55, ata_LBALow
, port
);
2420 ata_out(0x55, ata_Count
, port
);
2421 ata_out(0xaa, ata_LBALow
, port
);
2423 tmp1
= ata_in(ata_Count
, port
);
2424 tmp2
= ata_in(ata_LBALow
, port
);
2426 if ((tmp1
== 0x55) && (tmp2
== 0xaa))
2427 bus
->ab_Dev
[1] = DEV_UNKNOWN
;
2429 ata_ResetBus(tr
, bus
);
2431 CloseDevice((struct IORequest
*)tr
);
2432 DeleteIORequest((struct IORequest
*)tr
);
2437 * not really sure what this is meant to be - TO BE REPLACED
2439 static const ULONG ErrorMap
[] = {
2458 static ULONG
atapi_EndCmd(struct ata_Unit
*unit
)
2463 * read alternate status register (per specs)
2465 status
= ata_in(ata_AltStatus
, unit
->au_Bus
->ab_Alt
);
2466 DATAPI(bug("[ATAPI] Alternate status: %lx\n", status
));
2468 status
= ata_in(atapi_Status
, unit
->au_Bus
->ab_Port
);
2470 DATAPI(bug("[ATAPI] Command complete. Status: %lx\n", status
));
2472 if (!(status
& ATAPIF_CHECK
))
2478 status
= ata_in(atapi_Error
, unit
->au_Bus
->ab_Port
);
2479 DATAPI(bug("[ATAPI] Error code %lx\n", status
>> 4));
2480 return ErrorMap
[status
>> 4];
2485 * vim: ts=4 et sw=4 fdm=marker fmr={,}