2 Copyright © 2004-2016, The AROS Development Team. All rights reserved
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>
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>
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",
57 /* This should be dealt with using some sort of volume manager or such. */
58 switch (unit
->au_DevType
)
60 case DG_DIRECT_ACCESS
:
66 D(bug("[ATA>>]:-ata_RegisterVolume called on unknown devicetype\n"));
69 if (unit
->au_UnitNum
< 10)
70 dosdevname
[2] += unit
->au_UnitNum
% 10;
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
);
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
);
107 CloseLibrary((struct Library
*)ExpansionBase
);
113 /* Keep order the same as order of IDs in struct ataBase! */
114 static CONST_STRPTR
const attrBaseIDs
[] =
122 #define ATA_METHOD_ID_START 1
125 Here shall we start. Make function static as it shouldn't be visible from
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
)
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
)
147 D(bug("[ATA--] ata_init: MemPool @ %p\n", ATABase
->ata_MemPool
));
149 if (OOP_ObtainAttrBasesArray(&ATABase
->unitAttrBase
, attrBaseIDs
))
152 /* This is our own method base, so no check needed */
153 if (OOP_ObtainMethodBasesArray(&ATABase
->hwMethodBase
, &attrBaseIDs
[ATA_METHOD_ID_START
]))
156 storageRoot
= OOP_NewObject(NULL
, CLID_Hidd_Storage
, NULL
);
158 storageRoot
= OOP_NewObject(NULL
, CLID_HW_Root
, NULL
);
162 if (!HW_AddDriver(storageRoot
, ATABase
->ataClass
, NULL
))
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
)
182 list
= (struct List
*)GetBootInfo(BL_Args
);
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
,
231 D(bug("[ATA ] Failed to start up daemon!\n"));
235 /* Wait for handshake */
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
)
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
);
265 D(bug("[ATA ] ata_expunge: Done, destroying subystem object\n"));
266 OOP_DoSuperMethod(ATABase
->ataClass
, ATABase
->ataObj
, &disp_msg
);
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"));
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"));
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
,
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 */
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
--;
327 ADD2INITLIB(ata_init
, 0)
328 ADD2EXPUNGELIB(ata_expunge
, 0)
330 ADD2CLOSEDEV(close
, 0)