2 * $Id: cfggsc.c,v 1.1 2001/04/15 11:12:37 ant Exp $
3 * Copyright (c) 1997 by Matthew Jacob
5 * This software is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; version 2.
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this software; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 * The author may be reached via electronic communications at
22 * or, via United States Postal Address
26 * San Francisco, CA, 94131
32 #include <sys/types.h>
33 #include <sys/errno.h>
34 #include <sys/ioctl.h>
35 #include <sys/devinfo.h>
36 #include <sys/device.h>
37 #include <sys/cfgodm.h>
39 #include <sys/cfgdb.h>
41 #include <sys/sysconfig.h>
42 #include <sys/errno.h>
43 #include <sys/device.h>
48 extern mid_t loadext(char *, int, int);
51 static struct gsc_ddsinfo ddsinfo;
53 int main(int a, char **v);
54 static void check_add_sockets(dev_t, int, char *, char *);
55 static int has_driver_get_vpd(char *, int, char *);
57 #define MKNOD_MODE S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
59 #define vprintf if (verbose) printf
63 err_exit(char exitcode)
65 odm_close_class(CuDv_CLASS);
66 odm_close_class(PdDv_CLASS);
75 char sstring[256], bufname[256], conns[NAMESIZE], *ptr, *lname;
76 struct Class *cprp, *cusdev, *predev;
77 struct CuDvDr dpr, *dprp;
78 struct CuDv parobj, cusobj, hdobj, *xprp;
81 int rc, c, errflg, ipl_phase, unit, munit, howmany, lun, domake;
90 ipl_phase = RUNTIME_CFG;
91 (void) memset((void *) &ddsinfo, 0, sizeof ddsinfo);
93 while ((c = getopt(a, v, "l:12v")) != EOF) {
104 if (ipl_phase != RUNTIME_CFG)
109 if (ipl_phase != RUNTIME_CFG)
122 if (odm_initialize() == -1) {
126 /* lock the database */
127 if (odm_lock("/etc/objrepos/config_lock",0) == -1)
130 /* open customized devices object class */
131 if ((int)(cusdev = odm_open_class(CuDv_CLASS)) == -1)
134 /* search for customized object with this logical name */
135 sprintf(sstring, "name = '%s'", lname);
136 rc = (int) odm_get_first(cusdev, sstring, &cusobj);
138 /* No CuDv object with this name */
140 } else if (rc == -1) {
145 /* open predefined devices object class */
146 if ((int)(predev = odm_open_class(PdDv_CLASS)) == -1)
149 /* get predefined device object for this logical name */
150 sprintf(sstring, "uniquetype = '%s'", cusobj.PdDvLn_Lvalue);
151 rc = (int)odm_get_first(predev, sstring, &preobj);
153 /* No PdDv object for this device */
155 } else if (rc == -1) {
159 /* close predefined device object class */
160 if (odm_close_class(predev) == -1)
161 err_exit(E_ODMCLOSE);
163 if (ipl_phase != RUNTIME_CFG)
167 * Now, if the device is already configured, we're
170 if (cusobj.status == AVAILABLE) {
171 /* close customized device object class */
172 if (odm_close_class(cusdev) == -1)
173 err_exit(E_ODMCLOSE);
177 if (cusobj.status != DEFINED) {
178 vprintf("bad state: %d\n", cusobj.status);
179 err_exit(E_DEVSTATE);
182 /* get the device's parent object */
183 sprintf(sstring, "name = '%s'", cusobj.parent);
184 rc = (int) odm_get_first(cusdev, sstring, &parobj);
186 /* Parent device not in CuDv */
187 err_exit(E_NOCuDvPARENT);
188 } else if (rc == -1) {
193 /* Parent MUST be available to continue */
194 if (parobj.status != AVAILABLE)
195 err_exit(E_PARENTSTATE);
198 /* make sure that no other devices are configured */
199 /* at this location */
200 sprintf(sstring, "parent = '%s' AND location='%s' AND status=%d",
201 cusobj.parent, cusobj.location, AVAILABLE);
202 rc = (int) odm_get_first(cusdev, sstring, &cusobj);
207 /* Error: device config'd at this location */
208 err_exit(E_AVAILCONNECT);
211 memcpy(conns, cusobj.location, NAMESIZE);
212 vprintf("now fool with luns: location is %s\n", conns);
214 while (*ptr && ptr < &conns[NAMESIZE])
217 if (ptr < &conns[1]) {
221 vprintf("I see lun %d\n", lun);
222 if (lun < 0 || lun >= 8)
223 err_exit(E_INVCONNECT);
228 if (ptr[-1] == ',') {
233 while (ptr > conns && *ptr != '-')
237 ddsinfo.target = strtol(ptr, (char **) NULL, 0);
238 vprintf("I see tgt %d ptr = %d\n", ddsinfo.target, ptr - conns);
241 * Generate dev_t for adapter
243 cprp = odm_open_class(CuDvDr_CLASS) ;
244 sprintf(sstring, "value3 = %s", cusobj.parent);
245 rc = (int) odm_get_obj(cprp, sstring, &dpr, TRUE);
247 err_exit(E_NOCuDvPARENT);
248 } else if (rc == -1) {
251 ddsinfo.busid = (dev_t) makedev(atoi(dpr.value1), atoi(dpr.value2));
252 vprintf("I see %d.%d for connecting adapter\n",
253 major(ddsinfo.busid), minor(ddsinfo.busid));
256 * Get unit number out of logical name
260 ptr += strlen(preobj.prefix);
262 vprintf("I see %d as unit\n", unit);
265 * Okay, now that we have the pertinent information that we'll
266 * need (adapter dev_t, device type, target, lbits, shareable,
267 * unit number), we can look into actually loading/configuring the
270 (void) sprintf(bufname, "/dev/%s", lname);
273 * Get or generate major number..
275 if ((major = (long) genmajor(preobj.DvDr)) == -1) {
279 vprintf("major is %d\n", major);
282 * Let's see if this is the first time through. If it's
283 * the first time through, getminor will return NULL
284 * or won't have any minors in the list.
286 mlist = getminor(major, &howmany, preobj.DvDr);
287 vprintf("getminor: %x and howmany %d for %s\n", mlist, howmany,
291 if (mlist != NULL && howmany != 0) {
293 * We have a list of minors already.
294 * See if we already have the minor
297 for (c = 0; c < howmany; c++) {
298 if (mlist[c] == unit) {
299 vprintf("unit %d already has minor\n", unit);
307 (void) unlink(bufname);
309 * Now create the minor number that will match the unit number.
310 * We really don't care whether genminor succeeds, since
311 * we've alreay unlinked the device node.
313 mlist = genminor(preobj.DvDr, major, unit, 1, 1, 1);
314 if (mlist == (long *) NULL) {
317 vprintf("making %s as %d.%d with minor returned as %d\n",
318 bufname, major, unit, *mlist);
319 if (mknod(bufname, MKNOD_MODE, makedev(major, unit))) {
320 err_exit(E_MKSPECIAL);
323 (void) mknod(bufname, MKNOD_MODE, makedev(major, unit));
327 * Load the driver....
329 kmid = loadext(preobj.DvDr, TRUE, FALSE);
335 * And configure the driver...
338 dd.devno = makedev(major, unit);
340 dd.ddsptr = (caddr_t) &ddsinfo;
341 dd.ddslen = sizeof (ddsinfo);
343 if (sysconfig(SYS_CFGDD, &dd, sizeof (dd)) == CONF_FAIL) {
348 (void) loadext(preobj.DvDr, FALSE, FALSE);
351 err_exit(E_WRONGDEVICE);
355 err_exit(E_AVAILCONNECT);
366 /* now mark the device as available */
367 cusobj.status = AVAILABLE;
368 if (odm_change_obj(CuDv_CLASS, &cusobj) == -1) {
370 * Unconfigure driver (for this instance)...
373 dd.ddsptr = (caddr_t) NULL;
374 dd.ddslen = (int ) 0;
376 (void) sysconfig(SYS_CFGDD, &dd, sizeof (dd));
380 (void) loadext(preobj.DvDr, FALSE, FALSE);
381 err_exit (E_ODMUPDATE);
385 (void) odm_terminate();
390 * Overrides for Emacs so that we follow Linus's tabbing style.
391 * Emacs will notice this stuff at the end of the file and automatically
392 * adjust the settings for this buffer only. This must remain at the end
394 * ---------------------------------------------------------------------------
397 * c-brace-imaginary-offset: 0
399 * c-argdecl-indent: 4
401 * c-continued-statement-offset: 4
402 * c-continued-brace-offset: 0