revert between 56095 -> 55830 in arch
[AROS.git] / rom / hidds / ata_pci / probe.c
blob9919eed8192ae68c2da336d7c0e0905059552bcf
1 /*
2 Copyright © 2004-2019, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Hardware detection routine
6 Lang: English
7 */
9 #include <aros/debug.h>
10 #include <proto/exec.h>
12 /* We want all other bases obtained from our base */
13 #define __NOLIBBASE__
15 #include <proto/bootloader.h>
16 #include <proto/oop.h>
18 #include <aros/asmcall.h>
19 #include <aros/bootloader.h>
20 #include <aros/symbolsets.h>
21 #include <asm/io.h>
22 #include <exec/lists.h>
23 #include <exec/rawfmt.h>
24 #include <hardware/ahci.h>
25 #include <hidd/bus.h>
26 #include <hidd/ata.h>
27 #include <hidd/storage.h>
28 #include <hidd/pci.h>
29 #include <oop/oop.h>
31 #include <string.h>
33 #include "bus_class.h"
34 #include "interface_pio.h"
35 #include "interface_dma.h"
36 #include "pci.h"
38 #define DSATA(x)
41 * Currently we support legacy ISA ports only on x86.
42 * This can change only if someone ports AROS to PowerPC
43 * retro-machine like PReP.
45 #ifdef __i386__
46 #define SUPPORT_LEGACY
47 #endif
48 #ifdef __x86_64__
49 #define SUPPORT_LEGACY
50 #endif
52 #define NAME_BUFFER 128
54 #define RANGESIZE0 8
55 #define RANGESIZE1 4
56 #define DMASIZE 16
58 CONST_STRPTR ataPCIName = "ata_pci.hidd";
59 CONST_STRPTR ataPCIControllerName = "PCI Dual Channel IDE Controller";
60 #ifdef SUPPORT_LEGACY
61 CONST_STRPTR ataISAControllerName = "ISA IDE Controller";
62 #endif
64 /* static list of io/irqs that we can handle */
65 struct ata__legacybus
67 UWORD lb_Port;
68 UWORD lb_Alt;
69 UBYTE lb_IRQ;
70 UBYTE lb_ControllerID;
71 UBYTE lb_Bus;
72 const char *lb_Name;
75 static const struct ata__legacybus LegacyBuses[] =
77 {0x1f0, 0x3f4, 14, 0, 0, "ISA IDE0 primary channel" },
78 {0x170, 0x374, 15, 0, 1, "ISA IDE0 secondary channel"},
79 {0x168, 0x36c, 10, 1, 0, "ISA IDE1 primary channel" },
80 {0x1e8, 0x3ec, 11, 1, 1, "ISA IDE1 secondary channel"},
81 { 0, 0, 0, 0, 0, NULL }
84 #ifdef DO_SATA_HANDOFF
86 /* SATA handoff code needs timer */
88 static struct IORequest *OpenTimer(void)
90 struct MsgPort *p = CreateMsgPort();
92 if (NULL != p)
94 struct IORequest *io = CreateIORequest(p, sizeof(struct timerequest));
96 if (NULL != io)
98 if (0 == OpenDevice("timer.device", UNIT_MICROHZ, io, 0))
100 return io;
102 DeleteIORequest(io);
104 DeleteMsgPort(p);
107 return NULL;
110 static void CloseTimer(struct IORequest *tmr)
112 if (NULL != tmr)
114 struct MsgPort *p = tmr->io_Message.mn_ReplyPort;
116 CloseDevice(tmr);
117 DeleteIORequest(tmr);
118 DeleteMsgPort(p);
122 static void WaitTO(struct IORequest* tmr, ULONG secs, ULONG micro)
124 tmr->io_Command = TR_ADDREQUEST;
125 ((struct timerequest*)tmr)->tr_time.tv_secs = secs;
126 ((struct timerequest*)tmr)->tr_time.tv_micro = micro;
128 DoIO(tmr);
131 #endif
134 * PCI BUS ENUMERATOR
135 * collect ALL ata/ide capable devices (including SATA and other) and
136 * spawn concurrent tasks.
138 * This function is growing too large. It will shorten drasticly once this whole mess gets converted into c++
141 static
142 AROS_UFH3(void, ata_PCIEnumerator_h,
143 AROS_UFHA(struct Hook *, hook, A0),
144 AROS_UFHA(OOP_Object *, Device, A2),
145 AROS_UFHA(APTR, message,A1))
147 AROS_USERFUNC_INIT
149 struct atapciBase *base = hook->h_Data;
150 OOP_Object *Driver;
151 struct PCIDeviceRef *devRef;
152 IPTR DMABase, DMASize, INTLine;
153 IPTR IOBase, IOAlt, IOSize, AltSize, SubClass, Interface;
154 int x;
155 CONST_STRPTR owner;
156 OOP_Object *ata_PCI = NULL;
157 struct TagItem ata_tags[] =
159 {aHidd_Name , (IPTR)ataPCIName },
160 {aHidd_HardwareName , (IPTR)ataPCIControllerName },
161 {aHidd_Producer , 0 },
162 #define ATA_TAG_VEND 2
163 {aHidd_Product , 0 },
164 #define ATA_TAG_PROD 3
165 {TAG_DONE , 0 }
169 * obtain more or less useful data
171 OOP_GetAttr(Device, aHidd_PCIDevice_Driver , (IPTR *)&Driver);
172 OOP_GetAttr(Device, aHidd_PCIDevice_VendorID , &ata_tags[ATA_TAG_VEND].ti_Data);
173 OOP_GetAttr(Device, aHidd_PCIDevice_ProductID, &ata_tags[ATA_TAG_PROD].ti_Data);
174 OOP_GetAttr(Device, aHidd_PCIDevice_SubClass , &SubClass);
175 OOP_GetAttr(Device, aHidd_PCIDevice_Base4 , &DMABase);
176 OOP_GetAttr(Device, aHidd_PCIDevice_Size4 , &DMASize);
177 OOP_GetAttr(Device, aHidd_PCIDevice_Interface, &Interface);
179 D(bug("[ATA:PCI] ata_PCIEnumerator_h: Found IDE device %04x:%04x\n", ata_tags[ATA_TAG_VEND].ti_Data, ata_tags[ATA_TAG_PROD].ti_Data));
181 /* First check subclass */
182 if ((SubClass == PCI_SUBCLASS_SCSI) || (SubClass == PCI_SUBCLASS_SAS))
184 D(bug("[ATA:PCI] Unsupported subclass %d\n", SubClass));
185 return;
188 owner = HIDD_PCIDevice_Obtain(Device, base->lib.lib_Node.ln_Name);
189 if (owner)
191 D(bug("[ATA:PCI] Already owned by %s\n", owner));
192 return;
195 devRef = AllocMem(sizeof(struct PCIDeviceRef), MEMF_ANY);
196 if (!devRef)
198 D(bug("[ATA:PCI] Failed to allocate reference structure\n"));
199 return;
202 devRef->ref_Device = Device;
203 devRef->ref_Count = 0;
206 * SATA controllers may need a special treatment before becoming usable.
207 * The machine's firmware (EFI on Mac) may operate them in native AHCI mode
208 * and not set up legacy mode by itself.
209 * In this case we have to do it ourselves.
210 * This code is based on incomplete ahci.device source code by DissyOfCRN.
211 * CHECKME: In order to work on PPC it uses explicit little-endian I/O,
212 * assuming AHCI register file is always little-endian. Is it correct?
214 if (SubClass == PCI_SUBCLASS_SATA)
216 APTR hba_phys = NULL;
217 IPTR hba_size = 0;
218 volatile struct ahci_hwhba *hwhba;
219 ULONG ghc, cap;
221 OOP_GetAttr(Device, aHidd_PCIDevice_Base5, (IPTR *)&hba_phys);
222 OOP_GetAttr(Device, aHidd_PCIDevice_Size5, &hba_size);
224 DSATA(bug("[ATA:PCI] Device %04x:%04x is a SATA device, HBA 0x%p, size 0x%p\n", ata_tags[ATA_TAG_VEND].ti_Data, ata_tags[ATA_TAG_PROD].ti_Data, hba_phys, hba_size));
226 hwhba = HIDD_PCIDriver_MapPCI(Driver, hba_phys, hba_size);
227 DSATA(bug("[ATA:PCI] Mapped at 0x%p\n", hwhba));
229 if (!hwhba)
231 DSATA(bug("[ATA:PCI] Mapping failed, device will be ignored\n"));
232 DeviceFree(devRef, base);
233 return;
236 cap = mmio_inl_le(&hwhba->cap);
237 ghc = mmio_inl_le(&hwhba->ghc);
238 DSATA(bug("[ATA:PCI] Capabilities: 0x%08X, host control: 0x%08X\n", cap, ghc));
241 * Some hardware may report GHC_AE to be zero, together with CAP_SAM set (indicating
242 * that the device doesn't support legacy IDE registers). Seems to be spec violation
243 * (the AHCI specification says that in this cases GHC_AE is read-only bit which is
244 * hardwired to 1).
245 * Attempting to drive such a hardware causes ata.device to freeze.
246 * This effect has been observed on Marvel 9172 controller (and some other HW,
247 * according to user reports, but nobody has ever provided a debug log).
249 if (cap & CAP_SAM)
251 DSATA(bug("[ATA:PCI] Legacy mode is not supported, device will be ignored\n"));
253 HIDD_PCIDriver_UnmapPCI(Driver, hba_phys, hba_size);
254 DeviceFree(devRef, base);
255 return;
258 if (ghc & GHC_AE)
260 DSATA(bug("[ATA:PCI] AHCI enabled\n"));
263 * This is ATA driver, not SATA driver, so i'd like to keep SATA-specific code
264 * at a minimum. None of tests revealed a real need for BIOS handoff, no BIOS
265 * was discovered to use controllers in SMI mode.
266 * However, if on some machine we have problems, we can try
267 * to #define this.
269 #ifdef DO_SATA_HANDOFF
270 ULONG version = mmio_inl_le(&hwhba->vs);
271 ULONG cap2 = mmio_inl_le(&hwhba->cap2);
273 DSATA(bug("[ATA:PCI] Version: 0x%08X, Cap2: 0x%08X\n", version, cap2));
275 if ((version >= AHCI_VERSION_1_20) && (cap2 && CAP2_BOH))
277 ULONG bohc;
279 DSATA(bug("[ATA:PCI] HBA supports BIOS/OS handoff\n"));
281 bohc = mmio_inl_le(&hwhba->bohc);
282 if (bohc && BOHC_BOS)
284 struct IORequest *timereq;
286 DSATA(bug("[ATA:PCI] Device owned by BIOS, performing handoff\n"));
289 * We need timer.device in order to perform delays.
290 * TODO: in ata_InitBus() it will be opened and closed again.
291 * This is not optimal, it could be opened and closed just once.
293 timereq = OpenTimer(base);
294 if (!timereq)
296 DSATA(bug("[ATA:PCI] Failed to open timer, can't perform handoff. Device will be ignored\n"));
298 HIDD_PCIDriver_UnmapPCI(Driver, hba_phys, hba_size);
299 DeviceFree(devRef, base);
300 return;
303 mmio_outl_le(bohc | BOHC_OOS, &hwhba->bohc);
304 /* Spin on BOHC_BOS bit FIXME: Possible dead lock. No maximum time given on AHCI1.3 specs... */
305 while (mmio_inl_le(&hwhba->bohc) & BOHC_BOS);
307 WaitTO(timereq, 0, 25000);
308 /* If after 25ms BOHC_BB bit is still set give bios a minimum of 2 seconds more time to run */
310 if (mmio_inl_le(&hwhba->bohc) & BOHC_BB)
312 DSATA(bug("[ATA:PCI] Delayed handoff, waiting...\n"));
313 ata_WaitTO(timereq, 2, 0);
316 DSATA(bug("[ATA:PCI] Handoff done\n"));
317 CloseTimer(timereq);
320 #endif
321 /* This resets GHC_AE bit, disabling AHCI */
322 mmio_outl_le(0, &hwhba->ghc);
325 HIDD_PCIDriver_UnmapPCI(Driver, (APTR)hwhba, hba_size);
328 ata_PCI = HW_AddDriver(base->storageRoot, base->ataClass, ata_tags);
329 if (ata_PCI)
331 D(bug("[ATA:PCI] ata_PCIEnumerator_h: ATA HW Object @ 0x%p\n", ata_PCI));
333 * we can have up to two buses assigned to this device
335 for (x = 0; devRef != NULL && x < MAX_DEVICEBUSES; x++)
337 BYTE basePri = ATABUSNODEPRI_PROBED;
340 * obtain I/O bases and interrupt line
342 if ((Interface & (1 << (x << 1))) || SubClass != PCI_SUBCLASS_IDE)
344 switch (x)
346 case 0:
347 OOP_GetAttr(Device, aHidd_PCIDevice_Base0, &IOBase);
348 OOP_GetAttr(Device, aHidd_PCIDevice_Size0, &IOSize);
349 OOP_GetAttr(Device, aHidd_PCIDevice_Base1, &IOAlt);
350 OOP_GetAttr(Device, aHidd_PCIDevice_Size1, &AltSize);
351 break;
353 case 1:
354 OOP_GetAttr(Device, aHidd_PCIDevice_Base2, &IOBase);
355 OOP_GetAttr(Device, aHidd_PCIDevice_Size2, &IOSize);
356 OOP_GetAttr(Device, aHidd_PCIDevice_Base3, &IOAlt);
357 OOP_GetAttr(Device, aHidd_PCIDevice_Size3, &AltSize);
358 break;
360 OOP_GetAttr(Device, aHidd_PCIDevice_INTLine, &INTLine);
362 else if (LegacyBuses[base->legacycount].lb_ControllerID == 0)
364 IPTR isa_io_base;
366 OOP_GetAttr(Driver, aHidd_PCIDriver_IOBase, &isa_io_base);
367 D(bug("[ATA:PCI] Device using Legacy-Bus IOPorts @ 0x%p\n", isa_io_base));
369 IOBase = LegacyBuses[base->legacycount].lb_Port + isa_io_base;
370 IOAlt = LegacyBuses[base->legacycount].lb_Alt + isa_io_base;
371 INTLine = LegacyBuses[base->legacycount].lb_IRQ;
372 basePri = ATABUSNODEPRI_PROBEDLEGACY;
373 IOSize = RANGESIZE0;
374 AltSize = RANGESIZE1;
376 base->legacycount++;
378 else
380 D(bug("[ATA:PCI] Legacy buses exhausted\n"));
381 IOBase = 0;
384 if (IOBase != 0 && IOSize == RANGESIZE0 && AltSize == RANGESIZE1 &&
385 (DMASize >= DMASIZE || DMABase == 0 || SubClass == PCI_SUBCLASS_IDE))
387 struct ata_ProbedBus *probedbus;
388 STRPTR str[2];
389 int len;
391 D(bug("[ATA:PCI] ata_PCIEnumerator_h: Adding Bus %d - IRQ %d, IO: %x:%x, DMA: %x\n",
392 x, INTLine, IOBase, IOAlt, DMABase));
394 OOP_GetAttr(Device, aHidd_PCIDevice_SubClassDesc, (IPTR *)&str[0]);
395 str[1] = x ? "secondary" : "primary";
396 len = 14 + strlen(str[0]) + strlen(str[1]);
398 probedbus = AllocVec(sizeof(struct ata_ProbedBus) + len, MEMF_ANY);
399 if (probedbus)
401 IPTR dmaBase = DMABase ? DMABase + (x << 3) : 0;
402 STRPTR name = (char *)probedbus + sizeof(struct ata_ProbedBus);
404 RawDoFmt("PCI %s %s channel", (RAWARG)str, RAWFMTFUNC_STRING, name);
406 probedbus->atapb_Parent = ata_PCI;
407 probedbus->atapb_Node.ln_Name = name;
408 probedbus->atapb_Node.ln_Type = basePri;
409 probedbus->atapb_Node.ln_Pri = basePri - (base->ata__buscount++);
410 probedbus->atapb_Device = devRef;
411 probedbus->atapb_Vendor = ata_tags[ATA_TAG_VEND].ti_Data;
412 probedbus->atapb_Product = ata_tags[ATA_TAG_PROD].ti_Data;
413 probedbus->atapb_BusNo = x;
414 probedbus->atapb_IOBase = IOBase;
415 probedbus->atapb_IOAlt = IOAlt;
416 probedbus->atapb_INTLine = INTLine;
417 probedbus->atapb_DMABase = dmaBase;
419 devRef->ref_Count++;
420 Enqueue((struct List *)&base->probedbuses, &probedbus->atapb_Node);
422 OOP_SetAttrsTags(Device, aHidd_PCIDevice_isIO, TRUE,
423 aHidd_PCIDevice_isMaster, DMABase != 0,
424 TAG_DONE);
428 if (!devRef->ref_Count)
430 DeviceFree(devRef, base);
431 devRef = NULL;
435 AROS_USERFUNC_EXIT
438 static CONST_STRPTR pciInterfaceIDs[] =
440 IID_Hidd_PCI,
441 IID_Hidd_PCIDevice,
442 IID_Hidd_PCIDriver,
443 NULL
446 /* We need no attributes for IID_Hidd_PCI, only methods */
447 #define ATTR_OFFSET 1
449 static const struct TagItem Requirements[] =
451 {tHidd_PCI_Class, PCI_CLASS_MASSSTORAGE},
452 {TAG_DONE, 0x00 }
456 * The manner in which this code is written can look a little bit overcomplicated.
457 * However it's just experimental attempt to write hardware scan routine which
458 * can be run more than once, and is hotplug-aware.
459 * In future this may assist implementation of "Rescan devices" functionality
460 * in SysExplorer (for example). This will provide a possibility to load and unload
461 * device drivers on the fly.
462 * For now it's just experiment... Don't pay much attention please. :)
464 static int ata_bus_Detect(struct atapciBase *base)
466 APTR BootLoaderBase;
467 struct ata_ProbedBus *probedbus;
468 BOOL scanpci = TRUE;
469 #ifdef SUPPORT_LEGACY
470 BOOL scanlegacy = TRUE;
471 OOP_Object *ata_ISA = NULL;
472 int ata_ISA_Ports = 0;
473 #endif
475 D(bug("[ATA:PCI] %s()\n", __PRETTY_FUNCTION__));
477 /* Prepare lists for probed/found ide buses */
478 NEWLIST(&base->probedbuses);
479 base->ata__buscount = 0;
480 base->legacycount = 0;
482 /* Obtain command line parameters */
483 BootLoaderBase = OpenResource("bootloader.resource");
484 D(bug("[ATA:PCI] BootloaderBase = %p\n", BootLoaderBase));
485 if (BootLoaderBase != NULL)
487 struct List *list;
488 struct Node *node;
490 list = (struct List *)GetBootInfo(BL_Args);
491 if (list)
493 ForeachNode(list, node)
495 if (strncmp(node->ln_Name, "ATA=", 4) == 0)
497 const char *cmdline = &node->ln_Name[4];
499 if (strstr(cmdline, "nopci"))
501 D(bug("[ATA:PCI] Disabling PCI device scan\n"));
502 scanpci = FALSE;
504 #ifdef SUPPORT_LEGACY
505 if (strstr(cmdline, "nolegacy"))
507 D(bug("[ATA:PCI] Disabling Legacy ports\n"));
508 scanlegacy = FALSE;
510 #endif
511 if (strstr(cmdline, "disable"))
513 D(bug("[ATA:PCI] Disabling all ATA devices\n"));
514 #ifdef SUPPORT_LEGACY
515 scanlegacy = FALSE;
516 #endif
517 scanpci = FALSE;
525 D(bug("[ATA:PCI] ata_bus_Detect: Enumerating devices\n"));
527 if (scanpci)
529 BOOL doPCIScan = TRUE;
531 * Attempt to get PCI subsytem object.
532 * If this fails, PCI isn't there. But it's not fatal for us.
534 OOP_Object *pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
536 if (pci)
538 struct Hook FindHook =
540 .h_Entry = (IPTR (*)())ata_PCIEnumerator_h,
541 .h_Data = base
545 * Obtain PCI attribute and method bases only once.
547 if (!base->PCIDeviceAttrBase)
549 if (OOP_ObtainAttrBasesArray(&base->PCIDeviceAttrBase, &pciInterfaceIDs[ATTR_OFFSET]))
551 doPCIScan = FALSE;
553 if (OOP_ObtainMethodBasesArray(&base->PCIMethodBase, pciInterfaceIDs))
555 doPCIScan = FALSE;
559 if (doPCIScan)
561 D(bug("[ATA:PCI] ata_bus_Detect: Checking for supported PCI devices ..\n"));
563 HIDD_PCI_EnumDevices(pci, &FindHook, Requirements);
568 #ifdef SUPPORT_LEGACY
569 if (scanlegacy)
571 struct TagItem ata_tags[] =
573 {aHidd_Name , (IPTR)ataPCIName },
574 {aHidd_HardwareName , (IPTR)ataISAControllerName },
575 {TAG_DONE , 0 }
577 UBYTE n = base->legacycount;
579 D(bug("[ATA:PCI] ata_bus_Detect: Detecting Legacy-Buses\n"));
581 ata_ISA = HW_AddDriver(base->storageRoot, base->ataClass, ata_tags);
582 if (ata_ISA)
584 D(bug("[ATA:PCI] ata_bus_Detect: Adding Remaining Legacy-Buses\n"));
586 while (LegacyBuses[n].lb_Port)
588 probedbus = AllocVec(sizeof(struct ata_ProbedBus), MEMF_ANY);
589 if (probedbus)
591 probedbus->atapb_Parent = ata_ISA;
592 probedbus->atapb_Node.ln_Name = (STRPTR)LegacyBuses[n].lb_Name;
593 probedbus->atapb_Node.ln_Type = ATABUSNODEPRI_LEGACY;
594 probedbus->atapb_Node.ln_Pri = ATABUSNODEPRI_LEGACY - (base->ata__buscount++);
595 probedbus->atapb_Device = NULL;
596 probedbus->atapb_Vendor = 0;
597 probedbus->atapb_Product = 0;
598 probedbus->atapb_BusNo = LegacyBuses[n].lb_Bus;
599 probedbus->atapb_IOBase = LegacyBuses[n].lb_Port;
600 probedbus->atapb_IOAlt = LegacyBuses[n].lb_Alt;
601 probedbus->atapb_INTLine = LegacyBuses[n].lb_IRQ;
602 probedbus->atapb_DMABase = 0;
604 D(bug("[ATA:PCI] ata_bus_Detect: Adding Legacy Bus - IO: %x:%x\n",
605 probedbus->atapb_IOBase, probedbus->atapb_IOAlt));
607 Enqueue((struct List *)&base->probedbuses, &probedbus->atapb_Node);
609 n++;
613 #endif
615 D(bug("[ATA:PCI] ata_bus_Detect: Registering Probed Buses..\n"));
617 while ((probedbus = (struct ata_ProbedBus *)RemHead((struct List *)&base->probedbuses)) != NULL)
619 struct TagItem attrs[] =
621 {aHidd_Name , (IPTR)ataPCIName },
622 {aHidd_HardwareName , (IPTR)probedbus->atapb_Node.ln_Name },
623 {aHidd_Producer , probedbus->atapb_Vendor },
624 {aHidd_Product , probedbus->atapb_Product },
625 {aHidd_DriverData , (IPTR)probedbus },
626 {aHidd_ATABus_PIODataSize , sizeof(struct pio_data) },
627 {aHidd_ATABus_BusVectors , (IPTR)bus_FuncTable },
628 {aHidd_ATABus_PIOVectors , (IPTR)pio_FuncTable },
629 {aHidd_ATABus_DMADataSize , sizeof(struct dma_data) },
630 {aHidd_ATABus_DMAVectors , (IPTR)dma_FuncTable },
632 * Legacy ISA controllers have no other way to detect their
633 * presence. Do not confuse the user with phantom devices.
635 {aHidd_Bus_KeepEmpty , probedbus->atapb_Node.ln_Type == ATABUSNODEPRI_LEGACY
636 ? FALSE : TRUE },
637 {TAG_DONE , 0 }
639 OOP_Object *bus;
642 * We use this field as ownership indicator.
643 * The trick is that HW_AddDriver() fails if either object creation fails
644 * or subsystem-side setup fails. In the latter case our object will be
645 * disposed.
646 * We need to know whether OOP_DisposeObject() or we should deallocate
647 * this structure on failure.
649 probedbus->atapb_Node.ln_Succ = NULL;
651 D(bug("[ATA:PCI] ata_bus_Detect: Attaching Instance of 0x%p to Controller @ 0x%p\n", base->busClass, probedbus->atapb_Parent));
653 bus = HIDD_StorageController_AddBus(probedbus->atapb_Parent, base->busClass, attrs);
654 if (!bus)
656 D(bug("[ATA:PCI] Failed to create object for device %04X:%04X - IRQ %d, IO: %x:%x, DMA: %x\n",
657 probedbus->atapb_Vendor, probedbus->atapb_Product, probedbus->atapb_INTLine,
658 probedbus->atapb_IOBase, probedbus->atapb_IOAlt, probedbus->atapb_DMABase));
661 * Free the structure only upon object creation failure!
662 * In case of success it becomes owned by the driver object!
664 if (!probedbus->atapb_Node.ln_Succ)
666 DeviceUnref(probedbus->atapb_Device, base);
667 FreeVec(probedbus);
670 #ifdef SUPPORT_LEGACY
671 else if ((ata_ISA) && (probedbus->atapb_Parent == ata_ISA))
672 ata_ISA_Ports++;
673 #endif
676 #ifdef SUPPORT_LEGACY
677 if ((ata_ISA) && (ata_ISA_Ports == 0))
679 D(bug("[ATA:PCI] ata_bus_Detect: Disposing Unused ISA controller object\n");)
680 HW_RemoveDriver(base->storageRoot, ata_ISA);
682 #endif
684 D(bug("[ATA:PCI] ata_bus_Detect: Finished..\n");)
686 return TRUE;
689 ADD2INITLIB(ata_bus_Detect, 30)