2 Copyright © 2004-2009, The AROS Development Team. All rights reserved
11 * ---------- ------------------ -------------------------------------------------------------------
12 * 2008-04-25 P. Fedin Brought back device discovery for old machines without PCI IDE controllers
13 * 2008-01-25 T. Wiszkowski Rebuilt, rearranged and partially fixed 60% of the code here
14 * Enabled implementation to scan for other PCI IDE controllers
15 * Implemented ATAPI Packet Support for both read and write
16 * Corrected ATAPI DMA handling
17 * Fixed major IDE enumeration bugs severely handicapping transfers with more than one controller
18 * Compacted source and implemented major ATA support procedure
19 * Improved DMA and Interrupt management
20 * Removed obsolete code
21 * 2008-01-26 T. Wiszkowski Added 'nodma' flag for ata driver
22 * Moved variables out of global scope
23 * Replaced static variables
24 * 2008-02-08 T. Wiszkowski Fixed DMA accesses for direct scsi devices,
25 * Corrected IO Areas to allow ATA to talk to PCI controllers
26 * 2008-02-24 T. Wiszkowski Corrected unit open function
27 * 2008-03-03 T. Wiszkowski Added drive reselection + setup delay on Init
28 * 2008-03-23 T. Wiszkowski Corrected Alternative Command block position
29 * 2008-03-30 T. Wiszkowski Added workaround for interrupt collision handling; fixed SATA in LEGACY mode.
30 * nForce and Intel SATA chipsets should now be operational.
31 * 2008-04-03 T. Wiszkowski Fixed IRQ flood issue, eliminated and reduced obsolete / redundant code
32 * 2008-04-07 T. Wiszkowski Changed bus timeout mechanism
33 * 2008-04-07 M. Schulz The SiL3114 chip yields Class 0x01 and SubClass 0x80. Therefore it will
34 * not be find with the generic enumeration. Do an explicit search after it
35 * since ata.device may handle it in legacy mode without any issues.
36 * 2008-05-11 T. Wiszkowski Remade the ata trannsfers altogether, corrected the pio/irq handling
37 * medium removal, device detection, bus management and much more
38 * 2008-05-18 T. Wiszkowski corrected device naming to handle cases where more than 10 physical units may be available
39 * 2008-06-24 P. Fedin Added 'NoMulti' flag to disable multisector transfers
40 * 2009-03-05 T. Wiszkowski remade timeouts, added timer-based and benchmark-based delays.
44 #include <aros/debug.h>
46 #include <aros/symbolsets.h>
48 #include <exec/types.h>
49 #include <exec/exec.h>
50 #include <exec/resident.h>
51 #include <exec/tasks.h>
52 #include <exec/memory.h>
53 #include <exec/nodes.h>
54 #include <utility/utility.h>
56 #include <libraries/expansion.h>
57 #include <libraries/configvars.h>
60 #include <dos/filehandler.h>
63 #include <proto/exec.h>
64 #include <proto/timer.h>
65 #include <proto/bootloader.h>
66 #include <proto/expansion.h>
70 #include <proto/oop.h>
75 #include LC_LIBDEFS_FILE
79 struct ataBase
*ATABase
;
85 struct Node atapb_Node
;
90 EnumeratorArgs
*atapb_a
;
96 struct Node atalb_Node
;
101 UBYTE atalb_ControllerID
;
105 #define ATABUSNODEPRI_PROBED 0
106 #define ATABUSNODEPRI_PROBEDLEGACY 100
107 #define ATABUSNODEPRI_LEGACY 50
112 /* static list of io/irqs that we can handle */
113 static struct ata__legacybus
118 UBYTE lb_ControllerID
;
122 {0x1f0, 0x3f4, 14, 0, 0},
123 {0x170, 0x374, 15, 0, 1},
124 {0x168, 0x36c, 10, 1, 0},
125 {0x1e8, 0x3ec, 11, 1, 1},
129 /* Add a bootnode using expansion.library */
130 BOOL
ata_RegisterVolume(ULONG StartCyl
, ULONG EndCyl
, struct ata_Unit
*unit
)
132 struct ExpansionBase
*ExpansionBase
;
133 struct DeviceNode
*devnode
;
135 TEXT dosdevname
[4] = "HD0", *handler
;
138 ExpansionBase
= (struct ExpansionBase
*)OpenLibrary("expansion.library",
143 pp
= AllocMem(24*sizeof(IPTR
), MEMF_PUBLIC
| MEMF_CLEAR
);
147 /* This should be dealt with using some sort of volume manager or such. */
148 switch (unit
->au_DevType
)
150 case DG_DIRECT_ACCESS
:
156 D(bug("[ATA>>]:-ata_RegisterVolume called on unknown devicetype\n"));
159 if (unit
->au_UnitNum
< 10)
160 dosdevname
[2] += unit
->au_UnitNum
% 10;
162 dosdevname
[2] = 'A' - 10 + unit
->au_UnitNum
;
163 pp
[0] = (IPTR
)dosdevname
;
164 pp
[1] = (IPTR
)MOD_NAME_STRING
;
165 pp
[2] = unit
->au_UnitNum
;
166 pp
[DE_TABLESIZE
+ 4] = DE_BOOTBLOCKS
;
167 pp
[DE_SIZEBLOCK
+ 4] = 1 << (unit
->au_SectorShift
- 2);
168 pp
[DE_NUMHEADS
+ 4] = unit
->au_Heads
;
169 pp
[DE_SECSPERBLOCK
+ 4] = 1;
170 pp
[DE_BLKSPERTRACK
+ 4] = unit
->au_Sectors
;
171 pp
[DE_RESERVEDBLKS
+ 4] = 2;
172 pp
[DE_LOWCYL
+ 4] = StartCyl
;
173 pp
[DE_HIGHCYL
+ 4] = EndCyl
;
174 pp
[DE_NUMBUFFERS
+ 4] = 10;
175 pp
[DE_BUFMEMTYPE
+ 4] = MEMF_PUBLIC
| MEMF_CHIP
;
176 pp
[DE_MAXTRANSFER
+ 4] = 0x00200000;
177 pp
[DE_MASK
+ 4] = 0x7FFFFFFE;
178 pp
[DE_BOOTPRI
+ 4] = ((!unit
->au_DevType
) ? 0 : 10);
179 pp
[DE_DOSTYPE
+ 4] = 0x444F5301;
180 pp
[DE_BOOTBLOCKS
+ 4] = 2;
181 devnode
= MakeDosNode(pp
);
185 if(unit
->au_DevType
== DG_DIRECT_ACCESS
)
186 handler
= "afs.handler";
188 handler
= "cdrom.handler";
189 len
= strlen(handler
);
190 if ((devnode
->dn_Handler
=
191 MKBADDR(AllocMem(AROS_BSTR_MEMSIZE4LEN(len
),
192 MEMF_PUBLIC
| MEMF_CLEAR
197 CopyMem(handler
, AROS_BSTR_ADDR(devnode
->dn_Handler
), len
);
198 AROS_BSTR_setstrlen(devnode
->dn_Handler
, len
);
200 D(bug("[ATA>>]:-ata_RegisterVolume: '%s' with StartCyl=%d, EndCyl=%d .. ",
201 &(devnode
->dn_Ext
.dn_AROS
.dn_DevName
[0]), StartCyl
, EndCyl
));
202 AddBootNode(pp
[DE_BOOTPRI
+ 4], 0, devnode
, 0);
210 CloseLibrary((struct Library
*)ExpansionBase
);
216 static void ata_RegisterBus(IPTR IOBase
, IPTR IOAlt
, IPTR INTLine
,
217 IPTR DMABase
, BOOL has80Wire
, EnumeratorArgs
*a
)
220 * ata bus - this is going to be created and linked to the master list here
227 * initialize structure
229 ab
= (struct ata_Bus
*) AllocVecPooled(a
->ATABase
->ata_MemPool
, sizeof(struct ata_Bus
));
233 ab
->ab_Base
= a
->ATABase
;
234 ab
->ab_Port
= IOBase
;
236 ab
->ab_IRQ
= INTLine
;
237 ab
->ab_Dev
[0] = DEV_NONE
;
238 ab
->ab_Dev
[1] = DEV_NONE
;
240 ab
->ab_SleepySignal
= 0;
241 ab
->ab_BusNum
= a
->CurrentBus
++;
243 ab
->ab_Units
[0] = NULL
;
244 ab
->ab_Units
[1] = NULL
;
245 ab
->ab_IntHandler
= (HIDDT_IRQ_Handler
*)AllocVecPooled(a
->ATABase
->ata_MemPool
, sizeof(HIDDT_IRQ_Handler
));
247 ab
->ab_HandleIRQ
= NULL
;
249 D(bug("[ATA>>] ata_RegisterBus: Analysing bus %d, units %d and %d\n", ab
->ab_BusNum
, ab
->ab_BusNum
<<1, (ab
->ab_BusNum
<<1)+1));
250 D(bug("[ATA>>] ata_RegisterBus: IRQ %d, IO: %x:%x, DMA: %x\n", INTLine
, IOBase
, IOAlt
, DMABase
));
255 ab
->ab_PRD
= AllocVecPooled(a
->ATABase
->ata_MemPool
, (PRD_MAX
+1) * 2 * sizeof(struct PRDEntry
));
256 if ((0x10000 - ((ULONG
)ab
->ab_PRD
& 0xffff)) < PRD_MAX
* sizeof(struct PRDEntry
))
257 ab
->ab_PRD
= (void*)((((IPTR
)ab
->ab_PRD
)+0xffff) &~ 0xffff);
260 * scan bus - try to locate all devices (disables irq)
263 for (i
= 0; i
< MAX_BUSUNITS
; i
++)
265 if (ab
->ab_Dev
[i
] > DEV_UNKNOWN
)
267 ab
->ab_Units
[i
] = AllocVecPooled(a
->ATABase
->ata_MemPool
,
268 sizeof(struct ata_Unit
));
269 ab
->ab_Units
[i
]->au_DMAPort
= DMABase
;
270 ab
->ab_Units
[i
]->au_Flags
= has80Wire
? AF_80Wire
: 0;
271 ata_init_unit(ab
, i
);
275 D(bug("[ATA>>] ata_RegisterBus: Bus %ld: Unit 0 - %x, Unit 1 - %x\n", ab
->ab_BusNum
, ab
->ab_Dev
[0], ab
->ab_Dev
[1]));
279 * note: this happens no matter there are devices or not
280 * sort of almost-ready-for-hotplug ;)
282 AddTail((struct List
*)&a
->ATABase
->ata_Buses
, (struct Node
*)ab
);
287 * collect ALL ata/ide capable devices (including SATA and other) and
288 * spawn concurrent tasks.
290 * This function is growing too large. It will shorten drasticly once this whole mess gets converted into c++
294 AROS_UFH3(void, ata_PCIEnumerator_h
,
295 AROS_UFHA(struct Hook
*, hook
, A0
),
296 AROS_UFHA(OOP_Object
*, Device
, A2
),
297 AROS_UFHA(APTR
, message
,A1
))
302 * parameters we will want to acquire
316 BOOL _usablebus
= FALSE
;
321 OOP_AttrBase HiddPCIDeviceAttrBase
= OOP_ObtainAttrBase(IID_Hidd_PCIDevice
);
324 * message to get 80-wire cable report
326 struct pHidd_PCIDevice_ReadConfigLong ataioconfigmsg
=
328 OOP_GetMethodID(IID_Hidd_PCIDevice
, moHidd_PCIDevice_ReadConfigLong
),
335 EnumeratorArgs
*a
= (EnumeratorArgs
*)hook
->h_Data
;
338 * temporary variables
343 * obtain more or less useful data
345 OOP_GetAttr(Device
, aHidd_PCIDevice_VendorID
, &VendorID
);
346 OOP_GetAttr(Device
, aHidd_PCIDevice_ProductID
, &ProductID
);
347 OOP_GetAttr(Device
, aHidd_PCIDevice_Base4
, &DMABase
);
348 OOP_GetAttr(Device
, aHidd_PCIDevice_SubClass
, &SubClass
);
349 OOP_GetAttr(Device
, aHidd_PCIDevice_Interface
, &Interface
);
351 if (a
->ATABase
->ata_NoDMA
|| !(Interface
& 0x80))
354 ATAIOConfig
= OOP_DoMethod(Device
, (OOP_Msg
)&ataioconfigmsg
);
357 * we can have up to two buses assigned to this device
359 for (x
= 0; SubClass
!= 0 && SubClass
!= 7 && x
< MAX_DEVICEBUSES
; x
++)
361 struct ata_LegacyBus
*_legacyBus
= NULL
;
362 BOOL isLegacy
= FALSE
;
366 bug("[ATA ] ata_PCIEnumerator_h: Found IDE device %04x:%04x\n", VendorID
, ProductID
);
370 * obtain I/O bases and interrupt line
372 if ((Interface
& (1 << (x
<< 1))) || SubClass
!= 1)
377 OOP_GetAttr(Device
, aHidd_PCIDevice_Base0
, &IOBase
);
378 OOP_GetAttr(Device
, aHidd_PCIDevice_Size0
, &IOSize
);
379 OOP_GetAttr(Device
, aHidd_PCIDevice_Base1
, &IOAlt
);
380 OOP_GetAttr(Device
, aHidd_PCIDevice_Size1
, &AltSize
);
383 OOP_GetAttr(Device
, aHidd_PCIDevice_Base2
, &IOBase
);
384 OOP_GetAttr(Device
, aHidd_PCIDevice_Size2
, &IOSize
);
385 OOP_GetAttr(Device
, aHidd_PCIDevice_Base3
, &IOAlt
);
386 OOP_GetAttr(Device
, aHidd_PCIDevice_Size3
, &AltSize
);
389 OOP_GetAttr(Device
, aHidd_PCIDevice_INTLine
, &INTLine
);
391 else if ((_legacyBus
= (struct ata_LegacyBus
*)
392 a
->ATABase
->ata__legacybuses
.lh_Head
)->atalb_ControllerID
== 0)
394 Remove((struct Node
*)_legacyBus
);
395 IOBase
= _legacyBus
->atalb_IOBase
;
396 IOAlt
= _legacyBus
->atalb_IOAlt
;
397 INTLine
= _legacyBus
->atalb_INTLine
;
398 FreeMem(_legacyBus
, sizeof(struct ata_LegacyBus
));
401 AltSize
= RANGESIZE1
;
405 bug("[ATA ] ata_PCIEnumerator_h: Ran out of legacy buses\n");
409 if (IOBase
!= (IPTR
)NULL
&& IOSize
== RANGESIZE0
410 && AltSize
== RANGESIZE1
)
412 struct ata_ProbedBus
*probedbus
;
413 D(bug("[ATA ] ata_PCIEnumerator_h: Adding Bus %d - IRQ %d, IO: %x:%x, DMA: %x\n", x
, INTLine
, IOBase
, IOAlt
, DMABase
));
414 if ((probedbus
= AllocMem(sizeof(struct ata_ProbedBus
), MEMF_CLEAR
| MEMF_PUBLIC
)) != (IPTR
)NULL
)
416 probedbus
->atapb_IOBase
= IOBase
;
417 probedbus
->atapb_IOAlt
= IOAlt
;
418 probedbus
->atapb_INTLine
= INTLine
;
420 probedbus
->atapb_DMABase
= DMABase
+ (x
<< 3);
421 probedbus
->atapb_a
= a
;
422 probedbus
->atapb_Has80Wire
=
423 (ATAIOConfig
& (0x30 << (x
<< 1))) || SubClass
!= 0x1;
427 D(bug("[ATA ] ata_PCIEnumerator_h: Device using Legacy-Bus IOPorts\n"));
428 probedbus
->atapb_Node
.ln_Pri
= ATABUSNODEPRI_PROBEDLEGACY
- (a
->ATABase
->ata__buscount
++);
431 probedbus
->atapb_Node
.ln_Pri
= ATABUSNODEPRI_PROBED
- (a
->ATABase
->ata__buscount
++);
433 Enqueue((struct List
*)&a
->ATABase
->ata__probedbuses
, (struct Node
*)probedbus
);
441 struct TagItem attrs
[] =
443 { aHidd_PCIDevice_isIO
, TRUE
},
444 { aHidd_PCIDevice_isMaster
, DMABase
!= 0 },
447 OOP_SetAttrs(Device
, attrs
);
450 /* check dma status if applicable */
452 D(bug("[ATA ] ata_PCIEnumerator_h: Bus0 DMA Status %02x, Bus1 DMA Status %02x\n", ata_in(2, DMABase
), ata_in(10, DMABase
)));
454 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice
);
460 void ata_Scan(struct ataBase
*base
)
463 struct SignalSemaphore ssem
;
464 struct ata_ProbedBus
*probedbus
;
473 D(bug("[ATA--] ata_Scan: Enumerating devices\n"));
475 if (base
->ata_ScanFlags
& ATA_SCANPCI
) {
476 D(bug("[ATA--] ata_Scan: Checking for supported PCI devices ..\n"));
477 pci
= OOP_NewObject(NULL
, CLID_Hidd_PCI
, NULL
);
481 struct Hook FindHook
= {
482 h_Entry
: (IPTR (*)())ata_PCIEnumerator_h
,
486 struct TagItem Requirements
[] = {
487 {tHidd_PCI_Class
, 0x01},
491 struct pHidd_PCI_EnumDevices enummsg
= {
492 mID
: OOP_GetMethodID(IID_Hidd_PCI
, moHidd_PCI_EnumDevices
),
494 requirements
: (struct TagItem
*)&Requirements
,
497 OOP_DoMethod(pci
, (OOP_Msg
)msg
);
499 OOP_DisposeObject(pci
);
502 if (base
->ata_ScanFlags
& ATA_SCANLEGACY
) {
503 struct ata_LegacyBus
*legacybus
;
504 D(bug("[ATA--] ata_Scan: Adding Remaining Legacy-Buses\n"));
505 while ((legacybus
= (struct ata_LegacyBus
*)
506 RemHead((struct List
*)&base
->ata__legacybuses
)) != NULL
)
508 if ((probedbus
= AllocMem(sizeof(struct ata_ProbedBus
), MEMF_CLEAR
| MEMF_PUBLIC
)) != NULL
)
510 probedbus
->atapb_IOBase
= legacybus
->atalb_IOBase
;
511 probedbus
->atapb_IOAlt
= legacybus
->atalb_IOAlt
;
512 probedbus
->atapb_INTLine
= legacybus
->atalb_INTLine
;
513 probedbus
->atapb_DMABase
= (IPTR
)NULL
;
514 probedbus
->atapb_Has80Wire
= FALSE
;
515 probedbus
->atapb_a
= &Args
;
516 probedbus
->atapb_Node
.ln_Pri
= ATABUSNODEPRI_LEGACY
- (base
->ata__buscount
++);
517 D(bug("[ATA--] ata_Scan: Adding Legacy Bus - IO: %x:%x\n",
518 probedbus
->atapb_IOBase
, probedbus
->atapb_IOAlt
));
519 Enqueue((struct List
*)&base
->ata__probedbuses
, (struct Node
*)&probedbus
->atapb_Node
);
522 FreeMem(legacybus
, sizeof(struct ata_LegacyBus
));
525 D(bug("[ATA--] ata_Scan: Registering Probed Buses..\n"));
526 while ((probedbus
= (struct ata_ProbedBus
*)
527 RemHead((struct List
*)&base
->ata__probedbuses
)) != NULL
)
530 probedbus
->atapb_IOBase
,
531 probedbus
->atapb_IOAlt
,
532 probedbus
->atapb_INTLine
,
533 probedbus
->atapb_DMABase
,
534 probedbus
->atapb_Has80Wire
,
537 FreeMem(probedbus
, sizeof(struct ata_ProbedBus
));
540 D(bug("[ATA--] ata_Scan: Initialising Bus Tasks..\n"));
541 InitSemaphore(&ssem
);
542 ForeachNode(&base
->ata_Buses
, node
)
544 ata_InitBusTask((struct ata_Bus
*)node
, &ssem
);
548 * wait for all buses to complete their init
550 D(bug("[ATA--] ata_Scan: Waiting for Buses to finish Initialising\n"));
551 ObtainSemaphore(&ssem
);
556 ReleaseSemaphore(&ssem
);
557 D(bug("[ATA--] ata_Scan: Finished\n"));
561 Here shall we start. Make function static as it shouldn't be visible from
564 static int ata_init(LIBBASETYPEPTR LIBBASE
)
566 struct BootLoaderBase
*BootLoaderBase
;
567 struct ata_LegacyBus
*_legacybus
;
570 D(bug("[ATA--] ata_init: ata.device Initialization\n"));
573 * I've decided to use memory pools again. Alloc everything needed from
574 * a pool, so that we avoid memory fragmentation.
576 LIBBASE
->ata_MemPool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
| MEMF_SEM_PROTECTED
, 8192, 4096);
577 if (LIBBASE
->ata_MemPool
== NULL
)
580 D(bug("[ATA--] ata_init: MemPool @ %p\n", LIBBASE
->ata_MemPool
));
582 /* Prepare lists for probed/found ide buses */
583 NEWLIST((struct List
*)&LIBBASE
->ata__legacybuses
);
584 NEWLIST((struct List
*)&LIBBASE
->ata__probedbuses
);
586 /* Build the list of possible legacy-bus ports */
587 for (i
= 0; LegacyBuses
[i
].lb_Port
!= 0 ; i
++)
589 if ((_legacybus
= AllocMem(sizeof(struct ata_LegacyBus
), MEMF_CLEAR
| MEMF_PUBLIC
)) != NULL
)
591 D(bug("[ATA--] ata_init: Prepare Legacy Bus %d:%d entry [IOPorts %x:%x IRQ %d]\n", LegacyBuses
[i
].lb_ControllerID
, LegacyBuses
[i
].lb_Bus
, LegacyBuses
[i
].lb_Port
, LegacyBuses
[i
].lb_Alt
, LegacyBuses
[i
].lb_IRQ
));
593 _legacybus
->atalb_IOBase
= (IPTR
)LegacyBuses
[i
].lb_Port
;
594 _legacybus
->atalb_IOAlt
= (IPTR
)LegacyBuses
[i
].lb_Alt
;
595 _legacybus
->atalb_INTLine
= (IPTR
)LegacyBuses
[i
].lb_IRQ
;
596 _legacybus
->atalb_ControllerID
= (IPTR
)LegacyBuses
[i
].lb_ControllerID
;
597 _legacybus
->atalb_BusID
= (IPTR
)LegacyBuses
[i
].lb_Bus
;
598 AddTail(&LIBBASE
->ata__legacybuses
, &_legacybus
->atalb_Node
);
602 /* Set default ata.device config options */
603 LIBBASE
->ata_ScanFlags
= ATA_SCANPCI
| ATA_SCANLEGACY
;
604 LIBBASE
->ata_32bit
= FALSE
;
605 LIBBASE
->ata_NoMulti
= FALSE
;
606 LIBBASE
->ata_NoDMA
= FALSE
;
609 * start initialization:
610 * obtain kernel parameters
612 BootLoaderBase
= OpenResource("bootloader.resource");
613 D(bug("[ATA--] ata_init: BootloaderBase = %p\n", BootLoaderBase
));
614 if (BootLoaderBase
!= NULL
)
619 list
= (struct List
*)GetBootInfo(BL_Args
);
622 ForeachNode(list
, node
)
624 if (strncmp(node
->ln_Name
, "ATA=", 4) == 0)
626 if (strstr(node
->ln_Name
, "nopci"))
628 D(bug("[ATA ] ata_init: Disabling PCI device scan\n"));
629 LIBBASE
->ata_ScanFlags
&= ~ATA_SCANPCI
;
631 if (strstr(node
->ln_Name
, "nolegacy"))
633 D(bug("[ATA ] ata_init: Disabling Legacy ports\n"));
634 LIBBASE
->ata_ScanFlags
&= ~ATA_SCANLEGACY
;
636 if (strstr(node
->ln_Name
, "32bit"))
638 D(bug("[ATA ] ata_init: Using 32-bit IO transfers\n"));
639 LIBBASE
->ata_32bit
= TRUE
;
641 if (strstr(node
->ln_Name
, "nomulti"))
643 D(bug("[ATA ] ata_init: Disabled multisector transfers\n"));
644 LIBBASE
->ata_NoMulti
= TRUE
;
646 if (strstr(node
->ln_Name
, "nodma"))
648 D(bug("[ATA ] ata_init: Disabled DMA transfers\n"));
649 LIBBASE
->ata_NoDMA
= TRUE
;
657 * Initialize BUS list
659 LIBBASE
->ata_Buses
.mlh_Head
= (struct MinNode
*) &LIBBASE
->ata_Buses
.mlh_Tail
;
660 LIBBASE
->ata_Buses
.mlh_Tail
= NULL
;
661 LIBBASE
->ata_Buses
.mlh_TailPred
= (struct MinNode
*) &LIBBASE
->ata_Buses
.mlh_Head
;
664 * Find all suitable devices ..
668 /* Try to setup daemon task looking for diskchanges */
669 ata_InitDaemonTask(LIBBASE
);
675 LIBBASETYPEPTR LIBBASE
,
676 struct IORequest
*iorq
,
689 iorq
->io_Error
= IOERR_OPENFAIL
;
694 struct ata_Bus
*b
= (struct ata_Bus
*)LIBBASE
->ata_Buses
.mlh_Head
;
697 * Extract bus and device numbers
699 bus
= unitnum
>> 1; // 0xff00 >> 8
700 dev
= (unitnum
& 0x1); // 0x00ff
707 b
= (struct ata_Bus
*)b
->ab_Node
.mln_Succ
;
712 if (b
->ab_Node
.mln_Succ
== NULL
)
718 if (b
->ab_Units
[dev
] == NULL
)
724 iorq
->io_Device
= &LIBBASE
->ata_Device
;
725 iorq
->io_Unit
= &b
->ab_Units
[dev
]->au_Unit
;
728 b
->ab_Units
[dev
]->au_Unit
.unit_OpenCnt
++;
733 /* Close given device */
736 LIBBASETYPEPTR LIBBASE
,
737 struct IORequest
*iorq
740 struct ata_Unit
*unit
= (struct ata_Unit
*)iorq
->io_Unit
;
742 /* First of all make the important fields of struct IORequest invalid! */
743 iorq
->io_Unit
= (struct Unit
*)~0;
745 /* Decrease use counters of unit */
746 unit
->au_Unit
.unit_OpenCnt
--;
751 ADD2INITLIB(ata_init
, 0)
753 ADD2CLOSEDEV(close
, 0)
754 ADD2LIBS("irq.hidd", 0, static struct Library
*, __irqhidd
)
755 /* vim: set ts=8 sts=4 et : */