|
|
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);
if ( e3Dpresent(&e3Dtmpdevice, 1) == TRUE ) {
/* we don't need the memory mapping any more */
if (e3Dtmpdevice.ex_rambase) {
devmem_mapout(e3Dtmpdevice.ex_rambase,
e3Dtmpdevice.ex_memsize);
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;
}
return(ENODEV);
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.
*/
return(0);
} 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);
} 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);
}
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);
}
``Hotplug devices'' in HDK Technical Reference