revert between 56095 -> 55830 in arch
[AROS.git] / rom / devs / ata / ata_init.c
blob4aac4a9bb296a07cfaf8e12c32489740d6d03878
1 /*
2 Copyright © 2004-2019, The AROS Development Team. All rights reserved
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #include <aros/debug.h>
11 #include <proto/exec.h>
13 /* We want all other bases obtained from our base */
14 #define __NOLIBBASE__
16 #include <proto/timer.h>
17 #include <proto/bootloader.h>
18 #include <proto/expansion.h>
19 #include <proto/oop.h>
21 #include <aros/bootloader.h>
22 #include <aros/symbolsets.h>
23 #include <exec/exec.h>
24 #include <exec/resident.h>
25 #include <exec/tasks.h>
26 #include <exec/memory.h>
27 #include <exec/nodes.h>
28 #include <hidd/hidd.h>
29 #include <hidd/bus.h>
30 #include <hidd/storage.h>
31 #include <utility/utility.h>
32 #include <libraries/expansion.h>
33 #include <libraries/configvars.h>
34 #include <dos/bptr.h>
35 #include <dos/dosextens.h>
36 #include <dos/filehandler.h>
37 #include <string.h>
39 #include "ata.h"
40 #include "timer.h"
42 #include LC_LIBDEFS_FILE
44 /* Add a bootnode using expansion.library */
45 BOOL ata_RegisterVolume(ULONG StartCyl, ULONG EndCyl, struct ata_Unit *unit)
47 struct ExpansionBase *ExpansionBase;
48 struct DeviceNode *devnode;
49 TEXT dosdevname[4] = "HD0";
50 const ULONG IdDOS = AROS_MAKE_ID('D','O','S','\001');
51 const ULONG IdCDVD = AROS_MAKE_ID('C','D','V','D');
53 ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",
54 40L);
56 if (ExpansionBase)
58 IPTR pp[24];
60 /* This should be dealt with using some sort of volume manager or such. */
61 switch (unit->au_DevType)
63 case DG_DIRECT_ACCESS:
64 break;
65 case DG_CDROM:
66 dosdevname[0] = 'C';
67 break;
68 default:
69 D(bug("[ATA>>]:-ata_RegisterVolume called on unknown devicetype\n"));
72 if (unit->au_UnitNum < 10)
73 dosdevname[2] += unit->au_UnitNum % 10;
74 else
75 dosdevname[2] = 'A' - 10 + unit->au_UnitNum;
77 pp[0] = (IPTR)dosdevname;
78 pp[1] = (IPTR)MOD_NAME_STRING;
79 pp[2] = unit->au_UnitNum;
80 pp[DE_TABLESIZE + 4] = DE_BOOTBLOCKS;
81 pp[DE_SIZEBLOCK + 4] = 1 << (unit->au_SectorShift - 2);
82 pp[DE_NUMHEADS + 4] = unit->au_Heads;
83 pp[DE_SECSPERBLOCK + 4] = 1;
84 pp[DE_BLKSPERTRACK + 4] = unit->au_Sectors;
85 pp[DE_RESERVEDBLKS + 4] = 2;
86 pp[DE_LOWCYL + 4] = StartCyl;
87 pp[DE_HIGHCYL + 4] = EndCyl;
88 pp[DE_NUMBUFFERS + 4] = 10;
89 pp[DE_BUFMEMTYPE + 4] = MEMF_PUBLIC | MEMF_31BIT;
90 pp[DE_MAXTRANSFER + 4] = 0x00200000;
91 pp[DE_MASK + 4] = 0x7FFFFFFE;
92 pp[DE_BOOTPRI + 4] = ((unit->au_DevType == DG_DIRECT_ACCESS) ? 0 : 10);
93 pp[DE_DOSTYPE + 4] = ((unit->au_DevType == DG_DIRECT_ACCESS) ? IdDOS : IdCDVD);
94 pp[DE_CONTROL + 4] = 0;
95 pp[DE_BOOTBLOCKS + 4] = 2;
97 devnode = MakeDosNode(pp);
99 if (devnode)
101 D(bug("[ATA>>]:-ata_RegisterVolume: '%b', type=0x%08lx with StartCyl=%d, EndCyl=%d .. ",
102 devnode->dn_Name, pp[DE_DOSTYPE + 4], StartCyl, EndCyl));
104 AddBootNode(pp[DE_BOOTPRI + 4], ADNF_STARTPROC, devnode, NULL);
105 D(bug("done\n"));
107 return TRUE;
110 CloseLibrary((struct Library *)ExpansionBase);
113 return FALSE;
116 #if defined(__OOP_NOATTRBASES__)
117 /* Keep order the same as order of IDs in struct ataBase! */
118 static CONST_STRPTR const attrBaseIDs[] =
120 IID_Hidd_ATAUnit,
121 IID_HW,
122 IID_Hidd_Bus,
123 IID_Hidd_ATABus,
124 IID_Hidd_StorageUnit,
125 NULL
127 #endif
129 #if defined(__OOP_NOMETHODBASES__)
130 static CONST_STRPTR const methBaseIDs[] =
132 IID_HW,
133 IID_Hidd_ATABus,
134 IID_Hidd_StorageController,
135 NULL
137 #endif
139 static int ATA_init(struct ataBase *ATABase)
141 struct BootLoaderBase *BootLoaderBase;
143 D(bug("[ATA--] %s: ata.device Initialization\n", __PRETTY_FUNCTION__));
145 /* Prepare the list of detected controllers */
146 NEWLIST(&ATABase->ata_Controllers);
148 /* Set default ata.device config options */
149 ATABase->ata_32bit = FALSE;
150 ATABase->ata_NoMulti = FALSE;
151 ATABase->ata_NoDMA = FALSE;
152 ATABase->ata_Poll = FALSE;
155 * start initialization:
156 * obtain kernel parameters
158 BootLoaderBase = OpenResource("bootloader.resource");
159 D(bug("[ATA--] %s: BootloaderBase = %p\n", __PRETTY_FUNCTION__, BootLoaderBase));
160 if (BootLoaderBase != NULL)
162 struct List *list;
163 struct Node *node;
165 list = (struct List *)GetBootInfo(BL_Args);
166 if (list)
168 ForeachNode(list, node)
170 if (strncmp(node->ln_Name, "ATA=", 4) == 0)
172 const char *CmdLine = &node->ln_Name[4];
174 if (strstr(CmdLine, "disable"))
176 D(bug("[ATA ] %s: Disabling ATA support\n", __PRETTY_FUNCTION__));
177 return FALSE;
179 if (strstr(CmdLine, "32bit"))
181 D(bug("[ATA ] %s: Using 32-bit IO transfers\n", __PRETTY_FUNCTION__));
182 ATABase->ata_32bit = TRUE;
184 if (strstr(CmdLine, "nomulti"))
186 D(bug("[ATA ] %s: Disabled multisector transfers\n", __PRETTY_FUNCTION__));
187 ATABase->ata_NoMulti = TRUE;
189 if (strstr(CmdLine, "nodma"))
191 D(bug("[ATA ] %s: Disabled DMA transfers\n", __PRETTY_FUNCTION__));
192 ATABase->ata_NoDMA = TRUE;
194 if (strstr(CmdLine, "poll"))
196 D(bug("[ATA ] %s: Using polling to detect end of busy state\n", __PRETTY_FUNCTION__));
197 ATABase->ata_Poll = TRUE;
204 ATABase->ata_UtilityBase = OpenLibrary("utility.library", 36);
205 if (!ATABase->ata_UtilityBase)
207 bug("[ATA--] %s: Failed to open utility.library v36\n", __PRETTY_FUNCTION__);
208 return FALSE;
211 * I've decided to use memory pools again. Alloc everything needed from
212 * a pool, so that we avoid memory fragmentation.
214 ATABase->ata_MemPool = CreatePool(MEMF_CLEAR | MEMF_PUBLIC | MEMF_SEM_PROTECTED , 8192, 4096);
215 if (ATABase->ata_MemPool == NULL)
217 bug("[ATA--] %s: Failed to Allocate MemPool!\n", __PRETTY_FUNCTION__);
218 return FALSE;
221 D(bug("[ATA--] %s: MemPool @ %p\n", __PRETTY_FUNCTION__, ATABase->ata_MemPool));
223 #if defined(__OOP_NOATTRBASES__)
224 if (OOP_ObtainAttrBasesArray(&ATABase->unitAttrBase, attrBaseIDs))
226 bug("[ATA--] %s: Failed to obtain AttrBases!\n", __PRETTY_FUNCTION__);
227 return FALSE;
230 bug("[ATA--] %s: HiddBusAB %x @ 0x%p\n", __func__, HiddBusAB, &HiddBusAB);
231 bug("[ATA--] %s: HiddATABusAB %x @ 0x%p\n", __func__, HiddATABusAB, &HiddATABusAB);
233 #endif
235 #if defined(__OOP_NOMETHODBASES__)
236 if (OOP_ObtainMethodBasesArray(&ATABase->hwMethodBase, methBaseIDs))
238 bug("[ATA--] %s: Failed to obtain MethodBases!\n", __PRETTY_FUNCTION__);
239 bug("[ATA--] %s: %s = %p\n", __PRETTY_FUNCTION__, methBaseIDs[0], ATABase->hwMethodBase);
240 bug("[ATA--] %s: %s = %p\n", __PRETTY_FUNCTION__, methBaseIDs[1], ATABase->busMethodBase);
241 bug("[ATA--] %s: %s = %p\n", __PRETTY_FUNCTION__, methBaseIDs[2], ATABase->HiddSCMethodBase);
242 #if defined(__OOP_NOATTRBASES__)
243 OOP_ReleaseAttrBasesArray(&ATABase->unitAttrBase, attrBaseIDs);
244 #endif
245 return FALSE;
247 #endif
249 D(bug("[ATA ] %s: Base ATA Hidd Class @ 0x%p\n", __PRETTY_FUNCTION__, ATABase->ataClass));
251 /* Try to setup daemon task looking for diskchanges */
252 NEWLIST(&ATABase->Daemon_ios);
253 InitSemaphore(&ATABase->DaemonSem);
254 InitSemaphore(&ATABase->DetectionSem);
255 ATABase->daemonParent = FindTask(NULL);
256 SetSignal(0, SIGF_SINGLE);
258 if (!NewCreateTask(TASKTAG_PC, DaemonCode,
259 TASKTAG_NAME , "ATA.daemon",
260 TASKTAG_STACKSIZE , STACK_SIZE,
261 TASKTAG_TASKMSGPORT, &ATABase->DaemonPort,
262 TASKTAG_PRI , TASK_PRI - 1, /* The daemon should have a little bit lower Pri than handler tasks */
263 TASKTAG_ARG1 , ATABase,
264 TAG_DONE))
266 bug("[ATA ] %s: Failed to start up daemon!\n", __PRETTY_FUNCTION__);
267 return FALSE;
270 /* Wait for handshake */
271 Wait(SIGF_SINGLE);
272 D(bug("[ATA ] %s: Daemon task set to 0x%p\n", __PRETTY_FUNCTION__, ATABase->ata_Daemon));
274 return ATABase->ata_Daemon ? TRUE : FALSE;
277 static int ata_expunge(struct ataBase *ATABase)
279 struct ata_Controller *ataNode, *tmpNode;
280 ForeachNodeSafe (&ATABase->ata_Controllers, ataNode, tmpNode)
282 OOP_Object *storageRoot;
284 * CLID_Hidd_Storage is a singletone, you can get it as many times as
285 * you want. Here we save up some space in struct ataBase by
286 * obtaining storageRoot object only when we need it. This happens
287 * rarely, so small performance loss is OK here.
289 storageRoot = OOP_NewObject(NULL, CLID_Hidd_Storage, NULL);
290 if (!storageRoot)
291 storageRoot = OOP_NewObject(NULL, CLID_HW_Root, NULL);
292 if (storageRoot && HW_RemoveDriver(storageRoot, ataNode->ac_Object))
294 Remove(&ataNode->ac_Node);
295 /* Destroy our singletone */
296 OOP_MethodID disp_msg = OOP_GetMethodID(IID_Root, moRoot_Dispose);
298 D(bug("[ATA ] ata_expunge: Stopping Daemon...\n"));
299 ATABase->daemonParent = FindTask(NULL);
300 SetSignal(0, SIGF_SINGLE);
301 Signal(ATABase->ata_Daemon, SIGBREAKF_CTRL_C);
302 Wait(SIGF_SINGLE);
304 D(bug("[ATA ] ata_expunge: Done, destroying subystem object\n"));
305 OOP_DoSuperMethod(ataNode->ac_Class, ataNode->ac_Object, &disp_msg);
306 FreeMem(ataNode, sizeof(struct ata_Controller));
308 else
310 /* Our subsystem is in use, we have some bus driver(s) around. */
311 D(bug("[ATA ] ata_expunge: ATA subsystem is in use\n"));
312 return FALSE;
316 #if defined(__OOP_NOATTRBASES__)
317 D(bug("[ATA ] ata_expunge: Releasing attribute bases\n"));
318 OOP_ReleaseAttrBasesArray(&ATABase->unitAttrBase, attrBaseIDs);
319 #endif
321 if (ATABase->ata_UtilityBase)
322 CloseLibrary(ATABase->ata_UtilityBase);
324 D(bug("[ATA ] ata_expunge: Exiting\n"));
325 return TRUE;
328 static int open(struct ataBase *ATABase, struct IORequest *iorq,
329 ULONG unitnum, ULONG flags)
331 struct ata_Controller *ataNode;
332 struct Hook searchHook =
334 .h_Entry = Hidd_ATABus_Open,
335 .h_Data = iorq
338 /* Assume it failed */
339 iorq->io_Error = IOERR_OPENFAIL;
340 iorq->io_Device = &ATABase->ata_Device;
341 iorq->io_Unit = (APTR)(IPTR)-1;
343 /* Try to find the unit */
344 ForeachNode (&ATABase->ata_Controllers, ataNode)
346 HIDD_StorageController_EnumBuses(ataNode->ac_Object, &searchHook, (APTR)(IPTR)unitnum);
348 D(bug("[ATA%02d] Open result: %d\n", unitnum, iorq->io_Error));
350 /* If found, io_Error will be reset to zero */
351 return iorq->io_Error ? FALSE : TRUE;
354 /* Close given device */
355 static int close
357 LIBBASETYPEPTR LIBBASE,
358 struct IORequest *iorq
361 struct ata_Unit *unit = (struct ata_Unit *)iorq->io_Unit;
363 /* First of all make the important fields of struct IORequest invalid! */
364 iorq->io_Unit = (struct Unit *)~0;
366 /* Decrease use counters of unit */
367 unit->au_Unit.unit_OpenCnt--;
369 return TRUE;
372 ADD2INITLIB(ATA_init, 0)
373 ADD2EXPUNGELIB(ata_expunge, 0)
374 ADD2OPENDEV(open, 0)
375 ADD2CLOSEDEV(close, 0)