/* Copyright 1999 Red Hat, Inc. * * This software may be freely redistributed under the terms of the GNU * public license. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include "isapnp.h" /* I am in hell. ISAPnP is the fifth circle. */ /* Default to new-style access. */ static int access_type = 1; /* Needed for old access */ static int readport = 0; static void isapnpFreeDevice(struct isapnpDevice *dev) { if (dev->pdeviceId) free(dev->pdeviceId); if (dev->ppnpdesc) free(dev->ppnpdesc); if (dev->deviceId) free(dev->deviceId); if (dev->pnpdesc) free(dev->pnpdesc); if (dev->compat) free(dev->compat); if (dev->io) free(dev->io); if (dev->irq) free(dev->irq); if (dev->dma) free(dev->dma); if (dev->mem) free(dev->mem); freeDevice((struct device *)dev); } static void isapnpWriteDevice(FILE *file, struct isapnpDevice *dev) { int x; writeDevice(file, (struct device *)dev); if (dev->pdeviceId) fprintf(file,"pdeviceId: %s\n", dev->pdeviceId); if (dev->ppnpdesc) fprintf(file,"ppnpdesc: %s\n", dev->ppnpdesc); if (dev->deviceId) fprintf(file,"deviceId: %s\n",dev->deviceId); if (dev->pnpdesc) fprintf(file,"pnpdesc: %s\n",dev->pnpdesc); if (dev->compat) fprintf(file,"compat: %s\n",dev->compat); if (dev->io && dev->io[0]!=-1) { fprintf(file,"io: 0x%x", dev->io[0]); for (x=1;dev->io[x]!=-1;x++) fprintf(file,",0x%x",dev->io[x]); fprintf(file,"\n"); } if (dev->irq && dev->irq[0]!=-1) { fprintf(file,"irq: %d", dev->irq[0]); for (x=1;dev->irq[x]!=-1;x++) fprintf(file,",%d",dev->irq[x]); fprintf(file,"\n"); } if (dev->dma && dev->dma[0]!=-1) { fprintf(file,"dma: %d", dev->dma[0]); for (x=1;dev->dma[x]!=-1;x++) fprintf(file,",%d",dev->dma[x]); fprintf(file,"\n"); } if (dev->mem && dev->mem[0]!=-1) { fprintf(file,"mem: 0x%x", dev->mem[0]); for (x=1;dev->mem[x]!=-1;x++) fprintf(file,",0x%x",dev->mem[x]); fprintf(file,"\n"); } } static int devCmp(const void * a, const void * b) { /* All devices are equal... */ return 0; } static int isapnpCompareDevice(struct isapnpDevice *dev1, struct isapnpDevice *dev2) { int x=compareDevice((struct device *)dev1,(struct device *)dev2); if (x) return x; return devCmp( (void *)dev1, (void *)dev2 ); /* needs finished */ } struct isapnpDevice * isapnpNewDevice(struct isapnpDevice *dev) { struct isapnpDevice *ret; ret = malloc(sizeof(struct isapnpDevice)); memset(ret,'\0',sizeof(struct isapnpDevice)); ret=(struct isapnpDevice *)newDevice((struct device *)dev,(struct device *)ret); ret->bus = BUS_ISAPNP; if (dev && dev->bus == BUS_ISAPNP) { int x=0; if (dev->pdeviceId) ret->pdeviceId=strdup(dev->pdeviceId); if (dev->ppnpdesc) ret->ppnpdesc=strdup(dev->ppnpdesc); if (dev->deviceId) ret->deviceId=strdup(dev->deviceId); if (dev->pnpdesc) ret->pnpdesc=strdup(dev->pnpdesc); if (dev->compat) ret->compat=strdup(dev->compat); if (dev->io) { for (x=0;dev->io[x]!=-1;x++) { ret->io=realloc(ret->io,(x+1)*sizeof(int)); ret->io[x]=dev->io[x]; } ret->io[x]=-1; } if (dev->irq) { for (x=0;dev->irq[x]!=-1;x++) { ret->irq=realloc(ret->irq,(x+1)*sizeof(int)); ret->irq[x]=dev->irq[x]; } ret->irq[x]=-1; } if (dev->dma) { for (x=0;dev->dma[x]!=-1;x++) { ret->dma=realloc(ret->dma,(x+1)*sizeof(int)); ret->dma[x]=dev->dma[x]; } ret->dma[x]=-1; } if (dev->mem) { for (x=0;dev->mem[x]!=-1;x++) { ret->mem=realloc(ret->mem,(x+1)*sizeof(int)); ret->mem[x]=dev->mem[x]; } ret->mem[x]=-1; } } ret->newDevice = isapnpNewDevice; ret->freeDevice = isapnpFreeDevice; ret->writeDevice = isapnpWriteDevice; ret->compareDevice = isapnpCompareDevice; return ret; } int *isapnpReadResources(char *line, int base) { int *ret=NULL, x=0; char *ptr; do { ptr=strstr(line,","); if (ptr) *ptr='\0'; x++; ret = realloc(ret,(x+2)*sizeof(int)); ret[x-1] = strtoul(line,NULL,base); ret[x] = -1; if (ptr) line = ptr+1; } while (ptr); return ret; } struct device * isapnpProbeKernel(enum deviceClass probeClass, int probeFlags, struct device *devlist, int fd) { char *pnpbuf=NULL; char *start, *current, *ptr; struct isapnpDevice *dev; char pdev[10], pdesc[64]; char buf[2048]; int x, len=0; while ( (x=read(fd,buf,2048))==2048 ) { pnpbuf=realloc(pnpbuf,len+2048); strncpy(pnpbuf+len,buf,2048); len+=2048; } if (x && x!=-1) { pnpbuf=realloc(pnpbuf,len+x); strncpy(pnpbuf+len,buf,x); len+=x; pnpbuf[len]='\0'; } if (!pnpbuf) { close(fd); return devlist; } close(fd); start = pnpbuf; while (start && *start) { current = start; while (*current && *current != '\n') current++; if (*current) { *current = '\0'; current++; } if (!strncmp("Card ",start,5)) { start+=8; if ( (ptr=strstr(start,":")) ) { *ptr='\0'; strncpy(pdev,start,10); start=ptr+1; if ( (ptr=strstr(start,"'")) ) { *ptr='\0'; strncpy(pdesc,start,64); start=ptr+1; } } } else if (!strncmp(" Logical device",start,16)) { dev = isapnpNewDevice(NULL); if (devlist) { dev->next = devlist; } devlist = (struct device *)dev; dev->pdeviceId = strdup(pdev); dev->ppnpdesc = strdup(pdesc); dev->driver = strdup("unknown"); start += 20; if ( (ptr=strstr(start,":")) ) { *ptr='\0'; dev->deviceId = strdup(start); start = ptr+1; if ( (ptr=strstr(start,"'")) ) { *ptr = '\0'; dev->pnpdesc = strdup(start); } } dev->desc = malloc(strlen(dev->ppnpdesc)+strlen(dev->pnpdesc)+3); snprintf(dev->desc,strlen(dev->ppnpdesc)+strlen(dev->pnpdesc)+2,"%s:%s",dev->ppnpdesc,dev->pnpdesc); } else if (!strncmp(" Compatible device", start,21)) { dev->compat=strdup(start+22); } else if (!strncmp(" Active port", start, 15)) { dev->io=isapnpReadResources(start+16,16); } else if (!strncmp(" Active IRQ", start, 14)) { dev->irq=isapnpReadResources(start+15,10); } else if (!strncmp(" Active DMA", start, 14)) { dev->dma=isapnpReadResources(start+15,10); } else if (!strncmp(" Active memory", start, 17)) { dev->mem=isapnpReadResources(start+18,16); } start = current; } return devlist; } struct device * isapnpProbeOld(enum deviceClass probeClass, int probeFlags, struct device *devlist) { return devlist; } struct device * isapnpProbe(enum deviceClass probeClass, int probeFlags, struct device *devlist) { int fd; if ( (probeClass == CLASS_UNSPEC) || (probeClass == CLASS_OTHER) || (probeClass == CLASS_NETWORK) || (probeClass == CLASS_MODEM) || (probeClass == CLASS_AUDIO) ) { fd = open("./isapnp",O_RDONLY); if (fd==-1) { fd = open("/proc/isapnp",O_RDONLY); if (fd==-1) { if (probeFlags & PROBE_SAFE) return devlist; access_type = 0; devlist = isapnpProbeOld(probeClass, probeFlags, devlist); } } if (fd != -1) { devlist = isapnpProbeKernel(probeClass, probeFlags, devlist, fd); } } return devlist; }