config -- inform MDI drivers of hardware device instances to be managed


See the config(D2) manual page for syntax, context, version applicability, and general usage information about this entry point routine.


The config( ) entry point routine for MDI hotplug-aware drivers must do the following:

CFG_VERIFY for ISA devices

DDI 8 drivers for ISA devices must include the CFG_VERIFY subroutine to do the following:

  1. Retrieve CM_IOADDR from the resource manager. Do not attempt to retrieve resource manager parameters other than CM_IOADDR from your verify( ) routine:
           struct cm_args      cm_args ;
           cm_range_t      range ;

    cm_args.cm_key = key ; cm_args.cm_n = 0 ; cm_args.cm_param = CM_IOADDR ; cm_args.cm_val = &range ; cm_args.cm_vallen = sizeof(struct cm_addr_rng) ;

    cm_begin_trans(cm_args.cm_key, RM_READ); if (cm_getval(&cm_args) != 0) { cm_end_trans(cm_args.cm_key); cmn_err(CE_NOTE,"e3Dverify: IOADDR not found in resmgr\n"); return(ENODEV); } cm_end_trans(cm_args.cm_key);

  2. Determine if your board's hardware is at this I/O address. Return EINVAL or ENODEV if no board is found.
           if ( e3Dpresent(&e3Dtmpdevice, 1) == TRUE ) {
               /* we don't need the memory mapping any more */
               if (e3Dtmpdevice.ex_rambase) {
                   e3Dtmpdevice.ex_rambase = (caddr_t) 0;
           if (e3Dtmpdevice.ex_rambase) {
               /* e3Dpresent returned false.   free devmem_mapin'd memory */
               devmem_mapout(e3Dtmpdevice.ex_rambase, e3Dtmpdevice.ex_memsize);
               e3Dtmpdevice.ex_rambase = (caddr_t) 0;


  3. If you do find your board at this address, retrieve configuration parameters from the NVRAM/EEPROM. Also, if any bcfg(DSP/4dsp) file used by your driver uses CUSTOM parameters, look for them in the resource manager as well. Because the driver cannot know which bcfg file the user is manipulating, the driver should not fail if the parameter is not found in the resource manager, but instead should call cmn_err( ) with the CE_CONT level to tell the user the default setting that the driver is assuming.
       	if (getset == MDI_ISAVERIFY_TRADITIONAL) {
       		 * Probably called from the dcu.
       		 * We have already confirmed that the board is
       		 * present at the io address given by CM_IOADDR
       		 * in the resmgr in e3Dpresent so we know there
       		 * is a board at this address.  Return success
       		 * as this is all the traditional verify
       		 * routine does.
       	} else if (getset == MDI_ISAVERIFY_GET) {
       		 * Retrieve parameters from firmware, set
       		 * custom parameters in resmgr, call
       		 * mdi_AT_verify again with updated information,
       		 * and return 0.
       		 * We've already read EEPROM information by
       		 * calling e3Dpresent

    cm_args.cm_key = key ; cm_args.cm_n = 0 ; cm_args.cm_val = &answer ; cm_args.cm_vallen = strlen(answer)+1 ; /* * ex_bnc is 0 for AUI or HROM_BNC(0x80) for * other. The bcfg file says '0' is * BNC/TP and '1' is AUI. */

    /* cm_param must be less than 11 chars */ cm_args.cm_param = "CABLETYPE"; answer[0] = (e3Dtmpdevice.ex_bnc == 0 ? '1' : '0');

    cm_begin_trans(cm_args.cm_key, RM_RDWR); (void) cm_delval(&cm_args); if (cm_addval(&cm_args)) { cm_abort_trans(cm_args.cm_key); cmn_err(CE_WARN,"e3Dverify: cm_addval for CABLETYPE at key %d failed", key); return(ENODEV); } cm_end_trans(cm_args.cm_key); ... sioa = e3Dtmpdevice.ex_ioaddr; eioa = e3Dtmpdevice.ex_ioaddr + 0xf; /* * if your board/bcfg uses 2 for the irq you * should translate it to 9 here */ vector = e3Dtmpdevice.ex_int; scma = (ulong_t) e3Dtmpdevice.ex_base; ecma = (ulong_t) e3Dtmpdevice.ex_base + e3Dtmpdevice.ex_memsize - 1;

    /* * We have filled in the custom parameters and * other ISA parameters. Tell ndcfg about them. * We set DMA to null as we don't need it. * Only call mdi_AT_verify after all custom * parameters have been added to the resmgr. */ getset = MDI_ISAVERIFY_GET_REPLY; err = mdi_AT_verify(key, &getset, &sioa, &eioa, &vector, &scma, &ecma, NULL);

    if (err != 0) { cmn_err(CE_CONT,"e3Dverify: mdi_AT_verify returned %d",err); return(ENODEV); } return(0);

  4. Program the NVRAM/EEPROM with the values indicated by vector, sioa, eioa, scma, ecma, and dmac. Note that the range sioa-eioa may be different than the range given by CM_IOADDR in the resource manager. If it is, the user should change the existing I/O address that the board is using to the new address returned from mdi_AT_verify(D3mdi). You can call the cmn_err(D3) function to notify the user of are any problems.
       	} else if (getset == MDI_ISAVERIFY_SET) {
       		extern void e3Dconfigure(e3Ddev_t *);

    /* * set the eeprom/nvram to parameters indicated by * those returned from mdi_AT_verify. If the parameter * is -1 then it shouldn't change from its current * value. Note we must read custom parameters from * the resmgr by calling cm_getval explicitly */

    if (sioa != -1) { e3Dtmpdevice.ex_ioaddr = sioa; }

    /* irq 2 and 9 are the same on isa machines */ if (vector != -1) { e3Dtmpdevice.ex_int = vector; } if (scma != -1 && ecma != -1) { e3Dtmpdevice.ex_base = (caddr_t) scma; e3Dtmpdevice.ex_memsize = ecma+1-scma; } /* now get custom parameters */ cm_args.cm_key = key; cm_args.cm_n = 0; cm_args.cm_val = &answer; cm_args.cm_vallen = sizeof(answer); cm_args.cm_param = "CABLETYPE"; /* less than 11 chars */

    /* * If the custom parameter shouldn't change, it may not * be set in the resmgr. Don't error, continue on to * next parameter. */ ... /* * There is no way to change the ROM base address * or ROM size. We'll set its size to 0 so as not * to interfere with anything else on the system. */ e3Dtmpdevice.ex_romsize = 0;

    /* * We must call cm_AT_putconf again to indicate the new * settings at the key. if we are modifying an existing * board this is not an issue as the specific parameter * will already have been changed by ndcfg but if we * are adding a new board this is necessary. Why? * The order is as follows: * 1) netcfg issues the 'idinstall' command to ndcfg * 2) ndcfg creates new key(we're ISA), populates with * all information necessary * 3) ndcfg idinstalls the driver * 4) ndcfg loads the driver. This calls our init * routine which calls cm_AT_putconf giving it * the firmware's current arguments, not necessarily * what the user wanted to use. * 5) ndcfg calls our verify routine with * MDI_ISAVERIFY_SET telling us to reprogram * firmware. Ok, we will do that, but the resmgr * still has old values, which are wrong. * Of course, this will be taken care of at next boot * since we will call cm_AT_putconf again, but why * prolong the agony? * 6) We reprogram firmware and call cm_AT_putconf * again here, updating the resmgr * 7) ndcfg calls idconfupdate after we return from the * verify routine (in both idinstall and idmodify * cases) If this driver never called cm_AT_putconf * in the init routine then we wouldn't have to call * it again here. Also, since many of these values * may not be set from mdi_AT_verify, we must use * the later of: * a) current firmware * b) modified setting from mdi_AT_verify * in our call to cm_AT_putconf below. * Finally, the key passed to our verify routine is not * the key we need to modify with cm_AT_putconf. * The key to pass to cm_AT_putconf is stored in the * parameter "PUTCONFKEY". This parameter only exists * for MDI_ISAVERIFY_SET mode.

    cm_args.cm_key = key; cm_args.cm_n = 0; cm_args.cm_param = "PUTCONFKEY"; cm_args.cm_val = &putconfkey; cm_args.cm_vallen = sizeof(rm_key_t);

    cm_begin_trans(cm_args.cm_key, RM_READ); if (cm_getval(&cm_args) != 0) { cm_end_trans(cm_args.cm_key); cmn_err(CE_WARN, "e3Dverify: no PUTCONFKEY at key 0x%x\n", key); return(ENODEV); } cm_end_trans(cm_args.cm_key);

    /* update resmgr */ e3Dputconf(putconfkey, &e3Dtmpdevice);

    e3Dconfigure(&e3Dtmpdevice); /* update firmware */

    return(0); } else { cmn_err(CE_WARN, "!e3Dverify: unknown mode %d\n",getset); return(ENODEV); }

CFG_ADD for all smart-bus devices

DDI 8 drivers for ISA devices must include the CFG_ADD subroutine to determine if this instance of the driver has been configured with netconfig. To do show, use the mdi_get_unit(D3mdi) function as shown in this example:
       switch(func) {
       case CFG_ADD:
       void **idatap = idata;
       int unit;
       struct cm_args cm_args;
       cm_range_t range;
       cm_num_t cm_num;
       char macaddr[18];  /* 22:33:44:55:66:77<NUL> */
       e3Ddev_t    *dev;
       extern char *e3Dpartnostr(unsigned char *);

/* determine if this instance has been configured with netcfg. While * just a good thing for ISA drivers, calling mdi_get_unit is essential for * ALL smart-bus (PCI, EISA, MCA) drivers - your CFG_ADD code will be * invoked for each instance in the resmgr that has MODNAME set to your * driver(e3D in this example driver). */ if (mdi_get_unit(rmkey, NULL) == B_FALSE) { return(ENXIO); }

CFG_SUSPEND for all smart-bus devices

DDI 8 drivers for all smart-bus devices must include the CFG_SUSPEND subroutine to disable interrupts. This is especially important if interrupt sharing is implemented on any architecture with level-triggered interrupts, because the kernel will attempt to service any interrupt that has not been de-asserted, even if the associated device has been halted.

Version applicability

mdi: 2, 2.1 running with ddi: 8, 8mp


config(D2), config(D2str), mdi_get_unit(D3mdi), mdi_hw_resumed(D3mdi), mdi_hw_suspended(D3mdi)

``Hotplug devices'' in HDK Technical Reference

19 June 2005
© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 6 and UnixWare (SVR5) HDK - June 2005