Subject: Re: Device Properties: The Last Incarnation
To: None <tech-kern@netbsd.org>
From: Ignatios Souvatzis <is@netbsd.org>
List: tech-kern
Date: 03/04/2001 10:10:06
Chris Demetriou has brought to my attention that parts of the Device
Properties proposal may conflict with the (ab)?use of config_search in
NetBSD/Amiga (and Atari; though some details may be different).

NetBSD/Amiga can have a several different console output devices:
ser at mainbus (on non-DraCo), ite at grf at grfcc0 at mainbus (on
non-DraCo), and ite at grf at grfFOO at zbus at mainbus.

Also, it can have several different CPUs at several different speeds and
needs to calibrate the delay() routine before (some of the) drivers are 
initialized.

NetBSD-Amiga does this:

- before console selection, it runs a fake autoconfiguration pass on busses
  that can have a console device, and for the clock (that does the delay
  calibration) and ser mainbus devices.

- during this pass, devices get a NULL variable storage area, and use a 
  static one if they decide the might be a console.

- now console selection happens.

- after this, real configuration happens. Instances of devices that know
  they are a console don't reinitialize, but copy their early config state
  to the new device struct.

This happens in the config_console() and amiga_config_found() routines 
in amiga/amiga/autoconf.c cited below for your convenience. Some knowledge
of this is in amiga/dev/zbus.c, and obviously in the clock, grf* and ite*
drivers. 

My memory is a bit fuzzy about the details. Also, I have not yet closely
followed the Device Property proposal discussion, so I can't yet propose 
what to do. Suggestions are welcome.

Regards,
	-is

/*
 * this function needs to get enough configured to do a console
 * basically this means start attaching the grfxx's that support
 * the console. Kinda hacky but it works.
 */
void
config_console()
{
        struct cfdata *cf;

        /*
         * we need mainbus' cfdata.
         */
        cf = config_rootsearch(NULL, "mainbus", "mainbus");
        if (cf == NULL) {
                panic("no mainbus");
        }
        /*
         * delay clock calibration.
         */
        amiga_config_found(cf, NULL, "clock", NULL);

        /*
         * internal grf.
         */
#ifdef DRACO
        if (!(is_draco()))
#endif
                amiga_config_found(cf, NULL, "grfcc", NULL);

        /*
         * zbus knows when its not for real and will
         * only configure the appropriate hardware
         */
        amiga_config_found(cf, NULL, "zbus", NULL);
}


/*
 * use config_search to find appropriate device, then call that device
 * directly with NULL device variable storage.  A device can then
 * always tell the difference betwean the real and console init
 * by checking for NULL.
 */             
int             
amiga_config_found(pcfp, pdp, auxp, pfn)
        struct cfdata *pcfp;
        struct device *pdp;
        void *auxp;
        cfprint_t pfn;  
{   
        struct device temp;
        struct cfdata *cf;

        if (amiga_realconfig)
                return(config_found(pdp, auxp, pfn) != NULL);

        if (pdp == NULL)
                pdp = &temp;

        pdp->dv_cfdata = pcfp;
        if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) {
                cf->cf_attach->ca_attach(pdp, NULL, auxp); 
                pdp->dv_cfdata = NULL;
                return(1);
        }
        pdp->dv_cfdata = NULL;
        return(0);
}