2 Copyright © 2004-2019, The AROS Development Team. All rights reserved
9 #include <aros/debug.h>
11 #include <proto/exec.h>
13 /* We want all other bases obtained from our base */
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>
30 #include <hidd/storage.h>
31 #include <utility/utility.h>
32 #include <libraries/expansion.h>
33 #include <libraries/configvars.h>
35 #include <dos/dosextens.h>
36 #include <dos/filehandler.h>
42 #include LC_LIBDEFS_FILE
44 /* Add a bootnode using expansion.library */
45 BOOL
scsi_RegisterVolume(ULONG StartCyl
, ULONG EndCyl
, struct scsi_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",
60 /* This should be dealt with using some sort of volume manager or such. */
61 switch (unit
->su_DevType
)
63 case DG_DIRECT_ACCESS
:
69 D(bug("[SCSI>>]:-scsi_RegisterVolume called on unknown devicetype\n"));
72 if (unit
->su_UnitNum
< 10)
73 dosdevname
[2] += unit
->su_UnitNum
% 10;
75 dosdevname
[2] = 'A' - 10 + unit
->su_UnitNum
;
77 pp
[0] = (IPTR
)dosdevname
;
78 pp
[1] = (IPTR
)MOD_NAME_STRING
;
79 pp
[2] = unit
->su_UnitNum
;
80 pp
[DE_TABLESIZE
+ 4] = DE_BOOTBLOCKS
;
81 pp
[DE_SIZEBLOCK
+ 4] = 1 << (unit
->su_SectorShift
- 2);
82 pp
[DE_NUMHEADS
+ 4] = unit
->su_Heads
;
83 pp
[DE_SECSPERBLOCK
+ 4] = 1;
84 pp
[DE_BLKSPERTRACK
+ 4] = unit
->su_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
->su_DevType
== DG_DIRECT_ACCESS
) ? 0 : 10);
93 pp
[DE_DOSTYPE
+ 4] = ((unit
->su_DevType
== DG_DIRECT_ACCESS
) ? IdDOS
: IdCDVD
);
94 pp
[DE_CONTROL
+ 4] = 0;
95 pp
[DE_BOOTBLOCKS
+ 4] = 2;
97 devnode
= MakeDosNode(pp
);
101 D(bug("[SCSI>>]:-scsi_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
);
110 CloseLibrary((struct Library
*)ExpansionBase
);
116 #if defined(__OOP_NOATTRBASES__)
117 /* Keep order the same as order of IDs in struct scsiBase! */
118 static CONST_STRPTR
const attrBaseIDs
[] =
124 IID_Hidd_StorageUnit
,
129 #if defined(__OOP_NOMETHODBASES__)
130 static CONST_STRPTR
const methBaseIDs
[] =
134 IID_Hidd_StorageController
,
139 static int SCSI_init(struct scsiBase
*SCSIBase
)
141 struct BootLoaderBase
*BootLoaderBase
;
143 D(bug("[SCSI--] %s: scsi.device Initialization\n", __PRETTY_FUNCTION__
));
145 /* Prepare the list of detected controllers */
146 NEWLIST(&SCSIBase
->scsi_Controllers
);
148 /* Set default scsi.device config options */
149 SCSIBase
->scsi_32bit
= FALSE
;
150 SCSIBase
->scsi_NoMulti
= FALSE
;
151 SCSIBase
->scsi_NoDMA
= FALSE
;
152 SCSIBase
->scsi_Poll
= FALSE
;
155 * start initialization:
156 * obtain kernel parameters
158 BootLoaderBase
= OpenResource("bootloader.resource");
159 D(bug("[SCSI--] %s: BootloaderBase = %p\n", __PRETTY_FUNCTION__
, BootLoaderBase
));
160 if (BootLoaderBase
!= NULL
)
165 list
= (struct List
*)GetBootInfo(BL_Args
);
168 ForeachNode(list
, node
)
170 if (strncmp(node
->ln_Name
, "SCSI=", 4) == 0)
172 const char *CmdLine
= &node
->ln_Name
[4];
174 if (strstr(CmdLine
, "disable"))
176 D(bug("[SCSI ] %s: Disabling SCSI support\n", __PRETTY_FUNCTION__
));
179 if (strstr(CmdLine
, "32bit"))
181 D(bug("[SCSI ] %s: Using 32-bit IO transfers\n", __PRETTY_FUNCTION__
));
182 SCSIBase
->scsi_32bit
= TRUE
;
184 if (strstr(CmdLine
, "nomulti"))
186 D(bug("[SCSI ] %s: Disabled multisector transfers\n", __PRETTY_FUNCTION__
));
187 SCSIBase
->scsi_NoMulti
= TRUE
;
189 if (strstr(CmdLine
, "nodma"))
191 D(bug("[SCSI ] %s: Disabled DMA transfers\n", __PRETTY_FUNCTION__
));
192 SCSIBase
->scsi_NoDMA
= TRUE
;
194 if (strstr(CmdLine
, "poll"))
196 D(bug("[SCSI ] %s: Using polling to detect end of busy state\n", __PRETTY_FUNCTION__
));
197 SCSIBase
->scsi_Poll
= TRUE
;
204 SCSIBase
->scsi_UtilityBase
= OpenLibrary("utility.library", 36);
205 if (!SCSIBase
->scsi_UtilityBase
)
207 bug("[SCSI--] %s: Failed to open utility.library v36\n", __PRETTY_FUNCTION__
);
211 * I've decided to use memory pools again. Alloc everything needed from
212 * a pool, so that we avoid memory fragmentation.
214 SCSIBase
->scsi_MemPool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
| MEMF_SEM_PROTECTED
, 8192, 4096);
215 if (SCSIBase
->scsi_MemPool
== NULL
)
217 bug("[SCSI--] %s: Failed to Allocate MemPool!\n", __PRETTY_FUNCTION__
);
221 D(bug("[SCSI--] %s: MemPool @ %p\n", __PRETTY_FUNCTION__
, SCSIBase
->scsi_MemPool
));
223 #if defined(__OOP_NOATTRBASES__)
224 if (OOP_ObtainAttrBasesArray(&SCSIBase
->unitAttrBase
, attrBaseIDs
))
226 bug("[SCSI--] %s: Failed to obtain AttrBases!\n", __PRETTY_FUNCTION__
);
230 bug("[SCSI--] %s: HiddBusAB %x @ 0x%p\n", __func__
, HiddBusAB
, &HiddBusAB
);
231 bug("[SCSI--] %s: HiddSCSIBusAB %x @ 0x%p\n", __func__
, HiddSCSIBusAB
, &HiddSCSIBusAB
);
235 #if defined(__OOP_NOMETHODBASES__)
236 if (OOP_ObtainMethodBasesArray(&SCSIBase
->hwMethodBase
, methBaseIDs
))
238 bug("[SCSI--] %s: Failed to obtain MethodBases!\n", __PRETTY_FUNCTION__
);
239 bug("[SCSI--] %s: %s = %p\n", __PRETTY_FUNCTION__
, methBaseIDs
[0], SCSIBase
->hwMethodBase
);
240 bug("[SCSI--] %s: %s = %p\n", __PRETTY_FUNCTION__
, methBaseIDs
[1], SCSIBase
->busMethodBase
);
241 bug("[SCSI--] %s: %s = %p\n", __PRETTY_FUNCTION__
, methBaseIDs
[2], SCSIBase
->HiddSCMethodBase
);
242 #if defined(__OOP_NOATTRBASES__)
243 OOP_ReleaseAttrBasesArray(&SCSIBase
->unitAttrBase
, attrBaseIDs
);
249 D(bug("[SCSI ] %s: Base SCSI Hidd Class @ 0x%p\n", __PRETTY_FUNCTION__
, SCSIBase
->scsiClass
));
251 /* Try to setup daemon task looking for diskchanges */
252 NEWLIST(&SCSIBase
->Daemon_ios
);
253 InitSemaphore(&SCSIBase
->DaemonSem
);
254 InitSemaphore(&SCSIBase
->DetectionSem
);
255 SCSIBase
->daemonParent
= FindTask(NULL
);
256 SetSignal(0, SIGF_SINGLE
);
258 if (!NewCreateTask(TASKTAG_PC
, DaemonCode
,
259 TASKTAG_NAME
, "SCSI.daemon",
260 TASKTAG_STACKSIZE
, STACK_SIZE
,
261 TASKTAG_TASKMSGPORT
, &SCSIBase
->DaemonPort
,
262 TASKTAG_PRI
, TASK_PRI
- 1, /* The daemon should have a little bit lower Pri than handler tasks */
263 TASKTAG_ARG1
, SCSIBase
,
266 bug("[SCSI ] %s: Failed to start up daemon!\n", __PRETTY_FUNCTION__
);
270 /* Wait for handshake */
272 D(bug("[SCSI ] %s: Daemon task set to 0x%p\n", __PRETTY_FUNCTION__
, SCSIBase
->scsi_Daemon
));
274 return SCSIBase
->scsi_Daemon
? TRUE
: FALSE
;
277 static int scsi_expunge(struct scsiBase
*SCSIBase
)
279 struct scsi_Controller
*scsiNode
, *tmpNode
;
280 ForeachNodeSafe (&SCSIBase
->scsi_Controllers
, scsiNode
, 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 scsiBase 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
);
291 storageRoot
= OOP_NewObject(NULL
, CLID_HW_Root
, NULL
);
292 if (storageRoot
&& HW_RemoveDriver(storageRoot
, scsiNode
->sc_Object
))
294 Remove(&scsiNode
->sc_Node
);
295 /* Destroy our singletone */
296 OOP_MethodID disp_msg
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
298 D(bug("[SCSI ] scsi_expunge: Stopping Daemon...\n"));
299 SCSIBase
->daemonParent
= FindTask(NULL
);
300 SetSignal(0, SIGF_SINGLE
);
301 Signal(SCSIBase
->scsi_Daemon
, SIGBREAKF_CTRL_C
);
304 D(bug("[SCSI ] scsi_expunge: Done, destroying subystem object\n"));
305 OOP_DoSuperMethod(scsiNode
->sc_Class
, scsiNode
->sc_Object
, &disp_msg
);
306 FreeMem(scsiNode
, sizeof(struct scsi_Controller
));
310 /* Our subsystem is in use, we have some bus driver(s) around. */
311 D(bug("[SCSI ] scsi_expunge: SCSI subsystem is in use\n"));
316 #if defined(__OOP_NOATTRBASES__)
317 D(bug("[SCSI ] scsi_expunge: Releasing attribute bases\n"));
318 OOP_ReleaseAttrBasesArray(&SCSIBase
->unitAttrBase
, attrBaseIDs
);
321 if (SCSIBase
->scsi_UtilityBase
)
322 CloseLibrary(SCSIBase
->scsi_UtilityBase
);
324 D(bug("[SCSI ] scsi_expunge: Exiting\n"));
328 static int open(struct scsiBase
*SCSIBase
, struct IORequest
*iorq
,
329 ULONG unitnum
, ULONG flags
)
331 struct scsi_Controller
*scsiNode
;
332 struct Hook searchHook
=
334 .h_Entry
= Hidd_SCSIBus_Open
,
338 /* Assume it failed */
339 iorq
->io_Error
= IOERR_OPENFAIL
;
340 iorq
->io_Device
= &SCSIBase
->scsi_Device
;
341 iorq
->io_Unit
= (APTR
)(IPTR
)-1;
343 /* Try to find the unit */
344 ForeachNode (&SCSIBase
->scsi_Controllers
, scsiNode
)
346 HIDD_StorageController_EnumBuses(scsiNode
->sc_Object
, &searchHook
, (APTR
)(IPTR
)unitnum
);
348 D(bug("[SCSI%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 */
357 LIBBASETYPEPTR LIBBASE
,
358 struct IORequest
*iorq
361 struct scsi_Unit
*unit
= (struct scsi_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
->su_Unit
.unit_OpenCnt
--;
372 ADD2INITLIB(SCSI_init
, 0)
373 ADD2EXPUNGELIB(scsi_expunge
, 0)
375 ADD2CLOSEDEV(close
, 0)