📄 i82365.c
字号:
} if (recov_time >= 0) p->timer[2] = p->timer[5] = recov_time; buf += strlen(buf); sprintf(buf, " [%d/%d/%d] [%d/%d/%d]", p->timer[0], p->timer[1], p->timer[2], p->timer[3], p->timer[4], p->timer[5]); } return mask;}/*====================================================================== Code to save and restore global state information for Vadem VG468 and VG469 controllers, and to set and report global configuration options. ======================================================================*/#ifdef CONFIG_ISAstatic void vg46x_get_state(u_short s){ vg46x_state_t *p = &socket[s].state.vg46x; p->ctl = i365_get(s, VG468_CTL); if (socket[s].type == IS_VG469) p->ema = i365_get(s, VG469_EXT_MODE);}static void vg46x_set_state(u_short s){ vg46x_state_t *p = &socket[s].state.vg46x; i365_set(s, VG468_CTL, p->ctl); if (socket[s].type == IS_VG469) i365_set(s, VG469_EXT_MODE, p->ema);}static u_int __init vg46x_set_opts(u_short s, char *buf){ vg46x_state_t *p = &socket[s].state.vg46x; flip(p->ctl, VG468_CTL_ASYNC, async_clock); flip(p->ema, VG469_MODE_CABLE, cable_mode); if (p->ctl & VG468_CTL_ASYNC) strcat(buf, " [async]"); if (p->ctl & VG468_CTL_INPACK) strcat(buf, " [inpack]"); if (socket[s].type == IS_VG469) { u_char vsel = i365_get(s, VG469_VSELECT); if (vsel & VG469_VSEL_EXT_STAT) { strcat(buf, " [ext mode]"); if (vsel & VG469_VSEL_EXT_BUS) strcat(buf, " [isa buf]"); } if (p->ema & VG469_MODE_CABLE) strcat(buf, " [cable]"); if (p->ema & VG469_MODE_COMPAT) strcat(buf, " [c step]"); } return 0xffff;}#endif/*====================================================================== Generic routines to get and set controller options ======================================================================*/static void get_bridge_state(u_short s){ socket_info_t *t = &socket[s]; if (t->flags & IS_CIRRUS) cirrus_get_state(s);#ifdef CONFIG_ISA else if (t->flags & IS_VADEM) vg46x_get_state(s);#endif}static void set_bridge_state(u_short s){ socket_info_t *t = &socket[s]; if (t->flags & IS_CIRRUS) cirrus_set_state(s); else { i365_set(s, I365_GBLCTL, 0x00); i365_set(s, I365_GENCTL, 0x00); } i365_bflip(s, I365_INTCTL, I365_INTR_ENA, t->intr);#ifdef CONFIG_ISA if (t->flags & IS_VADEM) vg46x_set_state(s);#endif}static u_int __init set_bridge_opts(u_short s, u_short ns){ u_short i; u_int m = 0xffff; char buf[128]; for (i = s; i < s+ns; i++) { if (socket[i].flags & IS_ALIVE) { printk(KERN_INFO " host opts [%d]: already alive!\n", i); continue; } buf[0] = '\0'; get_bridge_state(i); if (socket[i].flags & IS_CIRRUS) m = cirrus_set_opts(i, buf);#ifdef CONFIG_ISA else if (socket[i].flags & IS_VADEM) m = vg46x_set_opts(i, buf);#endif set_bridge_state(i); printk(KERN_INFO " host opts [%d]:%s\n", i, (*buf) ? buf : " none"); } return m;}/*====================================================================== Interrupt testing code, for ISA and PCI interrupts ======================================================================*/#ifdef CONFIG_ISA#ifndef CONFIG_S3C2410_SMDKstatic u_int __init isa_scan(u_short sock, u_int mask0){ u_int mask1 = 0; int i;#ifdef __alpha__#define PIC 0x4d0 /* Don't probe level-triggered interrupts -- reserved for PCI */ mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));#endif if (do_scan) { set_bridge_state(sock); i365_set(sock, I365_CSCINT, 0); for (i = 0; i < 16; i++) if ((mask0 & (1 << i) )) mask1 |= (1 << i); for (i = 0; i < 16; i++) if ((mask1 & (1 << i))) mask1 ^= (1 << i); } printk(KERN_INFO " ISA irqs ("); if (mask1) { printk("scanned"); } else { /* Fallback: just find interrupts that aren't in use */ for (i = 0; i < 16; i++) if ((mask0 & (1 << i))) mask1 |= (1 << i); printk("default"); /* If scan failed, default to polled status */ if (!cs_irq && (poll_interval == 0)) poll_interval = HZ; } printk(") = "); for (i = 0; i < 16; i++) if (mask1 & (1<<i)) printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i); if (mask1 == 0) printk("none!"); return mask1;}#endif /* CONFIG_S3C2410_SMDK */#endif /* CONFIG_ISA *//*====================================================================*//* Time conversion functions */static int to_cycles(int ns){ return ns/cycle_time;}static int to_ns(int cycles){ return cycle_time*cycles;}/*====================================================================*/#ifdef CONFIG_ISAstatic int __init identify(u_short port, u_short sock){ u_char val; int type = -1; /* Use the next free entry in the socket table */ socket[sockets].ioaddr = port; socket[sockets].psock = sock; /* Wake up a sleepy Cirrus controller */ if (wakeup) { i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND); /* Pause at least 50 ms */ mdelay(50); } if ((val = i365_get(sockets, I365_IDENT)) & 0x70) { return -1; } switch (val) { case 0x82: type = IS_I82365A; break; case 0x83: type = IS_I82365B; break; case 0x84: type = IS_I82365DF; break; case 0x88: case 0x89: case 0x8a: type = IS_IBM; break; }#ifndef CONFIG_S3C2410_SMDK /* Check for Vadem VG-468 chips */ outb(0x0e, port); outb(0x37, port); i365_bset(sockets, VG468_MISC, VG468_MISC_VADEMREV); val = i365_get(sockets, I365_IDENT); if (val & I365_IDENT_VADEM) { i365_bclr(sockets, VG468_MISC, VG468_MISC_VADEMREV); type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468; } /* Check for Ricoh chips */ val = i365_get(sockets, RF5C_CHIP_ID); if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396)) type = IS_RF5Cx96;#endif /* Check for Cirrus CL-PD67xx chips */ i365_set(sockets, PD67_CHIP_INFO, 0); val = i365_get(sockets, PD67_CHIP_INFO); if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) { val = i365_get(sockets, PD67_CHIP_INFO); if ((val & PD67_INFO_CHIP_ID) == 0) { type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710; i365_set(sockets, PD67_EXT_INDEX, 0xe5); if (i365_get(sockets, PD67_EXT_INDEX) != 0xe5) type = IS_VT83C469; } } return type;} /* identify */#endif/*====================================================================== See if a card is present, powered up, in IO mode, and already bound to a (non PC Card) Linux driver. We leave these alone. We make an exception for cards that seem to be serial devices. ======================================================================*/static int __init is_alive(u_short sock){ u_char stat; u_short start, stop; stat = i365_get(sock, I365_STATUS); start = i365_get_pair(sock, I365_IO(0)+I365_W_START); stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP); if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) && (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) && (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) && (check_region(start, stop-start+1) != 0) && ((start & 0xfeef) != 0x02e8)) return 1; else return 0;}/*====================================================================*/static void __init add_socket(u_short port, int psock, int type){ socket[sockets].ioaddr = port; socket[sockets].psock = psock; socket[sockets].type = type; socket[sockets].flags = pcic[type].flags; if (is_alive(sockets)) socket[sockets].flags |= IS_ALIVE; sockets++;}static void __init add_pcic(int ns, int type){ u_int mask = 0, i, base; int use_pci = 0, isa_irq = 0; socket_info_t *t = &socket[sockets-ns]; base = sockets-ns; if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365"); if (base == 0) printk("\n"); printk(KERN_INFO " %s", pcic[type].name); printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x", t->ioaddr, t->psock*0x40); printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));#ifdef CONFIG_ISA /* Set host options, build basic interrupt mask */ if (irq_list[0] == -1) mask = irq_mask; else for (i = mask = 0; i < 16; i++) mask |= (1<<irq_list[i]);#endif mask &= I365_MASK & set_bridge_opts(base, ns);#ifdef CONFIG_ISA#ifndef CONFIG_S3C2410_SMDK /* Scan for ISA interrupts */ mask = isa_scan(base, mask);#endif#else printk(KERN_INFO " PCI card interrupts,");#endif#ifdef CONFIG_ISA /* Poll if only two interrupts available */ if (!use_pci && !poll_interval) { u_int tmp = (mask & 0xff20); tmp = tmp & (tmp-1); if ((tmp & (tmp-1)) == 0) poll_interval = HZ; } /* Only try an ISA cs_irq if this is the first controller */ if (!use_pci && !grab_irq && (cs_irq || !poll_interval)) { /* Avoid irq 12 unless it is explicitly requested */ u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12)); for (cs_irq = 15; cs_irq > 0; cs_irq--) if ((cs_mask & (1 << cs_irq))) break; if (cs_irq) { grab_irq = 1; isa_irq = cs_irq; printk(" status change on irq %d\n", cs_irq); } }#endif if (!use_pci && !isa_irq) { if (poll_interval == 0) poll_interval = HZ; printk(" polling interval = %d ms\n", poll_interval * 1000 / HZ); } /* Update socket interrupt information, capabilities */ for (i = 0; i < ns; i++) {#ifdef CONFIG_S3C2410_SMDK /* Use SS_CAP_STATIC_MAP which disables the memory resource database check and SS_CAP_PAGE_REGS which disable io port maximun limit 0xffff */ t[i].cap.features |= SS_CAP_PCCARD | SS_CAP_STATIC_MAP | SS_CAP_PAGE_REGS; /* We just pass up an offset which is applied to client-requested base I/O addresses in alloc_io_space() */ t[i].cap.io_offset = vCF_IO_BASE; /* Map Size */ t[i].cap.map_size = 0x1000; /* Do not use ISA irq */ t[i].cap.irq_mask = 0; t[i].cap.pci_irq = IRQ_CF_RDY; /* Card Detect IRQ */ t[i].cs_irq = isa_irq; /* Enable Management Interrupt for card detect */ t[i].intr = I365_INTR_ENA; /* PD6710 IRQ3 is only connected to IRQ_CF_RDY */ t[i].intr |= 3 << 0;#else t[i].cap.features |= SS_CAP_PCCARD; t[i].cap.map_size = 0x1000; t[i].cap.irq_mask = mask; t[i].cs_irq = isa_irq;#endif }} /* add_pcic *//*====================================================================*/#ifdef CONFIG_ISA#if defined(CONFIG_ISAPNP) || (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))#define I82365_ISAPNP#endif#ifdef I82365_ISAPNPstatic struct isapnp_device_id id_table[] __initdata = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x0e00), (unsigned long) "Intel 82365-Compatible" }, { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x0e01), (unsigned long) "Cirrus Logic CL-PD6720" }, { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x0e02), (unsigned long) "VLSI VL82C146" }, { 0 }};MODULE_DEVICE_TABLE(isapnp, id_table);static struct pci_dev *i82365_pnpdev;#endifstatic void __init isa_probe(void){#ifdef CONFIG_S3C2410_SMDK int i, sock, id;#else int i, j, sock, k, ns, id;#endif ioaddr_t port;#ifdef I82365_ISAPNP struct isapnp_device_id *devid; struct pci_dev *dev; for (devid = id_table; devid->vendor; devid++) { if ((dev = isapnp_find_dev(NULL, devid->vendor, devid->function, NULL))) { printk("ISAPNP "); if (dev->prepare && dev->prepare(dev) < 0) { printk("prepare failed\n"); break; } if (dev->activate && dev->activate(dev) < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -