/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos720 src/bos/usr/samples/cfg/cfgxxx.c 1.2 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 1990,1991 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ static char sccsid[] = "@(#)70 1.2 src/bos/usr/samples/cfg/cfgxxx.c, cfgsamp, bos720 6/7/91 11:51:37"; /* * COMPONENT_NAME: (BOSSAMP) IBM BOS Sample Program * * FUNCTIONS: NONE * * ORIGINS: 27 * * (C) COPYRIGHT International Business Machines Corp. 1990 * All Rights Reserved * Licensed Materials - Property of IBM * * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* NOTICE TO USERS OF THE SOURCE CODE EXAMPLES THE SOURCE CODE EXAMPLES PROVIDED BY IBM ARE ONLY INTENDED TO ASSIST IN THE DEVELOPMENT OF A WORKING SOFTWARE PROGRAM. THE SOURCE CODE EXAMPLES DO NOT FUNCTION AS WRITTEN: ADDITIONAL CODE IS REQUIRED. IN ADDITION, THE SOURCE CODE EXAMPLES MAY NOT COMPILE AND/OR BIND SUCCESSFULLY AS WRITTEN. INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THE SOURCE CODE EXAMPLES, BOTH INDIVIDUALLY AND AS ONE OR MORE GROUPS, "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOURCE CODE EXAMPLES, BOTH INDIVIDUALLY AND AS ONE OR MORE GROUPS, IS WITH YOU. SHOULD ANY PART OF THE SOURCE CODE EXAMPLES PROVE DEFECTIVE, YOU (AND NOT IBM OR AN AUTHORIZED RISC System/6000* WORKSTATION DEALER) ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. IBM does not warrant that the contents of the source code examples, whether individually or as one or more groups, will meet your requirements or that the source code examples are error-free. IBM may make improvements and/or changes in the source code examples at any time. Changes may be made periodically to the information in the source code examples; these changes may be reported, for the sample device drivers included herein, in new editions of the examples. References in the source code examples to IBM products, programs, or services do not imply that IBM intends to make these available in all countries in which IBM operates. Any reference to an IBM licensed program in the source code examples is not intended to state or imply that only IBM's licensed program may be used. Any functionally equivalent program may be used. * RISC System/6000 is a trademark of International Business Machines Corporation. */ /* * FUNCTION: Configure method for mca adapter of type xxx * * interface: * cfgxxx -l [-<1|2>] */ /* header files needed for compilation */ #include #include #include #include #include #include /* main function code */ main(argc, argv, envp) int argc; char *argv[]; char *envp[]; { extern int optind; /* for getopt function */ extern char *optarg; /* for getopt function */ char *logical_name; /* logical name to configure */ char *phase1, *phase2; /* ipl phase flags */ char sstring[256]; /* search criteria string */ char conflist[1024]; /* busresolve() configured devices */ char not_resolved[1024]; /* busresolve() not resolved devices */ struct Class *cusdev; /* customized devices class ptr */ struct Class *predev; /* predefined devices class ptr */ struct CuDv cusobj; /* customized device object storage */ struct PdDv preobj; /* predefined device object storage */ struct CuDv parobj; /* customized device object storage */ struct CuDv dmyobj; /* customized device object storage */ ushort devid; /* Device id - used at run-time */ int ipl_phase; /* ipl phase: 0=run,1=phase1,2=phase2 */ int slot; /* slot of adapters */ int rc; /* return codes go here */ int errflg,c; /* used in parsing parameters */ /***** */ /***** Parse Parameters */ /***** */ ipl_phase = RUNTIME_CFG; errflg = 0; logical_name = NULL; while ((c = getopt(argc,argv,"l:12")) != EOF) { switch (c) { case 'l': if (logical_name != NULL) errflg++; logical_name = optarg; break; case '1': if (ipl_phase != RUNTIME_CFG) errflg++; ipl_phase = PHASE1; break; case '2': if (ipl_phase != RUNTIME_CFG) errflg++; ipl_phase = PHASE2; break; default: errflg++; } } if (errflg) /* error parsing parameters */ exit(E_ARGS); /***** */ /***** Validate Parameters */ /***** */ /* logical name must be specified */ if (logical_name == NULL) exit(E_LNAME); /* start up odm */ if (odm_initialize() == -1) /* initialization failed */ exit(E_ODMINIT); /* lock the database */ if (odm_lock("/etc/objrepos/config_lock",0) == -1) err_exit(E_ODMLOCK); /* open customized devices object class */ if ((int)(cusdev = odm_open_class(CuDv_CLASS)) == -1) err_exit(E_ODMOPEN); /* search for customized object with this logical name */ sprintf(sstring, "name = '%s'", logical_name); rc = (int)odm_get_first(cusdev,sstring,&cusobj); if (rc==0) { /* No CuDv object with this name */ err_exit(E_NOCuDv); } else if (rc==-1) { /* ODM failure */ err_exit(E_ODMGET); } /* open predefined devices object class */ if ((int)(predev = odm_open_class(PdDv_CLASS)) == -1) err_exit(E_ODMOPEN); /* get predefined device object for this logical name */ sprintf(sstring, "uniquetype = '%s'", cusobj.PdDvLn_Lvalue); rc = (int)odm_get_first(predev, sstring, &preobj); if (rc==0) { /* No PdDv object for this device */ err_exit(E_NOPdDv); } else if (rc==-1) { /* ODM failure */ err_exit(E_ODMGET); } /* close predefined device object class */ if (odm_close_class(predev) == -1) err_exit(E_ODMCLOSE); /**************************************************************** If adapter xxx is being configured during an ipl phase, then display its LED value on the system LEDs. ****************************************************************/ if (ipl_phase != RUNTIME_CFG) setleds(preobj.led); /****************************************************************** Check to see if the adapter is already configured (AVAILABLE). We actually go about the business of configuring the adapter only if it is not configured yet. Configuring the adapter refers to the process of checking parent status, resolving bus resources, and obtaining VPD. ******************************************************************/ if (cusobj.status == DEFINED) { /* The adapter is not configured */ /* get the device's parent object */ sprintf(sstring, "name = '%s'", cusobj.parent); rc = (int)odm_get_first(cusdev,sstring,&parobj); if (rc==0) { /* Parent device not in CuDv */ err_exit(E_NOCuDvPARENT); } else if (rc==-1) { /* ODM failure */ err_exit(E_ODMGET); } /* Parent MUST be available to continue */ if (parobj.status != AVAILABLE) /* parent is not AVAILABLE */ err_exit(E_PARENTSTATE); /* make sure that no other devices are configured */ /* at this location */ sprintf(sstring, "parent = '%s' AND connwhere = '%s' AND status = %d", cusobj.parent, cusobj.connwhere, AVAILABLE); rc = (int)odm_get_first(cusdev,sstring,&dmyobj); if (rc == -1) { /* odm failure */ err_exit(E_ODMGET); } else if (rc) { /* Error: device config'd at this location */ err_exit(E_AVAILCONNECT); } /*************************************************** If the xxx adapter is being configured at RUN TIME, then we must resolve any bus attribute conflicts before configuring. If being configured at boot time, the bus configurator will have already resolved conflicts. ***************************************************/ if (ipl_phase == RUNTIME_CFG) { /* Make sure card is in specified slot */ slot = atoi(cusobj.connwhere); devid = (ushort) strtol(preobj.devid,(char **) NULL,0); sprintf (sstring,"/dev/%s",cusobj.parent); rc = chkslot(sstring,slot,devid); if (rc != 0) err_exit(rc); /* Invoke Bus Resolve */ rc = busresolve(logical_name,(int)0,conflist, not_resolved, cusobj.parent); if (rc != 0) err_exit(rc); } /* get VPD for this device */ rc = query_vpd(logical_name); if (rc) /* failed to get VPD */ err_exit(rc); /* update customized device object with a change operation */ cusobj.status = AVAILABLE; if (odm_change_obj(cusdev, &cusobj) == -1) /* ODM failure */ return(E_ODMUPDATE); } /* end if (adapter is not AVAILABLE) then ... */ /* call routine to detect/manage child devices */ if (define_children(logical_name, ipl_phase) != 0) { /* error defining children */ err_exit(E_FINDCHILD); } /* close customized device object class */ if (odm_close_class(cusdev) == -1) err_exit(E_ODMCLOSE); odm_terminate(); exit(0); } /* * NAME: err_exit * * FUNCTION: Closes any open object classes and terminates ODM. Used to * back out on an error. * * void * err_exit( exitcode ) * exitcode = The error exit code. * * RETURNS: None */ err_exit(exitcode) char exitcode; { /* Close any open object class */ odm_close_class(CuDv_CLASS); odm_close_class(PdDv_CLASS); odm_close_class(CuAt_CLASS); /* Terminate the ODM */ odm_terminate(); exit(exitcode); } /* * NAME: query_vpd * * FUNCTION: Obtaining VPD data from the adapter * * RETURNS: * 0 - success */ int query_vpd(logical_name) char *logical_name; /* logical name of adapter */ { char vpd[VPDSIZE]; /* vpd data */ struct Class *cusvpd; /* customized vpd class ptr */ struct CuVPD vpdobj; /* customized vpd object */ char sstring[256]; /* search criteria string */ int rc; /* odm return codes */ /* This routine obtains the VPD from the adapter card and returns it in the vpd string. The actual method of obtaining the VPD will depend on the hardware interface. */ /* code to be added here to obtain VPD */ /* open customized vpd object class */ if ((int)(cusvpd = odm_open_class(CuVPD_CLASS)) == -1) return(E_ODMOPEN); /* search for customized vpd object with this logical name */ sprintf(sstring, "name = '%s' and vpd_type = '%d'", logical_name,HW_VPD); rc = (int)odm_get_first(cusvpd,sstring,&vpdobj); if (rc==-1) { /* ODM failure */ return(E_ODMGET); } if (rc==0) { /* need to add vpd object */ strcpy(vpdobj.name,logical_name); vpdobj.vpd_type = HW_VPD; strcpy(vpdobj.vpd,vpd); if (odm_add_obj(cusvpd,&vpdobj) == -1) { return(E_ODMADD); } } else { /* see if vpd object needs to be updated */ if (strcmp(vpdobj.vpd,vpd)) { strcpy(vpdobj.vpd,vpd); if (odm_change_obj(cusvpd,&vpdobj) == -1) { return(E_ODMUPDATE); } } } /* close customized vpd object class */ if (odm_close_class(CuVPD_CLASS) == -1) return(E_ODMCLOSE); return(0); } /* * NAME: define_children * * FUNCTION: Routine for detecting and managing children of the * adapter. It defines each new device not already represented in * the Customized database. The names of all the defined children * in the Customized database are then written to stdout so they * can be configured. * * RETURNS: * 0 - success (E_OK) */ int define_children(logical_name,phase) char *logical_name; int phase; { /* code to be added here to detect child devices */ return(E_OK); } #include /* * NAME: chkslot * * FUNCTION: * Return zero value if cardid is in desired slot. * * INPUTS: * bus - The name of the bus device, for example, bus0. * slot - The slot number from the parent connection descriptor. * It should be a value of 1 through 8, with 0 being used * for the Standard I/O Planar. * cardid - The card Id composed as ((POS0<<8) || POS1). * * RETURNS: Returns 0 on success, >0 Error code. */ int chkslot(bus, slot, cardid) char *bus; int slot; ushort cardid; { MACH_DD_IO mddRecord; uchar pos[2]; int fd; int i; pos[0] = 0xff; pos[1] = 0xff; /* Decrement slot number found in database */ slot == (slot--) & 0x0F; if (0 > (fd = open(bus, O_RDWR))) return E_NODETECT; mddRecord.md_size = 2; mddRecord.md_incr = MV_BYTE; mddRecord.md_data = pos; mddRecord.md_addr = POSREG(0, slot); if (0 > ioctl(fd, MIOCCGET, &mddRecord)) return E_NODETECT; close(fd); if (cardid == ((pos[0] << 8) | pos[1])) return(0); else return E_NODETECT; }