/*====================================================================== PCMCIA controller probe Written by David Hinds, dhinds@allegro.stanford.edu ======================================================================*/ #include #include #include #include #include #include #include #include #ifdef MSF_COMMENTED_ME_OUT #include #include "i82365.h" #include "pd67xx.h" #include "vg468.h" #include "tcic.h" #endif #include "pcmcia-probe.h" #include "pcmcia-defines.h" #ifdef MSF_COMMENTED_ME_OUT static const char *version = "probe.c 1.21 1997/03/21 07:25:23 (David Hinds)\n"; #endif static int i365_base = 0x03e0; /*====================================================================*/ #ifdef CONFIG_PCI typedef struct { char *tag; char *name; } pci_id_t; pci_id_t pci_id[] = { { "Cirrus Logic CL 6729", "Cirrus PD6729" }, { "Vendor id=119b. Device id=1221.", "Omega Micro 82C092G" }, { "Vendor id=1180. Device id=466.", "Ricoh RL5C466" }, { "Vendor id=10b3. Device id=b106.", "SMC 34C90" }, { "Vendor id=1013. Device id=1110.", "Cirrus PD6832" }, { "Vendor id=104c. Device id=ac12.", "TI 1131" } }; #define PCI_COUNT (sizeof(pci_id)/sizeof(pci_id_t)) static int pci_probe(int verbose, int module) { char buf[4096], *name = NULL; int sock = 0, fd, nb, i; if (!module) printf("PCI bridge probe: "); fd = open("/proc/pci", O_RDONLY); if (fd != -1) { nb = read(fd, buf, 4096); buf[nb] = '\0'; for (i = 0; i < PCI_COUNT; i++) if (strstr(buf, pci_id[i].tag) != NULL) break; if (i != PCI_COUNT) { name = pci_id[i].name; sock = 2; } close(fd); } if (sock != 0) { if (module) printf("i82365\n"); else printf("%s found, %d sockets.\n", name, sock); return 0; } else { if (!module) printf("not found.\n"); return -ENODEV; } } #endif /*====================================================================*/ static u_char i365_get(u_short sock, u_short reg) { u_char val = I365_REG(sock, reg); outb_p(val, i365_base); val = inb_p(i365_base+1); return val; } static void i365_set(u_short sock, u_short reg, u_char data) { u_char val = I365_REG(sock, reg); outb_p(val, i365_base); outb_p(data, i365_base+1); } static void i365_bset(u_short sock, u_short reg, u_char mask) { u_char d = i365_get(sock, reg); d |= mask; i365_set(sock, reg, d); } static void i365_bclr(u_short sock, u_short reg, u_char mask) { u_char d = i365_get(sock, reg); d &= ~mask; i365_set(sock, reg, d); } /*====================================================================*/ /* msf - returns char * that you can examine, but DONT FREE IT! */ /* NULL means nothing found */ char *i365_probe(int verbose, int module) { int val, sock, done; char *name = "i82365sl"; #ifdef MSF_COMMENTED_ME_OUT if (!module) printf("Intel PCIC probe: "); if (verbose) printf("\n"); #endif sock = done = 0; ioperm(i365_base, 4, 1); ioperm(0x80, 1, 1); for (; sock < 2; sock++) { val = i365_get(sock, I365_IDENT); if (verbose) printf(" ident(%d)=%#2.2x", sock, val); switch (val) { case 0x82: name = "i82365sl A step"; break; case 0x83: name = "i82365sl B step"; break; case 0x84: name = "VLSI 82C146"; break; case 0x88: case 0x89: case 0x8a: name = "IBM Clone"; break; case 0x8b: case 0x8c: break; default: done = 1; } if (done) break; } if (verbose) printf("\n "); if (sock == 0) { #ifdef MSF_COMMENTED_ME_OUT if (!module) printf("not found.\n"); #endif return NULL; } if ((sock == 2) && (strcmp(name, "VLSI 82C146") == 0)) name = "i82365sl DF"; /* Check for Vadem chips */ outb_p(0x0e, i365_base); outb_p(0x37, i365_base); i365_bset(0, VG468_MISC, VG468_MISC_VADEMREV); val = i365_get(0, I365_IDENT); if (val & I365_IDENT_VADEM) { if ((val & 7) < 4) name = "Vadem VG-468"; else name = "Vadem VG-469"; i365_bclr(0, VG468_MISC, VG468_MISC_VADEMREV); } /* Check for Cirrus CL-PD67xx chips */ i365_set(0, PD67_CHIP_INFO, 0); val = i365_get(0, PD67_CHIP_INFO); if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) { val = i365_get(0, PD67_CHIP_INFO); if ((val & PD67_INFO_CHIP_ID) == 0) { if (val & PD67_INFO_SLOTS) name = "Cirrus CL-PD672x"; else { name = "Cirrus CL-PD6710"; sock = 1; } } } #ifdef MSF_COMMENTED_ME_OUT if (module) printf("i82365\n"); else printf("%s found, %d sockets.\n", name, sock); #endif return "i82365"; } /* i365_probe */ /*====================================================================*/ static u_char tcic_getb(u_long base, u_char reg) { u_char val = inb(base+reg); return val; } static void tcic_setb(u_long base, u_char reg, u_char data) { outb(data, base+reg); } static u_short tcic_getw(u_long base, u_char reg) { u_short val = inw(base+reg); return val; } static void tcic_setw(u_long base, u_char reg, u_short data) { outw(data, base+reg); } static u_short tcic_aux_getw(u_long base, u_short reg) { u_char mode = (tcic_getb(base, TCIC_MODE) & TCIC_MODE_PGMMASK) | reg; tcic_setb(base, TCIC_MODE, mode); return tcic_getw(base, TCIC_AUX); } static void tcic_aux_setw(u_long base, u_short reg, u_short data) { u_char mode = (tcic_getb(base, TCIC_MODE) & TCIC_MODE_PGMMASK) | reg; tcic_setb(base, TCIC_MODE, mode); tcic_setw(base, TCIC_AUX, data); } static int get_tcic_id(u_long base) { u_short id; tcic_aux_setw(base, TCIC_AUX_TEST, TCIC_TEST_DIAG); id = tcic_aux_getw(base, TCIC_AUX_ILOCK); id = (id & TCIC_ILOCKTEST_ID_MASK) >> TCIC_ILOCKTEST_ID_SH; tcic_aux_setw(base, TCIC_AUX_TEST, 0); return id; } int tcic_probe_at(u_long base, int module) { int i; u_short old; /* Anything there?? */ for (i = 0; i < 0x10; i += 2) if (tcic_getw(base, i) == 0xffff) return -1; if (!module) printf(" at %#3.3lx: ", base); fflush(stdout); /* Try to reset the chip */ tcic_setw(base, TCIC_SCTRL, TCIC_SCTRL_RESET); tcic_setw(base, TCIC_SCTRL, 0); /* Can we set the addr register? */ old = tcic_getw(base, TCIC_ADDR); tcic_setw(base, TCIC_ADDR, 0); if (tcic_getw(base, TCIC_ADDR) != 0) { tcic_setw(base, TCIC_ADDR, old); return -2; } tcic_setw(base, TCIC_ADDR, 0xc3a5); if (tcic_getw(base, TCIC_ADDR) != 0xc3a5) return -3; return 2; } char *tcic_probe(int verbose, int module, u_long base) { int sock; #ifdef MSF_COMMENTED_ME_OUT if (!module) printf("Databook TCIC-2 probe: "); fflush(stdout); #endif ioperm(base, 16, 1); ioperm(0x80, 1, 1); sock = tcic_probe_at(base, module); if (sock <= 0) { #ifdef MSF_COMMENTED_ME_OUT if (!module) printf("not found.\n"); #endif return NULL; } #ifdef MSF_COMMENTED_ME_OUT if (module) printf("tcic\n"); else { id = get_tcic_id(base); switch (id) { case TCIC_ID_DB86082: printf("DB86082"); break; case TCIC_ID_DB86082A: printf("DB86082A"); break; case TCIC_ID_DB86084: printf("DB86084"); break; case TCIC_ID_DB86084A: printf("DB86084A"); break; case TCIC_ID_DB86072: printf("DB86072"); break; case TCIC_ID_DB86184: printf("DB86184"); break; case TCIC_ID_DB86082B: printf("DB86082B"); break; default: printf("Unknown TCIC-2 ID 0x%02x", id); } printf(" found at %#6lx, %d sockets.\n", base, sock); } #endif return "TCIC"; } /* tcic_probe */ /*====================================================================*/ /* returns char * pointing at a CONSTANT string, so dont free it! */ /* NULL means nothing found */ char *pcmciaProbeController( void ) { int verbose = 0, module = 0; u_long tcic_base = TCIC_BASE; char *result; #ifdef CONFIG_PCI if (pci_probe(verbose, module) == 0) exit(EXIT_SUCCESS); else #endif if ((result=i365_probe(verbose, module)) != NULL) return result; else if ((result=tcic_probe(verbose, module, tcic_base)) != NULL) return result; else return NULL; } #ifdef TESTING void main() { char *r; r=pcmciaProbeController(); if (r != NULL) printf("Type is -> %s\n", r); else printf("None found\n"); exit(0); } #endif