revert commit 56204.
[AROS.git] / workbench / c / BindDrivers.c
blob4e6501490f82ae4ae50e8a65d9b953ad5623697d
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: BindDrivers CLI command
6 Lang: English
7 */
9 /******************************************************************************
12 NAME
14 BindDrivers
16 SYNOPSIS
18 DEVICES/S,DRIVERS/S,DIR/K/A
20 LOCATION
24 FUNCTION
26 For all device drivers with a .info file in SYS:Expansion, load
27 the device driver via Exec/InitResident() if its PRODUCT=
28 tooltype matches a device that is in the system, and not yet
29 configured.
31 INPUTS
33 DEVICES -- List all devices, and their bindings
35 DRIVERS -- List all drivers, and their supported products
37 DIR <directory> -- Directory to search, instead of SYS:Expansion/
39 RESULT
41 NOTES
44 EXAMPLE
46 C:BindDrivers
48 BUGS
50 SEE ALSO
52 INTERNALS
54 HISTORY
56 06.01.2012 Jason S. McMullan - Implemented
58 ******************************************************************************/
60 #define __NOLIBBASE__
62 #include <aros/debug.h>
64 #include <ctype.h>
65 #include <stdlib.h>
66 #include <stddef.h>
68 #include <exec/resident.h>
70 #include <proto/exec.h>
71 #include <proto/icon.h>
72 #include <proto/dos.h>
73 #include <proto/expansion.h>
75 #if DEBUG
76 #define SH_GLOBAL_SYSBASE 1 /* for kprintf() */
77 #endif
78 #include <aros/shcommands.h>
80 #define PROD_ANY ~0
82 struct BindDriverNode {
83 struct Node bd_Node;
84 UBYTE *bd_ProductString;
85 struct DiskObject *bd_Icon;
87 /* Must be at the end of this extendable structure.. */
88 ULONG bd_Products;
89 struct {
90 UWORD mfg;
91 UWORD prod;
92 } bd_Product[0];
95 static LONG BindDriverAdd(struct List *drivers, CONST_STRPTR name, APTR IconBase, APTR SysBase)
97 struct BindDriverNode *bd;
98 struct DiskObject *icon;
99 LONG err = 0;
100 UBYTE *product, *cp;
102 icon = GetDiskObject(name);
103 if (icon == NULL)
104 return err;
106 if ((product = FindToolType(icon->do_ToolTypes, "PRODUCT"))) {
107 int products = 1;
108 for (cp = product; *cp; cp++) {
109 if (!(isdigit(*cp) || *cp == '|' || *cp == '/'))
110 break;
111 if (*cp == '|')
112 products++;
114 if (*cp == 0) {
115 /* String had only valid characters */
116 if ((bd = AllocVec(sizeof(*bd) + sizeof(bd->bd_Product[0])*products + strlen(name) + 1, MEMF_ANY | MEMF_CLEAR))) {
117 int i;
119 bd->bd_ProductString = product;
120 bd->bd_Node.ln_Name = (APTR)&bd->bd_Product[products];
121 bd->bd_Icon = icon;
122 D(bug("%s: bd=%lx, icon=%lx\n", __func__, bd, icon));
123 strcpy(bd->bd_Node.ln_Name, name);
124 for (i = 0, cp = product; *cp; i++) {
125 unsigned long val;
126 char *next;
128 val = strtoul(cp, &next, 10);
129 if (next == (char *)cp)
130 break;
132 bd->bd_Product[i].mfg = val;
133 if (*next == '/') {
134 cp = next+1;
135 val = strtoul(cp, &next, 10);
136 if (next == (char *)cp)
137 break;
138 bd->bd_Product[i].prod = val;
139 } else {
140 bd->bd_Product[i].prod = PROD_ANY;
143 if (*next && *next != '|')
144 break;
146 bd->bd_Products++;
148 if (*next)
149 cp = next+1;
150 else
151 break;
154 if (bd->bd_Products) {
155 AddTail(drivers, &bd->bd_Node);
156 err = 0;
157 } else {
158 FreeDiskObject(bd->bd_Icon);
159 FreeVec(bd);
160 err = RETURN_FAIL;
164 } else {
165 D(bug("%s: \tNo PRODUCT= tooltype\n", __func__));
168 return err;
171 static struct Resident *SearchResident(BPTR seglist)
173 const int ressize = offsetof(struct Resident, rt_Init) + sizeof(APTR);
175 D(bug("%lx: Search for resident...\n", BADDR(seglist)));
176 while (seglist) {
177 APTR addr = (APTR)((IPTR)BADDR(seglist) - sizeof(ULONG));
178 ULONG size = *(ULONG *)addr;
180 for (addr += sizeof(BPTR) + sizeof(ULONG),
181 size -= sizeof(BPTR) + sizeof(ULONG);
182 size >= ressize;
183 size -= 2, addr += 2) {
184 struct Resident *res = (struct Resident *)addr;
186 if (res->rt_MatchWord == RTC_MATCHWORD &&
187 res->rt_MatchTag == res) {
188 D(bug("%lx: Resident found at %lx\n", BADDR(seglist), res));
189 return res;
193 seglist = *(BPTR *)BADDR(seglist);
196 D(bug("%lx: No resident\n", BADDR(seglist)));
197 return NULL;
200 static LONG BindDriver(STRPTR name, UWORD mfg, UBYTE prod, UBYTE *prodstr, UBYTE **tooltypes, APTR ExpansionBase, APTR DOSBase, APTR SysBase)
202 BPTR seglist;
203 LONG err = RETURN_OK;
205 struct CurrentBinding cb;
206 cb.cb_ConfigDev = NULL;
207 cb.cb_FileName = name;
208 cb.cb_ProductString = prodstr;
209 cb.cb_ToolTypes = tooltypes;
211 while ((cb.cb_ConfigDev = FindConfigDev(cb.cb_ConfigDev, mfg, prod))) {
213 if (cb.cb_ConfigDev->cd_Flags & CDF_SHUTUP)
214 continue;
216 if (!(cb.cb_ConfigDev->cd_Flags & CDF_CONFIGME))
217 continue;
219 if ((seglist = LoadSeg(name)) != BNULL) {
220 struct Resident *res;
222 if ((res = SearchResident(seglist))) {
223 D(bug("Binding=%lx, name=%s, res=%lx\n", &cb, name, res));
224 ObtainConfigBinding();
225 SetCurrentBinding(&cb, sizeof(cb));
226 D(bug("Calling InitResident via %lx\n", (IPTR)SysBase - 6 * 17));
227 if (InitResident(res, seglist) == NULL) {
228 D(bug("\tfailed\n"));
229 UnLoadSeg(seglist);
230 } else {
231 D(bug("\tbound\n"));
233 ReleaseConfigBinding();
234 } else {
235 /* No resident? Then never loadable */
236 err = RETURN_FAIL;
237 D(bug("No resident for %s\n", name));
238 UnLoadSeg(seglist);
240 } else {
241 /* Can't load the file? Then don't try again */
242 err = RETURN_FAIL;
245 if (err != RETURN_OK) {
246 break;
250 return err;
254 AROS_SH3(BindDrivers, 41.1,
255 AROS_SHA(BOOL, ,DRIVERS,/S, FALSE),
256 AROS_SHA(BOOL, ,DEVICES,/S, FALSE),
257 AROS_SHA(STRPTR, ,DIR,/K, "SYS:Expansion"))
260 AROS_SHCOMMAND_INIT
262 struct ExAllControl *eac;
263 BPTR lock, olddir;
264 struct List drivers;
265 struct BindDriverNode *node, *tmp;
266 struct Library *ExpansionBase;
267 struct Library *IconBase;
268 LONG error;
270 if (!(ExpansionBase = OpenLibrary("expansion.library", 33)))
271 return RETURN_FAIL;
273 if (!(IconBase = OpenLibrary("icon.library", 36))) {
274 CloseLibrary(ExpansionBase);
275 return RETURN_FAIL;
278 /* Just dump what devices we have */
279 if (SHArg(DEVICES)) {
280 struct ConfigDev *cdev = NULL;
282 ObtainConfigBinding();
283 while ((cdev = FindConfigDev(cdev, -1, -1))) {
284 struct Node *node = cdev->cd_Driver;
285 Printf("%5ld/%-3ld %08lx-%08lx %s\n",
286 cdev->cd_Rom.er_Manufacturer,
287 cdev->cd_Rom.er_Product,
288 (ULONG)(IPTR)cdev->cd_BoardAddr,
289 (ULONG)(IPTR)cdev->cd_BoardAddr+cdev->cd_BoardSize-1,
290 (cdev->cd_Flags & CDF_CONFIGME) ?
291 "(unbound)" : (const char *)node->ln_Name);
293 ReleaseConfigBinding();
294 CloseLibrary(IconBase);
295 CloseLibrary(ExpansionBase);
296 return RETURN_OK;
299 NEWLIST(&drivers);
301 lock = Lock(SHArg(DIR), SHARED_LOCK);
302 if (lock == BNULL) {
303 error = IoErr();
304 Printf("BindDrivers: Can't open %s\n", SHArg(DIR));
305 CloseLibrary(IconBase);
306 CloseLibrary(ExpansionBase);
307 SetIoErr(error);
308 return RETURN_FAIL;
311 olddir = CurrentDir(lock);
313 if ((eac = AllocDosObject(DOS_EXALLCONTROL,NULL))) {
314 BOOL more;
315 UBYTE eadarr[256];
317 do {
318 more = ExAll(lock, (struct ExAllData *)&eadarr[0], sizeof(eadarr), ED_NAME, eac);
319 if (!more && (IoErr() != ERROR_NO_MORE_ENTRIES))
320 break;
322 if (eac->eac_Entries) {
323 struct ExAllData *ead;
325 for (ead = (APTR)&eadarr[0]; ead; ead=ead->ed_Next)
326 BindDriverAdd(&drivers, ead->ed_Name, IconBase, SysBase);
328 } while (more);
331 ForeachNodeSafe(&drivers, node, tmp) {
332 int i;
333 for (i = 0; i < node->bd_Products; i++) {
334 /* If SHArg(DRIVERS) is true, just list the drivers
336 if (SHArg(DRIVERS)) {
337 Printf("%5ld/%-3ld %s\n", (ULONG)node->bd_Product[i].mfg, (ULONG)node->bd_Product[i].prod, node->bd_Node.ln_Name);
338 } else {
339 LONG err;
340 err = BindDriver(node->bd_Node.ln_Name, node->bd_Product[i].mfg, node->bd_Product[i].prod, node->bd_ProductString, node->bd_Icon->do_ToolTypes, ExpansionBase, DOSBase, SysBase);
341 if (err != RETURN_OK)
342 break;
345 Remove(&node->bd_Node);
346 FreeDiskObject(node->bd_Icon);
347 FreeVec(node);
350 CurrentDir(olddir);
351 UnLock(lock);
353 CloseLibrary(IconBase);
354 CloseLibrary(ExpansionBase);
355 return RETURN_OK;
357 AROS_SHCOMMAND_EXIT