2 Copyright (C) 2015-2019, The AROS Development Team.
6 #include <aros/debug.h>
8 #define __STORAGE_NOLIBBASE__
10 #include <proto/sysexp.h>
11 #include <proto/storage.h>
13 #include <proto/alib.h>
14 #include <proto/dos.h>
15 #include <proto/exec.h>
16 #include <proto/muimaster.h>
17 #include <proto/oop.h>
18 #include <proto/utility.h>
19 #include <proto/intuition.h>
21 #include <mui/NListtree_mcc.h>
22 #include <utility/tagitem.h>
23 #include <utility/hooks.h>
25 #include <devices/newstyle.h>
26 #include <devices/ata.h>
31 #include "storage_classes.h"
32 #include "storage_intern.h"
34 #if (1) // TODO : Move into libbase
35 extern OOP_AttrBase HiddAttrBase
;
36 extern OOP_AttrBase HWAttrBase
;
37 extern OOP_AttrBase HiddStorageUnitAB
;
39 extern OOP_MethodID HWBase
;
40 extern OOP_MethodID HiddStorageControllerBase
;
41 extern OOP_MethodID HiddStorageBusBase
;
42 extern OOP_MethodID HiddStorageUnitBase
;
45 CONST_STRPTR storagebuswindowclass_name
= "StorageBusWindow.Class";
46 CONST_STRPTR storageunitwindowclass_name
= "StorageUnitWindow.Class";
48 AROS_UFH3S(BOOL
, storageenumFunc
,
49 AROS_UFHA(struct Hook
*, h
, A0
),
50 AROS_UFHA(OOP_Object
*, obj
, A2
),
51 AROS_UFHA(void *, parent
, A1
))
56 CONST_STRPTR name
= NULL
;
57 struct MUI_NListtree_TreeNode
*tn
;
59 struct SysexpEnum_data
*edata
= (struct SysexpEnum_data
*)h
->h_Data
;
60 struct InsertObjectMsg msg
=
65 struct ClassHandlerNode
*clHandlers
;
66 struct SysexpBase
*SysexpBase
;
68 D(bug("[storage.sysexp] %s()\n", __func__
));
73 SysexpBase
= edata
->ed_sysexpbase
;
74 clHandlers
= FindObjectHandler(obj
, edata
->ed_list
);
76 D(bug("[storage.sysexp] %s: list @ 0x%p\n", __func__
, edata
->ed_list
));
77 D(bug("[storage.sysexp] %s: handler @ 0x%p\n", __func__
, clHandlers
));
81 if (clHandlers
->muiClass
)
82 msg
.winClass
= clHandlers
->muiClass
;
83 if (clHandlers
->enumFunc
)
84 flags
= TNF_LIST
|TNF_OPEN
;
85 if (clHandlers
->validFunc
)
86 objValid
= clHandlers
->validFunc(obj
, &flags
);
93 /* This is either HW or HIDD subclass */
94 OOP_GetAttr(obj
, aHW_ClassName
, (IPTR
*)&name
);
96 OOP_GetAttr(obj
, aHidd_HardwareName
, (IPTR
*)&name
);
98 D(bug("[storage.sysexp] %s: name = '%s'\n", __func__
, name
));
100 objnum
= ++SysexpBase
->GlobalCount
;
102 tn
= (APTR
)DoMethod(SysexpBase
->sesb_Tree
, MUIM_NListtree_Insert
, name
, &msg
,
103 parent
, MUIV_NListtree_Insert_PrevNode_Tail
, flags
);
104 D(bug("[storage.sysexp] %s: Inserted TreeNode 0x%p <%s> UserData 0x%p\n", __func__
, tn
, tn
->tn_Name
, tn
->tn_User
));
106 /* If we have enumerator for this class, call it now */
107 if (clHandlers
&& clHandlers
->enumFunc
&& (flags
& TNF_LIST
))
108 clHandlers
->enumFunc(obj
, tn
);
110 if (objnum
== SysexpBase
->GlobalCount
)
112 tn
->tn_Flags
&= ~flags
;
115 return FALSE
; /* Continue enumeration */
121 AROS_UFH3S(BOOL
, storageunitenumFunc
,
122 AROS_UFHA(struct Hook
*, h
, A0
),
123 AROS_UFHA(OOP_Object
*, unit
, A2
),
124 AROS_UFHA(void *, parent
, A1
))
128 struct SysexpEnum_data
*edata
= (struct SysexpEnum_data
*)h
->h_Data
;
129 struct InsertObjectMsg msg
=
132 .winClass
= StorageUnitWindow_CLASS
135 struct SysexpBase
*SysexpBase
;
137 D(bug("[storage.sysexp] %s()\n", __func__
));
142 SysexpBase
= edata
->ed_sysexpbase
;
144 D(bug("[storage.sysexp] %s: StorageUnit @ %p\n", __func__
, unit
));
148 SysexpBase
->GlobalCount
++;
150 OOP_GetAttr(unit
, aHidd_StorageUnit_Model
, (IPTR
*)&name
);
151 DoMethod(SysexpBase
->sesb_Tree
, MUIM_NListtree_Insert
, name
, &msg
,
152 parent
, MUIV_NListtree_Insert_PrevNode_Tail
, 0);
154 return FALSE
; /* Continue enumeration */
160 static struct SysexpEnum_data privatehookdata
=
166 struct Hook storageenum_hook
=
168 .h_Entry
= storageenumFunc
,
169 .h_Data
= &privatehookdata
172 struct Hook storageunitenum_hook
=
174 .h_Entry
= storageunitenumFunc
,
175 .h_Data
= &privatehookdata
178 static void storageHWEnum(OOP_Object
*obj
, struct MUI_NListtree_TreeNode
*tn
)
180 D(bug("[storage.sysexp] HWEnum: enumerating..\n"));
181 D(bug("[storage.sysexp] HWEnum: storage class list @ 0x%p\n", storageenum_hook
.h_Data
));
182 HW_EnumDrivers(obj
, &storageenum_hook
, tn
);
185 static void storageControllerEnum(OOP_Object
*obj
, struct MUI_NListtree_TreeNode
*tn
)
187 D(bug("[storage.sysexp] ControllerEnum: enumerating..\n"));
188 D(bug("[storage.sysexp] ControllerEnum: storage class list @ 0x%p\n", storageenum_hook
.h_Data
));
189 HIDD_StorageController_EnumBuses(obj
, &storageenum_hook
, tn
);
192 void storageBusEnum(OOP_Object
*obj
, struct MUI_NListtree_TreeNode
*parent
)
194 D(bug("[storage.sysexp] BusEnum: enumerating..\n"));
195 D(bug("[storage.sysexp] BusEnum: storage class list @ 0x%p\n", storageenum_hook
.h_Data
));
196 HIDD_StorageBus_EnumUnits(obj
, &storageunitenum_hook
, parent
);
199 AROS_LH4(void, EnumBusUnits
,
200 AROS_LHA(OOP_Object
*, obj
, A0
),
201 AROS_LHA(struct MUI_NListtree_TreeNode
*, parent
, A1
),
202 AROS_LHA(APTR
, hookFunc
, A2
),
203 AROS_LHA(APTR
, hookData
, A3
),
204 struct SysexpStorageBase
*, StorageBase
, 15, Storage
)
208 struct Hook busunitenum_hook
;
209 D(bug("[storage.sysexp] %s: StorageBus @ %p\n", __func__
, obj
));
211 busunitenum_hook
.h_Entry
= hookFunc
;
212 busunitenum_hook
.h_Data
= hookData
;
214 HIDD_StorageBus_EnumUnits(obj
, &busunitenum_hook
, parent
);
220 Query a units device to see if it supports ATA device features, and if they are enebaled
222 Add objects to the passed in colgroup(2) if supported features are found.
224 AROS_LH3(void, QueryATAStorageFeatures
,
225 AROS_LHA(Object
*, obj
, A0
),
226 AROS_LHA(char *, devName
, A1
),
227 AROS_LHA(int, devUnit
, D0
),
228 struct SysexpStorageBase
*, StorageBase
, 16, Storage
)
233 struct MsgPort
* ioReplyPort
;
234 struct NSDeviceQueryResult nsdqr
;
237 ioReplyPort
= CreateMsgPort();
241 io
= CreateIORequest(ioReplyPort
, sizeof(struct IOStdReq
));
244 DeleteMsgPort(ioReplyPort
);
248 if (!OpenDevice(devName
, devUnit
,(struct IORequest
*)io
,0))
250 io
->io_Command
= NSCMD_DEVICEQUERY
;
251 io
->io_Length
= sizeof(nsdqr
);
252 io
->io_Data
= (APTR
)&nsdqr
;
254 error
= DoIO((struct IORequest
*)io
);
257 (io
->io_Actual
>= 16) &&
258 (io
->io_Actual
<= sizeof(nsdqr
)) &&
259 (nsdqr
.SizeAvailable
== io
->io_Actual
))
262 for(cmdcheck
= nsdqr
.SupportedCommands
;
268 // Does the device understand the SMART Cmd?
269 if(*cmdcheck
== HD_SMARTCMD
)
271 // Check if the unit Supports SMART
272 io
->io_Command
= HD_SMARTCMD
;
273 io
->io_Reserved1
= io
->io_Reserved2
= ATAFEATURE_TEST_AVAIL
;
274 io
->io_Length
= sizeof(queryres
);
275 io
->io_Data
= (APTR
)&queryres
;
276 error
= DoIO((struct IORequest
*)io
);
277 if ((!error
) && (io
->io_Actual
>= 4) && (queryres
== SMART_MAGIC_ID
))
279 IPTR smartSpacer
= (IPTR
)HVSpace
;
280 IPTR smartLabel
= (IPTR
)Label("SMART Supported");
281 if (DoMethod(obj
, MUIM_Group_InitChange
))
283 DoMethod(obj
, OM_ADDMEMBER
, smartSpacer
);
284 DoMethod(obj
, OM_ADDMEMBER
, smartLabel
);
285 DoMethod(obj
, MUIM_Group_ExitChange
);
290 // Does the device understand the TRIM Cmd?
291 if(*cmdcheck
== HD_TRIMCMD
)
293 // Check if the unit Supports TRIM
294 io
->io_Command
= HD_TRIMCMD
;
295 io
->io_Reserved1
= io
->io_Reserved2
= ATAFEATURE_TEST_AVAIL
;
296 io
->io_Length
= sizeof(queryres
);
297 io
->io_Data
= (APTR
)&queryres
;
298 error
= DoIO((struct IORequest
*)io
);
299 if ((!error
) && (io
->io_Actual
>= 4) && (queryres
== TRIM_MAGIC_ID
))
301 IPTR trimSpacer
= (IPTR
)HVSpace
;
302 IPTR trimLabel
= (IPTR
)Label("TRIM Supported");
303 if (DoMethod(obj
, MUIM_Group_InitChange
))
305 DoMethod(obj
, OM_ADDMEMBER
, trimSpacer
);
306 DoMethod(obj
, OM_ADDMEMBER
, trimLabel
);
307 DoMethod(obj
, MUIM_Group_ExitChange
);
313 CloseDevice((struct IORequest
*)io
);
315 DeleteIORequest((struct IORequest
*)io
);
316 DeleteMsgPort(ioReplyPort
);
321 AROS_LH5(BOOL
, RegisterStorageClassHandler
,
322 AROS_LHA(CONST_STRPTR
, classid
, A0
),
323 AROS_LHA(BYTE
, pri
, D0
),
324 AROS_LHA(struct MUI_CustomClass
*, customwinclass
, A1
),
325 AROS_LHA(CLASS_ENUMFUNC
, enumfunc
, A2
),
326 AROS_LHA(CLASS_VALIDFUNC
, validfunc
, A3
),
327 struct SysexpStorageBase
*, StorageBase
, 9, Storage
)
331 struct SysexpBase
*SysexpBase
= StorageBase
->sesb_SysexpBase
;
332 struct ClassHandlerNode
*newClass
;
335 if ((newClass
= FindClassHandler(classid
, &StorageBase
->sesb_HandlerList
)))
337 if (newClass
->enumFunc
!= GetBase("HWEnum.Func"))
340 D(bug("[storage.sysexp] %s: Updating '%s'..\n", __func__
, classid
));
346 D(bug("[storage.sysexp] %s: Registering '%s'..\n", __func__
, classid
));
347 newClass
= AllocMem(sizeof(struct ClassHandlerNode
), MEMF_CLEAR
);
352 newClass
->ch_Node
.ln_Name
= (char *)classid
;
353 newClass
->ch_Node
.ln_Pri
= pri
;
354 newClass
->muiClass
= customwinclass
;
355 newClass
->enumFunc
= enumfunc
;
356 newClass
->validFunc
= validfunc
;
360 RegisterClassHandler(classid
, pri
, NULL
, newClass
->enumFunc
, newClass
->validFunc
);
361 Enqueue(&StorageBase
->sesb_HandlerList
, &newClass
->ch_Node
);
372 AROS_LH5(BOOL
, RegisterStorageControllerHandler
,
373 AROS_LHA(CONST_STRPTR
, classid
, A0
),
374 AROS_LHA(BYTE
, pri
, D0
),
375 AROS_LHA(struct MUI_CustomClass
*, customwinclass
, A1
),
376 AROS_LHA(CLASS_ENUMFUNC
, enumfunc
, A2
),
377 AROS_LHA(CLASS_VALIDFUNC
, validfunc
, A3
),
378 struct SysexpStorageBase
*, StorageBase
, 10, Storage
)
382 CLASS_ENUMFUNC enumFunc
;
387 enumFunc
= storageControllerEnum
;
389 return RegisterStorageClassHandler(classid
, pri
, customwinclass
, enumFunc
, validfunc
);
394 AROS_LH5(BOOL
, RegisterStorageBusHandler
,
395 AROS_LHA(CONST_STRPTR
, classid
, A0
),
396 AROS_LHA(BYTE
, pri
, D0
),
397 AROS_LHA(struct MUI_CustomClass
*, customwinclass
, A1
),
398 AROS_LHA(CLASS_ENUMFUNC
, enumfunc
, A2
),
399 AROS_LHA(CLASS_VALIDFUNC
, validfunc
, A3
),
400 struct SysexpStorageBase
*, StorageBase
, 11, Storage
)
404 CLASS_ENUMFUNC enumFunc
;
409 enumFunc
= storageBusEnum
;
411 return RegisterStorageClassHandler(classid
, pri
, customwinclass
, enumFunc
, validfunc
);
416 void StorageStartup(struct SysexpBase
*SysexpBase
)
418 struct SysexpStorageBase
*StorageBase
;
420 D(bug("[storage.sysexp] %s(%p)\n", __func__
, SysexpBase
));
422 StorageBase
= GetBase("Storage.Module");
424 D(bug("[storage.sysexp] %s: StorageBase @ %p\n", __func__
, StorageBase
));
426 privatehookdata
.ed_sysexpbase
= SysexpBase
;
427 privatehookdata
.ed_list
= &StorageBase
->sesb_HandlerList
;
429 StorageBase
->sesb_DevicePageCLASS
= GetBase("DevicePage.Class");
430 StorageBusWindow_CLASS
->mcc_Class
->cl_UserData
= (IPTR
)StorageBase
;
432 RegisterBase(storagebuswindowclass_name
, StorageBusWindow_CLASS
);
433 RegisterBase(storageunitwindowclass_name
, StorageUnitWindow_CLASS
);
435 RegisterClassHandler(CLID_Hidd_Storage
, 90, NULL
, storageHWEnum
, NULL
);
436 RegisterStorageBusHandler(CLID_Hidd_StorageBus
, 0, StorageBusWindow_CLASS
, NULL
, NULL
);