scripts: add crosstools packages for i386 and armhf
[AROS.git] / rom / devs / ata / ata_init.c
blob8a32d110dc3aba57ae0143c5836e990e5cae114c
1 /*
2 Copyright © 2004-2016, The AROS Development Team. All rights reserved
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #define __OOP_NOMETHODBASES__
11 #include <aros/bootloader.h>
12 #include <aros/debug.h>
13 #include <aros/symbolsets.h>
14 #include <exec/exec.h>
15 #include <exec/resident.h>
16 #include <exec/tasks.h>
17 #include <exec/memory.h>
18 #include <exec/nodes.h>
19 #include <hidd/hidd.h>
20 #include <hidd/storage.h>
21 #include <utility/utility.h>
22 #include <libraries/expansion.h>
23 #include <libraries/configvars.h>
24 #include <dos/bptr.h>
25 #include <dos/dosextens.h>
26 #include <dos/filehandler.h>
28 #include <proto/exec.h>
29 #include <proto/timer.h>
30 #include <proto/bootloader.h>
31 #include <proto/expansion.h>
32 #include <proto/oop.h>
34 #include <string.h>
36 #include "ata.h"
37 #include "timer.h"
39 #include LC_LIBDEFS_FILE
41 /* Add a bootnode using expansion.library */
42 BOOL ata_RegisterVolume(ULONG StartCyl, ULONG EndCyl, struct ata_Unit *unit)
44 struct ExpansionBase *ExpansionBase;
45 struct DeviceNode *devnode;
46 TEXT dosdevname[4] = "HD0";
47 const ULONG IdDOS = AROS_MAKE_ID('D','O','S','\001');
48 const ULONG IdCDVD = AROS_MAKE_ID('C','D','V','D');
50 ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",
51 40L);
53 if (ExpansionBase)
55 IPTR pp[24];
57 /* This should be dealt with using some sort of volume manager or such. */
58 switch (unit->au_DevType)
60 case DG_DIRECT_ACCESS:
61 break;
62 case DG_CDROM:
63 dosdevname[0] = 'C';
64 break;
65 default:
66 D(bug("[ATA>>]:-ata_RegisterVolume called on unknown devicetype\n"));
69 if (unit->au_UnitNum < 10)
70 dosdevname[2] += unit->au_UnitNum % 10;
71 else
72 dosdevname[2] = 'A' - 10 + unit->au_UnitNum;
74 pp[0] = (IPTR)dosdevname;
75 pp[1] = (IPTR)MOD_NAME_STRING;
76 pp[2] = unit->au_UnitNum;
77 pp[DE_TABLESIZE + 4] = DE_BOOTBLOCKS;
78 pp[DE_SIZEBLOCK + 4] = 1 << (unit->au_SectorShift - 2);
79 pp[DE_NUMHEADS + 4] = unit->au_Heads;
80 pp[DE_SECSPERBLOCK + 4] = 1;
81 pp[DE_BLKSPERTRACK + 4] = unit->au_Sectors;
82 pp[DE_RESERVEDBLKS + 4] = 2;
83 pp[DE_LOWCYL + 4] = StartCyl;
84 pp[DE_HIGHCYL + 4] = EndCyl;
85 pp[DE_NUMBUFFERS + 4] = 10;
86 pp[DE_BUFMEMTYPE + 4] = MEMF_PUBLIC | MEMF_31BIT;
87 pp[DE_MAXTRANSFER + 4] = 0x00200000;
88 pp[DE_MASK + 4] = 0x7FFFFFFE;
89 pp[DE_BOOTPRI + 4] = ((unit->au_DevType == DG_DIRECT_ACCESS) ? 0 : 10);
90 pp[DE_DOSTYPE + 4] = ((unit->au_DevType == DG_DIRECT_ACCESS) ? IdDOS : IdCDVD);
91 pp[DE_CONTROL + 4] = 0;
92 pp[DE_BOOTBLOCKS + 4] = 2;
94 devnode = MakeDosNode(pp);
96 if (devnode)
98 D(bug("[ATA>>]:-ata_RegisterVolume: '%b', type=0x%08lx with StartCyl=%d, EndCyl=%d .. ",
99 devnode->dn_Name, pp[DE_DOSTYPE + 4], StartCyl, EndCyl));
101 AddBootNode(pp[DE_BOOTPRI + 4], ADNF_STARTPROC, devnode, NULL);
102 D(bug("done\n"));
104 return TRUE;
107 CloseLibrary((struct Library *)ExpansionBase);
110 return FALSE;
113 /* Keep order the same as order of IDs in struct ataBase! */
114 static CONST_STRPTR const attrBaseIDs[] =
116 IID_Hidd_ATAUnit,
117 IID_HW,
118 IID_Hidd_ATABus,
119 NULL
122 #define ATA_METHOD_ID_START 1
125 Here shall we start. Make function static as it shouldn't be visible from
126 outside.
128 static int ata_init(struct ataBase *ATABase)
130 OOP_Object *storageRoot;
131 struct BootLoaderBase *BootLoaderBase;
133 D(bug("[ATA--] ata_init: ata.device Initialization\n"));
135 ATABase->ata_UtilityBase = OpenLibrary("utility.library", 36);
136 if (!ATABase->ata_UtilityBase)
137 return FALSE;
140 * I've decided to use memory pools again. Alloc everything needed from
141 * a pool, so that we avoid memory fragmentation.
143 ATABase->ata_MemPool = CreatePool(MEMF_CLEAR | MEMF_PUBLIC | MEMF_SEM_PROTECTED , 8192, 4096);
144 if (ATABase->ata_MemPool == NULL)
145 return FALSE;
147 D(bug("[ATA--] ata_init: MemPool @ %p\n", ATABase->ata_MemPool));
149 if (OOP_ObtainAttrBasesArray(&ATABase->unitAttrBase, attrBaseIDs))
150 return FALSE;
152 /* This is our own method base, so no check needed */
153 if (OOP_ObtainMethodBasesArray(&ATABase->hwMethodBase, &attrBaseIDs[ATA_METHOD_ID_START]))
154 return FALSE;
156 storageRoot = OOP_NewObject(NULL, CLID_Hidd_Storage, NULL);
157 if (!storageRoot)
158 storageRoot = OOP_NewObject(NULL, CLID_HW_Root, NULL);
159 if (!storageRoot)
160 return FALSE;
162 if (!HW_AddDriver(storageRoot, ATABase->ataClass, NULL))
163 return FALSE;
165 /* Set default ata.device config options */
166 ATABase->ata_32bit = FALSE;
167 ATABase->ata_NoMulti = FALSE;
168 ATABase->ata_NoDMA = FALSE;
169 ATABase->ata_Poll = FALSE;
172 * start initialization:
173 * obtain kernel parameters
175 BootLoaderBase = OpenResource("bootloader.resource");
176 D(bug("[ATA--] ata_init: BootloaderBase = %p\n", BootLoaderBase));
177 if (BootLoaderBase != NULL)
179 struct List *list;
180 struct Node *node;
182 list = (struct List *)GetBootInfo(BL_Args);
183 if (list)
185 ForeachNode(list, node)
187 if (strncmp(node->ln_Name, "ATA=", 4) == 0)
189 const char *CmdLine = &node->ln_Name[4];
191 if (strstr(CmdLine, "32bit"))
193 D(bug("[ATA ] ata_init: Using 32-bit IO transfers\n"));
194 ATABase->ata_32bit = TRUE;
196 if (strstr(CmdLine, "nomulti"))
198 D(bug("[ATA ] ata_init: Disabled multisector transfers\n"));
199 ATABase->ata_NoMulti = TRUE;
201 if (strstr(CmdLine, "nodma"))
203 D(bug("[ATA ] ata_init: Disabled DMA transfers\n"));
204 ATABase->ata_NoDMA = TRUE;
206 if (strstr(CmdLine, "poll"))
208 D(bug("[ATA ] ata_init: Using polling to detect end of busy state\n"));
209 ATABase->ata_Poll = TRUE;
216 /* Try to setup daemon task looking for diskchanges */
217 NEWLIST(&ATABase->Daemon_ios);
218 InitSemaphore(&ATABase->DaemonSem);
219 InitSemaphore(&ATABase->DetectionSem);
220 ATABase->daemonParent = FindTask(NULL);
221 SetSignal(0, SIGF_SINGLE);
223 if (!NewCreateTask(TASKTAG_PC, DaemonCode,
224 TASKTAG_NAME , "ATA.daemon",
225 TASKTAG_STACKSIZE , STACK_SIZE,
226 TASKTAG_TASKMSGPORT, &ATABase->DaemonPort,
227 TASKTAG_PRI , TASK_PRI - 1, /* The daemon should have a little bit lower Pri than handler tasks */
228 TASKTAG_ARG1 , ATABase,
229 TAG_DONE))
231 D(bug("[ATA ] Failed to start up daemon!\n"));
232 return FALSE;
235 /* Wait for handshake */
236 Wait(SIGF_SINGLE);
237 D(bug("[ATA ] Daemon task set to 0x%p\n", ATABase->ata_Daemon));
239 return ATABase->ata_Daemon ? TRUE : FALSE;
242 static int ata_expunge(struct ataBase *ATABase)
244 if (ATABase->ataObj)
247 * CLID_Hidd_Storage is a singletone, you can get it as many times as
248 * you want. Here we save up some space in struct ataBase by
249 * obtaining storageRoot object only when we need it. This happens
250 * rarely, so small performance loss is OK here.
252 OOP_Object *storageRoot = OOP_NewObject(NULL, CLID_Hidd_Storage, NULL);
254 if (storageRoot && HW_RemoveDriver(storageRoot, ATABase->ataObj))
256 /* Destroy our singletone */
257 OOP_MethodID disp_msg = OOP_GetMethodID(IID_Root, moRoot_Dispose);
259 D(bug("[ATA ] ata_expunge: Stopping Daemon...\n"));
260 ATABase->daemonParent = FindTask(NULL);
261 SetSignal(0, SIGF_SINGLE);
262 Signal(ATABase->ata_Daemon, SIGBREAKF_CTRL_C);
263 Wait(SIGF_SINGLE);
265 D(bug("[ATA ] ata_expunge: Done, destroying subystem object\n"));
266 OOP_DoSuperMethod(ATABase->ataClass, ATABase->ataObj, &disp_msg);
268 else
270 /* Our subsystem is in use, we have some bus driver(s) around. */
271 D(bug("[ATA ] ata_expunge: ATA subsystem is in use\n"));
272 return FALSE;
276 D(bug("[ATA ] ata_expunge: Releasing attribute bases\n"));
277 OOP_ReleaseAttrBasesArray(&ATABase->hwAttrBase, attrBaseIDs);
279 if (ATABase->ata_UtilityBase)
280 CloseLibrary(ATABase->ata_UtilityBase);
282 D(bug("[ATA ] ata_expunge: Exiting\n"));
283 return TRUE;
286 static int open(struct ataBase *ATABase, struct IORequest *iorq,
287 ULONG unitnum, ULONG flags)
289 struct Hook searchHook =
291 .h_Entry = Hidd_ATABus_Open,
292 .h_Data = iorq
295 /* Assume it failed */
296 iorq->io_Error = IOERR_OPENFAIL;
297 iorq->io_Device = &ATABase->ata_Device;
298 iorq->io_Unit = (APTR)(IPTR)-1;
300 /* Try to find the unit */
301 HW_EnumDrivers(ATABase->ataObj, &searchHook, (APTR)(IPTR)unitnum);
303 D(bug("[ATA%02d] Open result: %d\n", unitnum, iorq->io_Error));
305 /* If found, io_Error will be reset to zero */
306 return iorq->io_Error ? FALSE : TRUE;
309 /* Close given device */
310 static int close
312 LIBBASETYPEPTR LIBBASE,
313 struct IORequest *iorq
316 struct ata_Unit *unit = (struct ata_Unit *)iorq->io_Unit;
318 /* First of all make the important fields of struct IORequest invalid! */
319 iorq->io_Unit = (struct Unit *)~0;
321 /* Decrease use counters of unit */
322 unit->au_Unit.unit_OpenCnt--;
324 return TRUE;
327 ADD2INITLIB(ata_init, 0)
328 ADD2EXPUNGELIB(ata_expunge, 0)
329 ADD2OPENDEV(open, 0)
330 ADD2CLOSEDEV(close, 0)