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 50
106 #define ATABUSNODEPRI_PROBEDLEGACY 100
107 #define ATABUSNODEPRI_LEGACY 0
113 /* static list of io/irqs that we can handle */
114 static struct ata__legacybus
119 UBYTE lb_ControllerID
;
123 {0x1f0, 0x3f4, 14, 0, 0},
124 {0x170, 0x374, 15, 0, 1},
125 {0x168, 0x36c, 10, 1, 0},
126 {0x1e8, 0x3ec, 11, 1, 1},
130 /* Add a bootnode using expansion.library */
131 BOOL
ata_RegisterVolume(ULONG StartCyl
, ULONG EndCyl
, struct ata_Unit
*unit
)
133 struct ExpansionBase
*ExpansionBase
;
134 struct DeviceNode
*devnode
;
136 TEXT dosdevname
[4] = "HD0", *handler
;
139 ExpansionBase
= (struct ExpansionBase
*)OpenLibrary("expansion.library",
144 pp
= AllocMem(24*sizeof(IPTR
), MEMF_PUBLIC
| MEMF_CLEAR
);
148 /* This should be dealt with using some sort of volume manager or such. */
149 switch (unit
->au_DevType
)
151 case DG_DIRECT_ACCESS
:
157 D(bug("[ATA>>]:-ata_RegisterVolume called on unknown devicetype\n"));
160 if (unit
->au_UnitNum
< 10)
161 dosdevname
[2] += unit
->au_UnitNum
% 10;
163 dosdevname
[2] = 'A' - 10 + unit
->au_UnitNum
;
164 pp
[0] = (IPTR
)dosdevname
;
165 pp
[1] = (IPTR
)MOD_NAME_STRING
;
166 pp
[2] = unit
->au_UnitNum
;
167 pp
[DE_TABLESIZE
+ 4] = DE_BOOTBLOCKS
;
168 pp
[DE_SIZEBLOCK
+ 4] = 1 << (unit
->au_SectorShift
- 2);
169 pp
[DE_NUMHEADS
+ 4] = unit
->au_Heads
;
170 pp
[DE_SECSPERBLOCK
+ 4] = 1;
171 pp
[DE_BLKSPERTRACK
+ 4] = unit
->au_Sectors
;
172 pp
[DE_RESERVEDBLKS
+ 4] = 2;
173 pp
[DE_LOWCYL
+ 4] = StartCyl
;
174 pp
[DE_HIGHCYL
+ 4] = EndCyl
;
175 pp
[DE_NUMBUFFERS
+ 4] = 10;
176 pp
[DE_BUFMEMTYPE
+ 4] = MEMF_PUBLIC
| MEMF_CHIP
;
177 pp
[DE_MAXTRANSFER
+ 4] = 0x00200000;
178 pp
[DE_MASK
+ 4] = 0x7FFFFFFE;
179 pp
[DE_BOOTPRI
+ 4] = ((!unit
->au_DevType
) ? 0 : 10);
180 pp
[DE_DOSTYPE
+ 4] = 0x444F5301;
181 pp
[DE_BOOTBLOCKS
+ 4] = 2;
182 devnode
= MakeDosNode(pp
);
186 if(unit
->au_DevType
== DG_DIRECT_ACCESS
)
187 handler
= "afs.handler";
189 handler
= "cdrom.handler";
190 len
= strlen(handler
);
191 if ((devnode
->dn_Handler
=
192 MKBADDR(AllocMem(AROS_BSTR_MEMSIZE4LEN(len
),
193 MEMF_PUBLIC
| MEMF_CLEAR
198 CopyMem(handler
, AROS_BSTR_ADDR(devnode
->dn_Handler
), len
);
199 AROS_BSTR_setstrlen(devnode
->dn_Handler
, len
);
201 D(bug("[ATA>>]:-ata_RegisterVolume: '%s' with StartCyl=%d, EndCyl=%d .. ",
202 &(devnode
->dn_Ext
.dn_AROS
.dn_DevName
[0]), StartCyl
, EndCyl
));
203 AddBootNode(pp
[DE_BOOTPRI
+ 4], 0, devnode
, 0);
211 CloseLibrary((struct Library
*)ExpansionBase
);
217 static void ata_RegisterBus(IPTR IOBase
, IPTR IOAlt
, IPTR INTLine
,
218 IPTR DMABase
, BOOL has80Wire
, EnumeratorArgs
*a
)
221 * ata bus - this is going to be created and linked to the master list here
228 * initialize structure
230 ab
= (struct ata_Bus
*) AllocVecPooled(a
->ATABase
->ata_MemPool
, sizeof(struct ata_Bus
));
234 ab
->ab_Base
= a
->ATABase
;
235 ab
->ab_Port
= IOBase
;
237 ab
->ab_IRQ
= INTLine
;
238 ab
->ab_Dev
[0] = DEV_NONE
;
239 ab
->ab_Dev
[1] = DEV_NONE
;
241 ab
->ab_SleepySignal
= 0;
242 ab
->ab_BusNum
= a
->CurrentBus
++;
244 ab
->ab_Units
[0] = NULL
;
245 ab
->ab_Units
[1] = NULL
;
246 ab
->ab_IntHandler
= (HIDDT_IRQ_Handler
*)AllocVecPooled(a
->ATABase
->ata_MemPool
, sizeof(HIDDT_IRQ_Handler
));
248 ab
->ab_HandleIRQ
= NULL
;
250 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));
251 D(bug("[ATA>>] ata_RegisterBus: IRQ %d, IO: %x:%x, DMA: %x\n", INTLine
, IOBase
, IOAlt
, DMABase
));
256 ab
->ab_PRD
= AllocVecPooled(a
->ATABase
->ata_MemPool
, (PRD_MAX
+1) * 2 * sizeof(struct PRDEntry
));
257 if ((0x10000 - ((ULONG
)ab
->ab_PRD
& 0xffff)) < PRD_MAX
* sizeof(struct PRDEntry
))
258 ab
->ab_PRD
= (void*)((((IPTR
)ab
->ab_PRD
)+0xffff) &~ 0xffff);
261 * scan bus - try to locate all devices (disables irq)
264 for (i
= 0; i
< MAX_BUSUNITS
; i
++)
266 if (ab
->ab_Dev
[i
] > DEV_UNKNOWN
)
268 ab
->ab_Units
[i
] = AllocVecPooled(a
->ATABase
->ata_MemPool
,
269 sizeof(struct ata_Unit
));
270 ab
->ab_Units
[i
]->au_DMAPort
= DMABase
;
271 ab
->ab_Units
[i
]->au_Flags
= has80Wire
? AF_80Wire
: 0;
272 ata_init_unit(ab
, i
);
276 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]));
280 * note: this happens no matter there are devices or not
281 * sort of almost-ready-for-hotplug ;)
283 AddTail((struct List
*)&a
->ATABase
->ata_Buses
, (struct Node
*)ab
);
288 * collect ALL ata/ide capable devices (including SATA and other) and
289 * spawn concurrent tasks.
291 * This function is growing too large. It will shorten drasticly once this whole mess gets converted into c++
295 AROS_UFH3(void, ata_PCIEnumerator_h
,
296 AROS_UFHA(struct Hook
*, hook
, A0
),
297 AROS_UFHA(OOP_Object
*, Device
, A2
),
298 AROS_UFHA(APTR
, message
,A1
))
303 * parameters we will want to acquire
317 BOOL _usablebus
= FALSE
;
322 OOP_AttrBase HiddPCIDeviceAttrBase
= OOP_ObtainAttrBase(IID_Hidd_PCIDevice
);
327 EnumeratorArgs
*a
= (EnumeratorArgs
*)hook
->h_Data
;
330 * temporary variables
335 * obtain more or less useful data
337 OOP_GetAttr(Device
, aHidd_PCIDevice_VendorID
, &VendorID
);
338 OOP_GetAttr(Device
, aHidd_PCIDevice_ProductID
, &ProductID
);
339 OOP_GetAttr(Device
, aHidd_PCIDevice_Base4
, &DMABase
);
340 OOP_GetAttr(Device
, aHidd_PCIDevice_Size4
, &DMASize
);
341 OOP_GetAttr(Device
, aHidd_PCIDevice_SubClass
, &SubClass
);
342 OOP_GetAttr(Device
, aHidd_PCIDevice_Interface
, &Interface
);
344 if (a
->ATABase
->ata_NoDMA
|| !(Interface
& 0x80))
348 * we can have up to two buses assigned to this device
350 for (x
= 0; SubClass
!= 0 && SubClass
!= 7 && x
< MAX_DEVICEBUSES
; x
++)
352 struct ata_LegacyBus
*_legacyBus
= NULL
;
353 BOOL isLegacy
= FALSE
;
357 bug("[ATA ] ata_PCIEnumerator_h: Found IDE device %04x:%04x\n", VendorID
, ProductID
);
361 * obtain I/O bases and interrupt line
363 if ((Interface
& (1 << (x
<< 1))) || SubClass
!= 1)
368 OOP_GetAttr(Device
, aHidd_PCIDevice_Base0
, &IOBase
);
369 OOP_GetAttr(Device
, aHidd_PCIDevice_Size0
, &IOSize
);
370 OOP_GetAttr(Device
, aHidd_PCIDevice_Base1
, &IOAlt
);
371 OOP_GetAttr(Device
, aHidd_PCIDevice_Size1
, &AltSize
);
374 OOP_GetAttr(Device
, aHidd_PCIDevice_Base2
, &IOBase
);
375 OOP_GetAttr(Device
, aHidd_PCIDevice_Size2
, &IOSize
);
376 OOP_GetAttr(Device
, aHidd_PCIDevice_Base3
, &IOAlt
);
377 OOP_GetAttr(Device
, aHidd_PCIDevice_Size3
, &AltSize
);
380 OOP_GetAttr(Device
, aHidd_PCIDevice_INTLine
, &INTLine
);
382 else if ((_legacyBus
= (struct ata_LegacyBus
*)
383 a
->ATABase
->ata__legacybuses
.lh_Head
)->atalb_ControllerID
== 0)
385 Remove((struct Node
*)_legacyBus
);
386 IOBase
= _legacyBus
->atalb_IOBase
;
387 IOAlt
= _legacyBus
->atalb_IOAlt
;
388 INTLine
= _legacyBus
->atalb_INTLine
;
389 FreeMem(_legacyBus
, sizeof(struct ata_LegacyBus
));
392 AltSize
= RANGESIZE1
;
396 bug("[ATA ] ata_PCIEnumerator_h: Ran out of legacy buses\n");
400 if (IOBase
!= (IPTR
)NULL
&& IOSize
== RANGESIZE0
401 && AltSize
== RANGESIZE1
402 && (DMASize
= DMASIZE
|| DMABase
== NULL
|| SubClass
== 1))
404 struct ata_ProbedBus
*probedbus
;
405 D(bug("[ATA ] ata_PCIEnumerator_h: Adding Bus %d - IRQ %d, IO: %x:%x, DMA: %x\n", x
, INTLine
, IOBase
, IOAlt
, DMABase
));
406 if ((probedbus
= AllocMem(sizeof(struct ata_ProbedBus
), MEMF_CLEAR
| MEMF_PUBLIC
)) != (IPTR
)NULL
)
408 probedbus
->atapb_IOBase
= IOBase
;
409 probedbus
->atapb_IOAlt
= IOAlt
;
410 probedbus
->atapb_INTLine
= INTLine
;
412 probedbus
->atapb_DMABase
= DMABase
+ (x
<< 3);
413 probedbus
->atapb_a
= a
;
414 probedbus
->atapb_Has80Wire
= TRUE
;
418 D(bug("[ATA ] ata_PCIEnumerator_h: Device using Legacy-Bus IOPorts\n"));
419 probedbus
->atapb_Node
.ln_Pri
= ATABUSNODEPRI_PROBEDLEGACY
- (a
->ATABase
->ata__buscount
++);
422 probedbus
->atapb_Node
.ln_Pri
= ATABUSNODEPRI_PROBED
- (a
->ATABase
->ata__buscount
++);
424 Enqueue((struct List
*)&a
->ATABase
->ata__probedbuses
, (struct Node
*)probedbus
);
432 struct TagItem attrs
[] =
434 { aHidd_PCIDevice_isIO
, TRUE
},
435 { aHidd_PCIDevice_isMaster
, DMABase
!= 0 },
438 OOP_SetAttrs(Device
, attrs
);
441 /* check dma status if applicable */
443 D(bug("[ATA ] ata_PCIEnumerator_h: Bus0 DMA Status %02x, Bus1 DMA Status %02x\n", ata_in(2, DMABase
), ata_in(10, DMABase
)));
445 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice
);
451 void ata_Scan(struct ataBase
*base
)
454 struct SignalSemaphore ssem
;
455 struct ata_ProbedBus
*probedbus
;
464 D(bug("[ATA--] ata_Scan: Enumerating devices\n"));
466 if (base
->ata_ScanFlags
& ATA_SCANPCI
) {
467 D(bug("[ATA--] ata_Scan: Checking for supported PCI devices ..\n"));
468 pci
= OOP_NewObject(NULL
, CLID_Hidd_PCI
, NULL
);
472 struct Hook FindHook
= {
473 h_Entry
: (IPTR (*)())ata_PCIEnumerator_h
,
477 struct TagItem Requirements
[] = {
478 {tHidd_PCI_Class
, 0x01},
482 struct pHidd_PCI_EnumDevices enummsg
= {
483 mID
: OOP_GetMethodID(IID_Hidd_PCI
, moHidd_PCI_EnumDevices
),
485 requirements
: (struct TagItem
*)&Requirements
,
488 OOP_DoMethod(pci
, (OOP_Msg
)msg
);
490 OOP_DisposeObject(pci
);
493 if (base
->ata_ScanFlags
& ATA_SCANLEGACY
) {
494 struct ata_LegacyBus
*legacybus
;
495 D(bug("[ATA--] ata_Scan: Adding Remaining Legacy-Buses\n"));
496 while ((legacybus
= (struct ata_LegacyBus
*)
497 RemHead((struct List
*)&base
->ata__legacybuses
)) != NULL
)
499 if ((probedbus
= AllocMem(sizeof(struct ata_ProbedBus
), MEMF_CLEAR
| MEMF_PUBLIC
)) != NULL
)
501 probedbus
->atapb_IOBase
= legacybus
->atalb_IOBase
;
502 probedbus
->atapb_IOAlt
= legacybus
->atalb_IOAlt
;
503 probedbus
->atapb_INTLine
= legacybus
->atalb_INTLine
;
504 probedbus
->atapb_DMABase
= (IPTR
)NULL
;
505 probedbus
->atapb_Has80Wire
= FALSE
;
506 probedbus
->atapb_a
= &Args
;
507 probedbus
->atapb_Node
.ln_Pri
= ATABUSNODEPRI_LEGACY
- (base
->ata__buscount
++);
508 D(bug("[ATA--] ata_Scan: Adding Legacy Bus - IO: %x:%x\n",
509 probedbus
->atapb_IOBase
, probedbus
->atapb_IOAlt
));
510 Enqueue((struct List
*)&base
->ata__probedbuses
, (struct Node
*)&probedbus
->atapb_Node
);
513 FreeMem(legacybus
, sizeof(struct ata_LegacyBus
));
516 D(bug("[ATA--] ata_Scan: Registering Probed Buses..\n"));
517 while ((probedbus
= (struct ata_ProbedBus
*)
518 RemHead((struct List
*)&base
->ata__probedbuses
)) != NULL
)
521 probedbus
->atapb_IOBase
,
522 probedbus
->atapb_IOAlt
,
523 probedbus
->atapb_INTLine
,
524 probedbus
->atapb_DMABase
,
525 probedbus
->atapb_Has80Wire
,
528 FreeMem(probedbus
, sizeof(struct ata_ProbedBus
));
531 D(bug("[ATA--] ata_Scan: Initialising Bus Tasks..\n"));
532 InitSemaphore(&ssem
);
533 ForeachNode(&base
->ata_Buses
, node
)
535 ata_InitBusTask((struct ata_Bus
*)node
, &ssem
);
539 * wait for all buses to complete their init
541 D(bug("[ATA--] ata_Scan: Waiting for Buses to finish Initialising\n"));
542 ObtainSemaphore(&ssem
);
547 ReleaseSemaphore(&ssem
);
548 D(bug("[ATA--] ata_Scan: Finished\n"));
552 Here shall we start. Make function static as it shouldn't be visible from
555 static int ata_init(LIBBASETYPEPTR LIBBASE
)
557 struct BootLoaderBase
*BootLoaderBase
;
558 struct ata_LegacyBus
*_legacybus
;
561 D(bug("[ATA--] ata_init: ata.device Initialization\n"));
564 * I've decided to use memory pools again. Alloc everything needed from
565 * a pool, so that we avoid memory fragmentation.
567 LIBBASE
->ata_MemPool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
| MEMF_SEM_PROTECTED
, 8192, 4096);
568 if (LIBBASE
->ata_MemPool
== NULL
)
571 D(bug("[ATA--] ata_init: MemPool @ %p\n", LIBBASE
->ata_MemPool
));
573 /* Prepare lists for probed/found ide buses */
574 NEWLIST((struct List
*)&LIBBASE
->ata__legacybuses
);
575 NEWLIST((struct List
*)&LIBBASE
->ata__probedbuses
);
577 /* Build the list of possible legacy-bus ports */
578 for (i
= 0; LegacyBuses
[i
].lb_Port
!= 0 ; i
++)
580 if ((_legacybus
= AllocMem(sizeof(struct ata_LegacyBus
), MEMF_CLEAR
| MEMF_PUBLIC
)) != NULL
)
582 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
));
584 _legacybus
->atalb_IOBase
= (IPTR
)LegacyBuses
[i
].lb_Port
;
585 _legacybus
->atalb_IOAlt
= (IPTR
)LegacyBuses
[i
].lb_Alt
;
586 _legacybus
->atalb_INTLine
= (IPTR
)LegacyBuses
[i
].lb_IRQ
;
587 _legacybus
->atalb_ControllerID
= (IPTR
)LegacyBuses
[i
].lb_ControllerID
;
588 _legacybus
->atalb_BusID
= (IPTR
)LegacyBuses
[i
].lb_Bus
;
589 AddTail(&LIBBASE
->ata__legacybuses
, &_legacybus
->atalb_Node
);
593 /* Set default ata.device config options */
594 LIBBASE
->ata_ScanFlags
= ATA_SCANPCI
| ATA_SCANLEGACY
;
595 LIBBASE
->ata_32bit
= FALSE
;
596 LIBBASE
->ata_NoMulti
= FALSE
;
597 LIBBASE
->ata_NoDMA
= FALSE
;
600 * start initialization:
601 * obtain kernel parameters
603 BootLoaderBase
= OpenResource("bootloader.resource");
604 D(bug("[ATA--] ata_init: BootloaderBase = %p\n", BootLoaderBase
));
605 if (BootLoaderBase
!= NULL
)
610 list
= (struct List
*)GetBootInfo(BL_Args
);
613 ForeachNode(list
, node
)
615 if (strncmp(node
->ln_Name
, "ATA=", 4) == 0)
617 if (strstr(node
->ln_Name
, "nopci"))
619 D(bug("[ATA ] ata_init: Disabling PCI device scan\n"));
620 LIBBASE
->ata_ScanFlags
&= ~ATA_SCANPCI
;
622 if (strstr(node
->ln_Name
, "nolegacy"))
624 D(bug("[ATA ] ata_init: Disabling Legacy ports\n"));
625 LIBBASE
->ata_ScanFlags
&= ~ATA_SCANLEGACY
;
627 if (strstr(node
->ln_Name
, "32bit"))
629 D(bug("[ATA ] ata_init: Using 32-bit IO transfers\n"));
630 LIBBASE
->ata_32bit
= TRUE
;
632 if (strstr(node
->ln_Name
, "nomulti"))
634 D(bug("[ATA ] ata_init: Disabled multisector transfers\n"));
635 LIBBASE
->ata_NoMulti
= TRUE
;
637 if (strstr(node
->ln_Name
, "nodma"))
639 D(bug("[ATA ] ata_init: Disabled DMA transfers\n"));
640 LIBBASE
->ata_NoDMA
= TRUE
;
648 * Initialize BUS list
650 LIBBASE
->ata_Buses
.mlh_Head
= (struct MinNode
*) &LIBBASE
->ata_Buses
.mlh_Tail
;
651 LIBBASE
->ata_Buses
.mlh_Tail
= NULL
;
652 LIBBASE
->ata_Buses
.mlh_TailPred
= (struct MinNode
*) &LIBBASE
->ata_Buses
.mlh_Head
;
655 * Find all suitable devices ..
659 /* Try to setup daemon task looking for diskchanges */
660 ata_InitDaemonTask(LIBBASE
);
666 LIBBASETYPEPTR LIBBASE
,
667 struct IORequest
*iorq
,
680 iorq
->io_Error
= IOERR_OPENFAIL
;
685 struct ata_Bus
*b
= (struct ata_Bus
*)LIBBASE
->ata_Buses
.mlh_Head
;
688 * Extract bus and device numbers
690 bus
= unitnum
>> 1; // 0xff00 >> 8
691 dev
= (unitnum
& 0x1); // 0x00ff
698 b
= (struct ata_Bus
*)b
->ab_Node
.mln_Succ
;
703 if (b
->ab_Node
.mln_Succ
== NULL
)
709 if (b
->ab_Units
[dev
] == NULL
)
715 iorq
->io_Device
= &LIBBASE
->ata_Device
;
716 iorq
->io_Unit
= &b
->ab_Units
[dev
]->au_Unit
;
719 b
->ab_Units
[dev
]->au_Unit
.unit_OpenCnt
++;
724 /* Close given device */
727 LIBBASETYPEPTR LIBBASE
,
728 struct IORequest
*iorq
731 struct ata_Unit
*unit
= (struct ata_Unit
*)iorq
->io_Unit
;
733 /* First of all make the important fields of struct IORequest invalid! */
734 iorq
->io_Unit
= (struct Unit
*)~0;
736 /* Decrease use counters of unit */
737 unit
->au_Unit
.unit_OpenCnt
--;
742 ADD2INITLIB(ata_init
, 0)
744 ADD2CLOSEDEV(close
, 0)
745 ADD2LIBS("irq.hidd", 0, static struct Library
*, __irqhidd
)
746 /* vim: set ts=8 sts=4 et : */