/**Copyright(c)1997,1998DougRabson*Allrightsreserved.**Redistributionanduseinsourceandbinaryforms,withorwithout*modification,arepermittedpro
videdthatthefollowingconditions*aremet:*1.Redistributionsofsourcecodemustretaintheabovecopyright*notice,thislistofconditionsandthefollowingd
isclaimer.*2.Redistributionsinbinaryformmustreproducetheabovecopyright*notice,thislistofconditionsandthefollowingdisclaimerinthe*documentati
onand/orothermaterialsprovidedwiththedistribution.**THISSOFTWAREISPROVIDEDBYTHEAUTHORANDCONTRIBUTORS``ASIS''AND*ANYEXPRESSORIMPLIEDWARRANTIE
S,INCLUDING,BUTNOTLIMITEDTO,THE*IMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSE*AREDISCLAIMED.INNOEVENTSHALLTHEAUTHORORCON
TRIBUTORSBELIABLE*FORANYDIRECT,INDIRECT,INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQUENTIAL*DAMAGES(INCLUDING,BUTNOTLIMITEDTO,PROCUREMENTOFSUBSTITU
TEGOODS*ORSERVICES;LOSSOFUSE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)*HOWEVERCAUSEDANDONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICT*LIABILIT
Y,ORTORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAY*OUTOFTHEUSEOFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOF*SUCHDAMAGE.**$FreeBSD:src/
sys/kern/subr_bus.c,v1.54.2.82001/01/1800:19:50n_hibmaExp$*/#include"opt_bus.h"#include<sys/param.h>#include<sys/queue.h>#include<sys/malloc
.h>#include<sys/kernel.h>#include<sys/module.h>#ifdefDEVICE_SYSCTLS#include<sys/sysctl.h>#endif#include<sys/bus_private.h>#include<sys/systm
.h>#include<machine/bus.h>#include<sys/rman.h>#include<machine/stdarg.h>/*fordevice_printf()*/MALLOC_DEFINE(M_BUS,"bus","Busdatastructures")
;#ifdefBUS_DEBUG#definePDEBUG(a)(printf(__FUNCTION__":%d:",__LINE__),printfa,printf("\n"))#defineDEVICENAME(d)((d)?device_get_name(d):"nodev
ice")#defineDRIVERNAME(d)((d)?d->name:"nodriver")#defineDEVCLANAME(d)((d)?d->name:"nodevclass")/*Producetheindenting,indent*2spacesplusa'.'a
headofthatto*preventsyslogfromdeletinginitialspaces*/#defineindentprintf(p)do{intiJ;printf(".");for(iJ=0;iJ<indent;iJ++)printf("");printfp;}
while(0)staticvoidprint_method_list(device_method_t*m,intindent);staticvoidprint_device_ops(device_ops_tops,intindent);staticvoidprint_devic
e_short(device_tdev,intindent);staticvoidprint_device(device_tdev,intindent);voidprint_device_tree_short(device_tdev,intindent);voidprint_de
vice_tree(device_tdev,intindent);staticvoidprint_driver_short(driver_t*driver,intindent);staticvoidprint_driver(driver_t*driver,intindent);s
taticvoidprint_driver_list(driver_list_tdrivers,intindent);staticvoidprint_devclass_short(devclass_tdc,intindent);staticvoidprint_devclass(d
evclass_tdc,intindent);voidprint_devclass_list_short(void);voidprint_devclass_list(void);#else/*Makethecompilerignorethefunctioncalls*/#defi
nePDEBUG(a)/*nop*/#defineDEVICENAME(d)/*nop*/#defineDRIVERNAME(d)/*nop*/#defineDEVCLANAME(d)/*nop*/#defineprint_method_list(m,i)/*nop*/#defi
neprint_device_ops(o,i)/*nop*/#defineprint_device_short(d,i)/*nop*/#defineprint_device(d,i)/*nop*/#defineprint_device_tree_short(d,i)/*nop*/
#defineprint_device_tree(d,i)/*nop*/#defineprint_driver_short(d,i)/*nop*/#defineprint_driver(d,i)/*nop*/#defineprint_driver_list(d,i)/*nop*/
#defineprint_devclass_short(d,i)/*nop*/#defineprint_devclass(d,i)/*nop*/#defineprint_devclass_list_short()/*nop*/#defineprint_devclass_list(
)/*nop*/#endif#ifdefDEVICE_SYSCTLSstaticvoiddevice_register_oids(device_tdev);staticvoiddevice_unregister_oids(device_tdev);#endif/**Methodt
ablehandling*/staticinterror_method(void);staticintnext_method_offset=1;LIST_HEAD(methodlist,method)methods;structmethod{LIST_ENTRY(method)l
ink;/*linkedlistofmethods*/intoffset;/*offsetinmethodtable*/intrefs;/*countofdevice_op_descusers*/devop_tdeflt;/*defaultimplementation*/char
*name;/*uniquenameofmethod*/};staticvoidregister_method(structdevice_op_desc*desc){structmethod*m;if(desc->method){desc->method->refs++;retu
rn;}/**Makesurethatdesc->defltisalwaysvalidtosimplifydispatch.*/if(!desc->deflt)desc->deflt=error_method;for(m=LIST_FIRST(&methods);m;m=LIST
_NEXT(m,link)){if(!strcmp(m->name,desc->name)){desc->offset=m->offset;desc->method=m;m->refs++;PDEBUG(("method%phasthesamename,%s,withoffset
%d",(void*)m,desc->name,desc->offset));return;}}m=(structmethod*)malloc(sizeof(structmethod)+strlen(desc->name)+1,M_BUS,M_NOWAIT);if(!m)pani
c("register_method:outofmemory");bzero(m,sizeof(structmethod)+strlen(desc->name)+1);m->offset=next_method_offset++;m->refs=1;m->deflt=desc->
deflt;m->name=(char*)(m+1);strcpy(m->name,desc->name);LIST_INSERT_HEAD(&methods,m,link);desc->offset=m->offset;desc->method=m;}staticvoidunr
egister_method(structdevice_op_desc*desc){structmethod*m=desc->method;m->refs--;if(m->refs==0){PDEBUG(("method%s,reachedrefcount0",desc->nam
e));LIST_REMOVE(m,link);free(m,M_BUS);desc->method=0;}}staticinterror_method(void){returnENXIO;}staticstructdevice_opsnull_ops={1,{error_met
hod}};staticvoidcompile_methods(driver_t*driver){device_ops_tops;structdevice_method*m;structmethod*cm;inti;/**Firstregisteranymethodswhichn
eedit.*/for(i=0,m=driver->methods;m->desc;i++,m++)register_method(m->desc);/**Thenallocatethecompiledoptable.*/ops=malloc(sizeof(structdevic
e_ops)+(next_method_offset-1)*sizeof(devop_t),M_BUS,M_NOWAIT);if(!ops)panic("compile_methods:outofmemory");bzero(ops,sizeof(structdevice_ops
)+(next_method_offset-1)*sizeof(devop_t));ops->maxoffset=next_method_offset;/*Fillindefaultmethodsandthenoverwritewithdrivermethods*/for(i=0
;i<next_method_offset;i++)ops->methods[i]=error_method;for(cm=LIST_FIRST(&methods);cm;cm=LIST_NEXT(cm,link)){if(cm->deflt)ops->methods[cm->o
ffset]=cm->deflt;}for(i=0,m=driver->methods;m->desc;i++,m++)ops->methods[m->desc->offset]=m->func;PDEBUG(("%shas%dmethod%s,wasting%dbytes",D
RIVERNAME(driver),i,(i==1?"":"s"),(next_method_offset-i)*sizeof(devop_t)));driver->ops=ops;}staticvoidfree_methods(driver_t*driver){inti;str
uctdevice_method*m;/**Unregisteranymethodswhicharenolongerused.*/for(i=0,m=driver->methods;m->desc;i++,m++)unregister_method(m->desc);/**Fre
ememoryandcleanup.*/free(driver->ops,M_BUS);driver->ops=0;}/**Devclassimplementation*/staticdevclass_list_tdevclasses=TAILQ_HEAD_INITIALIZER
(devclasses);staticdevclass_tdevclass_find_internal(constchar*classname,intcreate){devclass_tdc;PDEBUG(("lookingfor%s",classname));if(!class
name)returnNULL;for(dc=TAILQ_FIRST(&devclasses);dc;dc=TAILQ_NEXT(dc,link))if(!strcmp(dc->name,classname))returndc;PDEBUG(("%snotfound%s",cla
ssname,(create?",creating":"")));if(create){dc=malloc(sizeof(structdevclass)+strlen(classname)+1,M_BUS,M_NOWAIT);if(!dc)returnNULL;bzero(dc,
sizeof(structdevclass)+strlen(classname)+1);dc->name=(char*)(dc+1);strcpy(dc->name,classname);dc->devices=NULL;dc->maxunit=0;TAILQ_INIT(&dc-
>drivers);TAILQ_INSERT_TAIL(&devclasses,dc,link);}returndc;}devclass_tdevclass_create(constchar*classname){returndevclass_find_internal(clas
sname,TRUE);}devclass_tdevclass_find(constchar*classname){returndevclass_find_internal(classname,FALSE);}intdevclass_add_driver(devclass_tdc
,driver_t*driver){driverlink_tdl;inti;PDEBUG(("%s",DRIVERNAME(driver)));dl=malloc(sizeof*dl,M_BUS,M_NOWAIT);if(!dl)returnENOMEM;bzero(dl,siz
eof*dl);/**Compilethedriver'smethods.*/if(!driver->ops)compile_methods(driver);/**Makesurethedevclasswhichthedriverisimplementingexists.*/de
vclass_find_internal(driver->name,TRUE);dl->driver=driver;TAILQ_INSERT_TAIL(&dc->drivers,dl,link);driver->refs++;/**CallBUS_DRIVER_ADDEDfora
nyexistingbussesinthisclass.*/for(i=0;i<dc->maxunit;i++)if(dc->devices[i])BUS_DRIVER_ADDED(dc->devices[i],driver);return0;}intdevclass_delet
e_driver(devclass_tbusclass,driver_t*driver){devclass_tdc=devclass_find(driver->name);driverlink_tdl;device_tdev;inti;interror;PDEBUG(("%sfr
omdevclass%s",driver->name,DEVCLANAME(busclass)));if(!dc)return0;/**Findthelinkstructureinthebus'listofdrivers.*/for(dl=TAILQ_FIRST(&busclas
s->drivers);dl;dl=TAILQ_NEXT(dl,link)){if(dl->driver==driver)break;}if(!dl){PDEBUG(("%snotfoundin%slist",driver->name,busclass->name));retur
nENOENT;}/**Disassociatefromanydevices.Weiteratethroughallthe*devicesinthedevclassofthedriveranddetachanywhichare*usingthedriverandwhichhave
aparentinthedevclasswhich*wearedeletingfrom.**Notethatsinceadrivercanbeinmultipledevclasses,we*shouldnotdetachdeviceswhicharenotchildrenofde
vicesin*theaffecteddevclass.*/for(i=0;i<dc->maxunit;i++){if(dc->devices[i]){dev=dc->devices[i];if(dev->driver==driver&&dev->parent&&dev->par
ent->devclass==busclass){if((error=device_detach(dev))!=0)returnerror;device_set_driver(dev,NULL);}}}TAILQ_REMOVE(&busclass->drivers,dl,link
);free(dl,M_BUS);driver->refs--;if(driver->refs==0)free_methods(driver);return0;}staticdriverlink_tdevclass_find_driver_internal(devclass_td
c,constchar*classname){driverlink_tdl;PDEBUG(("%sindevclass%s",classname,DEVCLANAME(dc)));for(dl=TAILQ_FIRST(&dc->drivers);dl;dl=TAILQ_NEXT(
dl,link)){if(!strcmp(dl->driver->name,classname))returndl;}PDEBUG(("notfound"));returnNULL;}driver_t*devclass_find_driver(devclass_tdc,const
char*classname){driverlink_tdl;dl=devclass_find_driver_internal(dc,classname);if(dl)returndl->driver;elsereturnNULL;}constchar*devclass_get_
name(devclass_tdc){returndc->name;}device_tdevclass_get_device(devclass_tdc,intunit){if(dc==NULL||unit<0||unit>=dc->maxunit)returnNULL;retur
ndc->devices[unit];}void*devclass_get_softc(devclass_tdc,intunit){device_tdev;dev=devclass_get_device(dc,unit);if(!dev)return(NULL);return(d
evice_get_softc(dev));}intdevclass_get_devices(devclass_tdc,device_t**devlistp,int*devcountp){inti;intcount;device_t*list;count=0;for(i=0;i<
dc->maxunit;i++)if(dc->devices[i])count++;list=malloc(count*sizeof(device_t),M_TEMP,M_NOWAIT);if(!list)returnENOMEM;bzero(list,count*sizeof(
device_t));count=0;for(i=0;i<dc->maxunit;i++)if(dc->devices[i]){list[count]=dc->devices[i];count++;}*devlistp=list;*devcountp=count;return0;
}intdevclass_get_maxunit(devclass_tdc){returndc->maxunit;}staticintdevclass_alloc_unit(devclass_tdc,int*unitp){intunit=*unitp;PDEBUG(("unit%
dindevclass%s",unit,DEVCLANAME(dc)));/*Ifwehavebeengivenawiredunitnumber,checkforexistingdevice*/if(unit!=-1){if(unit>=0&&unit<dc->maxunit&&
dc->devices[unit]!=NULL){if(bootverbose)printf("%s-:%s%dexists,usingnextavailableunitnumber\n",dc->name,dc->name,unit);/*findthenextavailabl
eslot*/while(++unit<dc->maxunit&&dc->devices[unit]!=NULL);}}else{/*Unwireddevice,findthenextavailableslotforit*/unit=0;while(unit<dc->maxuni
t&&dc->devices[unit]!=NULL)unit++;}/**We'veselectedaunitbeyondthelengthofthetable,solet'sextend*thetabletomakeroomforallunitsuptoandincludin
gthisone.*/if(unit>=dc->maxunit){device_t*newlist;intnewsize;newsize=roundup((unit+1),MINALLOCSIZE/sizeof(device_t));newlist=malloc(sizeof(d
evice_t)*newsize,M_BUS,M_NOWAIT);if(!newlist)returnENOMEM;bcopy(dc->devices,newlist,sizeof(device_t)*dc->maxunit);bzero(newlist+dc->maxunit,
sizeof(device_t)*(newsize-dc->maxunit));if(dc->devices)free(dc->devices,M_BUS);dc->devices=newlist;dc->maxunit=newsize;}PDEBUG(("now:unit%di
ndevclass%s",unit,DEVCLANAME(dc)));*unitp=unit;return0;}staticintdevclass_add_device(devclass_tdc,device_tdev){intbuflen,error;PDEBUG(("%sin
devclass%s",DEVICENAME(dev),DEVCLANAME(dc)));buflen=strlen(dc->name)+5;dev->nameunit=malloc(buflen,M_BUS,M_NOWAIT);if(!dev->nameunit)returnE
NOMEM;bzero(dev->nameunit,buflen);if((error=devclass_alloc_unit(dc,&dev->unit))!=0){free(dev->nameunit,M_BUS);dev->nameunit=NULL;returnerror
;}dc->devices[dev->unit]=dev;dev->devclass=dc;snprintf(dev->nameunit,buflen,"%s%d",dc->name,dev->unit);#ifdefDEVICE_SYSCTLSdevice_register_o
ids(dev);#endifreturn0;}staticintdevclass_delete_device(devclass_tdc,device_tdev){if(!dc||!dev)return0;PDEBUG(("%sindevclass%s",DEVICENAME(d
ev),DEVCLANAME(dc)));if(dev->devclass!=dc||dc->devices[dev->unit]!=dev)panic("devclass_delete_device:inconsistentdeviceclass");dc->devices[d
ev->unit]=NULL;if(dev->flags&DF_WILDCARD)dev->unit=-1;dev->devclass=NULL;free(dev->nameunit,M_BUS);dev->nameunit=NULL;#ifdefDEVICE_SYSCTLSde
vice_unregister_oids(dev);#endifreturn0;}staticdevice_tmake_device(device_tparent,constchar*name,intunit){device_tdev;devclass_tdc;PDEBUG(("
%sat%sasunit%d",name,DEVICENAME(parent),unit));if(name){dc=devclass_find_internal(name,TRUE);if(!dc){printf("make_device:can'tfinddeviceclas
s%s\n",name);returnNULL;}}elsedc=NULL;dev=malloc(sizeof(structdevice),M_BUS,M_NOWAIT);if(!dev)return0;bzero(dev,sizeof(structdevice));dev->p
arent=parent;TAILQ_INIT(&dev->children);dev->ops=&null_ops;dev->driver=NULL;dev->devclass=NULL;dev->unit=unit;dev->nameunit=NULL;dev->desc=N
ULL;dev->busy=0;dev->devflags=0;dev->flags=DF_ENABLED;dev->order=0;if(unit==-1)dev->flags|=DF_WILDCARD;if(name){dev->flags|=DF_FIXEDCLASS;de
vclass_add_device(dc,dev);}dev->ivars=NULL;dev->softc=NULL;dev->state=DS_NOTPRESENT;returndev;}staticintdevice_print_child(device_tdev,devic
e_tchild){intretval=0;if(device_is_alive(child)){retval+=BUS_PRINT_CHILD(dev,child);}elseretval+=device_printf(child,"notfound\n");return(re
tval);}device_tdevice_add_child(device_tdev,constchar*name,intunit){returndevice_add_child_ordered(dev,0,name,unit);}device_tdevice_add_chil
d_ordered(device_tdev,intorder,constchar*name,intunit){device_tchild;device_tplace;PDEBUG(("%sat%swithorder%dasunit%d",name,DEVICENAME(dev),
order,unit));child=make_device(dev,name,unit);if(child==NULL)returnchild;child->order=order;TAILQ_FOREACH(place,&dev->children,link)if(place
->order>order)break;if(place){/**Thedevice'place'isthefirstdevicewhoseorderis*greaterthanthenewchild.*/TAILQ_INSERT_BEFORE(place,child,link)
;}else{/**Thenewchild'sorderisgreaterorequaltotheorderof*anyexistingdevice.Addthechildtothetailofthelist.*/TAILQ_INSERT_TAIL(&dev->children,
child,link);}returnchild;}intdevice_delete_child(device_tdev,device_tchild){interror;device_tgrandchild;PDEBUG(("%sfrom%s",DEVICENAME(child)
,DEVICENAME(dev)));/*removechildrenfirst*/while((grandchild=TAILQ_FIRST(&child->children))){error=device_delete_child(child,grandchild);if(e
rror)returnerror;}if((error=device_detach(child))!=0)returnerror;if(child->devclass)devclass_delete_device(child->devclass,child);TAILQ_REMO
VE(&dev->children,child,link);device_set_desc(child,NULL);free(child,M_BUS);return0;}/**Findonlydevicesattachedtothisbus.*/device_tdevice_fi
nd_child(device_tdev,constchar*classname,intunit){devclass_tdc;device_tchild;dc=devclass_find(classname);if(!dc)returnNULL;child=devclass_ge
t_device(dc,unit);if(child&&child->parent==dev)returnchild;returnNULL;}staticdriverlink_tfirst_matching_driver(devclass_tdc,device_tdev){if(
dev->devclass)returndevclass_find_driver_internal(dc,dev->devclass->name);elsereturnTAILQ_FIRST(&dc->drivers);}staticdriverlink_tnext_matchi
ng_driver(devclass_tdc,device_tdev,driverlink_tlast){if(dev->devclass){driverlink_tdl;for(dl=TAILQ_NEXT(last,link);dl;dl=TAILQ_NEXT(dl,link)
)if(!strcmp(dev->devclass->name,dl->driver->name))returndl;returnNULL;}elsereturnTAILQ_NEXT(last,link);}staticintdevice_probe_child(device_t
dev,device_tchild){devclass_tdc;driverlink_tbest=0;driverlink_tdl;intresult,pri=0;inthasclass=(child->devclass!=0);dc=dev->devclass;if(!dc)p
anic("device_probe_child:parentdevicehasnodevclass");if(child->state==DS_ALIVE)return0;for(dl=first_matching_driver(dc,child);dl;dl=next_mat
ching_driver(dc,child,dl)){PDEBUG(("Trying%s",DRIVERNAME(dl->driver)));device_set_driver(child,dl->driver);if(!hasclass)device_set_devclass(
child,dl->driver->name);result=DEVICE_PROBE(child);if(!hasclass)device_set_devclass(child,0);/**IfthedriverreturnsSUCCESS,therecanbenohigher
match*forthisdevice.*/if(result==0){best=dl;pri=0;break;}/**Thedriverreturnedanerrorsoitcertainlydoesn'tmatch.*/if(result>0){device_set_driv
er(child,0);continue;}/**AprioritylowerthanSUCCESS,rememberthebestmatching*driver.Initialisethevalueofpriforthefirstmatch.*/if(best==0||resu
lt>pri){best=dl;pri=result;continue;}}/**Ifwefoundadriver,changestateandinitialisethedevclass.*/if(best){if(!child->devclass)device_set_devc
lass(child,best->driver->name);device_set_driver(child,best->driver);if(pri<0){/**Abitbogus.Calltheprobemethodagaintomakesure*thatwehavether
ightdescription.*/DEVICE_PROBE(child);}child->state=DS_ALIVE;return0;}returnENXIO;}device_tdevice_get_parent(device_tdev){returndev->parent;
}intdevice_get_children(device_tdev,device_t**devlistp,int*devcountp){intcount;device_tchild;device_t*list;count=0;for(child=TAILQ_FIRST(&de
v->children);child;child=TAILQ_NEXT(child,link))count++;list=malloc(count*sizeof(device_t),M_TEMP,M_NOWAIT);if(!list)returnENOMEM;bzero(list
,count*sizeof(device_t));count=0;for(child=TAILQ_FIRST(&dev->children);child;child=TAILQ_NEXT(child,link)){list[count]=child;count++;}*devli
stp=list;*devcountp=count;return0;}driver_t*device_get_driver(device_tdev){returndev->driver;}devclass_tdevice_get_devclass(device_tdev){ret
urndev->devclass;}constchar*device_get_name(device_tdev){if(dev->devclass)returndevclass_get_name(dev->devclass);returnNULL;}constchar*devic
e_get_nameunit(device_tdev){returndev->nameunit;}intdevice_get_unit(device_tdev){returndev->unit;}constchar*device_get_desc(device_tdev){ret
urndev->desc;}u_int32_tdevice_get_flags(device_tdev){returndev->devflags;}intdevice_print_prettyname(device_tdev){constchar*name=device_get_
name(dev);if(name==0)returnprintf("unknown:");elsereturnprintf("%s%d:",name,device_get_unit(dev));}intdevice_printf(device_tdev,constchar*fm
t,...){va_listap;intretval;retval=device_print_prettyname(dev);va_start(ap,fmt);retval+=vprintf(fmt,ap);va_end(ap);returnretval;}staticvoidd
evice_set_desc_internal(device_tdev,constchar*desc,intcopy){if(dev->desc&&(dev->flags&DF_DESCMALLOCED)){free(dev->desc,M_BUS);dev->flags&=~D
F_DESCMALLOCED;dev->desc=NULL;}if(copy&&desc){dev->desc=malloc(strlen(desc)+1,M_BUS,M_NOWAIT);if(dev->desc){strcpy(dev->desc,desc);dev->flag
s|=DF_DESCMALLOCED;}}else/*Avoida-Wcast-qualwarning*/dev->desc=(char*)(uintptr_t)desc;#ifdefDEVICE_SYSCTLS{structsysctl_oid*oid=&dev->oid[1]
;oid->oid_arg1=dev->desc?dev->desc:"";oid->oid_arg2=dev->desc?strlen(dev->desc):0;}#endif}voiddevice_set_desc(device_tdev,constchar*desc){de
vice_set_desc_internal(dev,desc,FALSE);}voiddevice_set_desc_copy(device_tdev,constchar*desc){device_set_desc_internal(dev,desc,TRUE);}voidde
vice_set_flags(device_tdev,u_int32_tflags){dev->devflags=flags;}void*device_get_softc(device_tdev){returndev->softc;}voiddevice_set_softc(de
vice_tdev,void*softc){if(dev->softc&&!(dev->flags&DF_EXTERNALSOFTC))free(dev->softc,M_BUS);dev->softc=softc;if(dev->softc)dev->flags|=DF_EXT
ERNALSOFTC;elsedev->flags&=~DF_EXTERNALSOFTC;}void*device_get_ivars(device_tdev){returndev->ivars;}voiddevice_set_ivars(device_tdev,void*iva
rs){if(!dev)return;dev->ivars=ivars;return;}device_state_tdevice_get_state(device_tdev){returndev->state;}voiddevice_enable(device_tdev){dev
->flags|=DF_ENABLED;}voiddevice_disable(device_tdev){dev->flags&=~DF_ENABLED;}voiddevice_busy(device_tdev){if(dev->state<DS_ATTACHED)panic("
device_busy:calledforunattacheddevice");if(dev->busy==0&&dev->parent)device_busy(dev->parent);dev->busy++;dev->state=DS_BUSY;}voiddevice_unb
usy(device_tdev){if(dev->state!=DS_BUSY)panic("device_unbusy:calledfornon-busydevice");dev->busy--;if(dev->busy==0){if(dev->parent)device_un
busy(dev->parent);dev->state=DS_ATTACHED;}}voiddevice_quiet(device_tdev){dev->flags|=DF_QUIET;}voiddevice_verbose(device_tdev){dev->flags&=~
DF_QUIET;}intdevice_is_quiet(device_tdev){return(dev->flags&DF_QUIET)!=0;}intdevice_is_enabled(device_tdev){return(dev->flags&DF_ENABLED)!=0
;}intdevice_is_alive(device_tdev){returndev->state>=DS_ALIVE;}intdevice_set_devclass(device_tdev,constchar*classname){devclass_tdc;if(!class
name){if(dev->devclass)devclass_delete_device(dev->devclass,dev);return0;}if(dev->devclass){printf("device_set_devclass:deviceclassalreadyse
t\n");returnEINVAL;}dc=devclass_find_internal(classname,TRUE);if(!dc)returnENOMEM;returndevclass_add_device(dc,dev);}intdevice_set_driver(de
vice_tdev,driver_t*driver){if(dev->state>=DS_ATTACHED)returnEBUSY;if(dev->driver==driver)return0;if(dev->softc&&!(dev->flags&DF_EXTERNALSOFT
C)){free(dev->softc,M_BUS);dev->softc=NULL;}dev->ops=&null_ops;dev->driver=driver;if(driver){dev->ops=driver->ops;if(!(dev->flags&DF_EXTERNA
LSOFTC)){dev->softc=malloc(driver->softc,M_BUS,M_NOWAIT);if(!dev->softc){dev->ops=&null_ops;dev->driver=NULL;returnENOMEM;}bzero(dev->softc,
driver->softc);}}return0;}intdevice_probe_and_attach(device_tdev){device_tbus=dev->parent;interror=0;inthasclass=(dev->devclass!=0);if(dev->
state>=DS_ALIVE)return0;if(dev->flags&DF_ENABLED){error=device_probe_child(bus,dev);if(!error){if(!device_is_quiet(dev))device_print_child(b
us,dev);error=DEVICE_ATTACH(dev);if(!error)dev->state=DS_ATTACHED;else{printf("device_probe_and_attach:%s%dattachreturned%d\n",dev->driver->
name,dev->unit,error);/*Unsettheclassthatwassetindevice_probe_child*/if(!hasclass)device_set_devclass(dev,0);device_set_driver(dev,NULL);dev
->state=DS_NOTPRESENT;}}else{if(!(dev->flags&DF_DONENOMATCH)){BUS_PROBE_NOMATCH(bus,dev);dev->flags|=DF_DONENOMATCH;}}}else{if(bootverbose){
device_print_prettyname(dev);printf("notprobed(disabled)\n");}}returnerror;}intdevice_detach(device_tdev){interror;PDEBUG(("%s",DEVICENAME(d

Hosted by uCoz