📄 i82365.c
字号:
pci_writeb(s, TOPIC_CARD_CONTROL, p->ccr); pci_writeb(s, TOPIC_CARD_DETECT, p->cdr); pci_writel(s, TOPIC_REGISTER_CONTROL, p->rcr); i365_set(s, TOPIC_FUNCTION_CONTROL, p->fcr); state = cb_readl(s, CB_SOCKET_STATE); if (!(state & CB_SS_32BIT)) cb_writel(s, CB_SOCKET_CONTROL, 0); if (!(state & CB_SS_VSENSE)) cb_writel(s, CB_SOCKET_FORCE, CB_SF_CVSTEST);}static u_int __init topic_set_opts(socket_info_t *s, char *buf){ topic_state_t *p = &s->state.topic; p->slot |= TOPIC_SLOT_SLOTON|TOPIC_SLOT_SLOTEN; p->slot &= ~TOPIC_SLOT_ID_LOCK; p->cdr |= TOPIC_CDR_MODE_PC32; p->cdr &= ~(TOPIC_CDR_SW_DETECT); p->ccr |= TOPIC97_ICR_IRQSEL; p->fcr |= TOPIC_FCR_3V_ENA; sprintf(buf, " [slot 0x%02x] [ccr 0x%02x] [cdr 0x%02x] [rcr 0x%02x]", p->slot, p->ccr, p->cdr, p->rcr); return 0xffff;}#endif/*====================================================================== Routines to handle common CardBus options ======================================================================*//* Default settings for PCI command configuration register */#define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \ PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)#ifdef CONFIG_PCIstatic void __init cb_get_state(socket_info_t *s){ pci_readb(s, PCI_CACHE_LINE_SIZE, &s->cache); pci_readb(s, PCI_LATENCY_TIMER, &s->pci_lat); pci_readb(s, CB_LATENCY_TIMER, &s->cb_lat); pci_readb(s, CB_CARDBUS_BUS, &s->cap.cardbus); pci_readb(s, CB_SUBORD_BUS, &s->sub_bus); pci_readw(s, CB_BRIDGE_CONTROL, &s->bcr); get_pci_irq(s);}static void cb_set_state(socket_info_t *s){ pci_set_power_state(pci_find_slot(s->bus, s->devfn), 0); pci_writel(s, CB_LEGACY_MODE_BASE, 0); pci_writel(s, PCI_BASE_ADDRESS_0, s->cb_phys); pci_writew(s, PCI_COMMAND, CMD_DFLT); pci_writeb(s, PCI_CACHE_LINE_SIZE, s->cache); pci_writeb(s, PCI_LATENCY_TIMER, s->pci_lat); pci_writeb(s, CB_LATENCY_TIMER, s->cb_lat); pci_writeb(s, CB_CARDBUS_BUS, s->cap.cardbus); pci_writeb(s, CB_SUBORD_BUS, s->sub_bus); pci_writew(s, CB_BRIDGE_CONTROL, s->bcr);}static int cb_get_irq_mode(socket_info_t *s){ return (!(s->bcr & CB_BCR_ISA_IRQ));}static int cb_set_irq_mode(socket_info_t *s, int pcsc, int pint){ flip(s->bcr, CB_BCR_ISA_IRQ, !(pint)); if (s->flags & IS_CIRRUS) return cirrus_set_irq_mode(s, pcsc, pint); else if (s->flags & IS_TI) return ti113x_set_irq_mode(s, pcsc, pint); /* By default, assume that we can't do ISA status irqs */ return (!pcsc);}static void __init cb_set_opts(socket_info_t *s, char *buf){ s->bcr |= CB_BCR_WRITE_POST; /* some TI1130's seem to exhibit problems with write posting */ if (((s->type == IS_TI1130) && (s->revision == 4) && (cb_write_post < 0)) || (cb_write_post == 0)) s->bcr &= ~CB_BCR_WRITE_POST; if (s->cache == 0) s->cache = 8; if (s->pci_lat == 0) s->pci_lat = 0xa8; if (s->cb_lat == 0) s->cb_lat = 0xb0; if (s->cap.pci_irq == 0) strcat(buf, " [no pci irq]"); else sprintf(buf, " [pci irq %d]", s->cap.pci_irq); buf += strlen(buf); if (!(s->flags & IS_TOPIC)) s->cap.features |= SS_CAP_PAGE_REGS; sprintf(buf, " [lat %d/%d] [bus %d/%d]", s->pci_lat, s->cb_lat, s->cap.cardbus, s->sub_bus);}#endif/*====================================================================== Power control for Cardbus controllers: used both for 16-bit and Cardbus cards. ======================================================================*/#ifdef CONFIG_PCIstatic void cb_get_power(socket_info_t *s, socket_state_t *state){ u_int reg = cb_readl(s, CB_SOCKET_CONTROL); state->Vcc = state->Vpp = 0; switch (reg & CB_SC_VCC_MASK) { case CB_SC_VCC_3V: state->Vcc = 33; break; case CB_SC_VCC_5V: state->Vcc = 50; break; } switch (reg & CB_SC_VPP_MASK) { case CB_SC_VPP_3V: state->Vpp = 33; break; case CB_SC_VPP_5V: state->Vpp = 50; break; case CB_SC_VPP_12V: state->Vpp = 120; break; }}static int cb_set_power(socket_info_t *s, socket_state_t *state){ u_int reg = 0; /* restart card voltage detection if it seems appropriate */ if ((state->Vcc == 0) && (state->Vpp == 0) && !(cb_readl(s, CB_SOCKET_STATE) & CB_SS_VSENSE)) cb_writel(s, CB_SOCKET_FORCE, CB_SF_CVSTEST); switch (state->Vcc) { case 0: reg = 0; break; case 33: reg = CB_SC_VCC_3V; break; case 50: reg = CB_SC_VCC_5V; break; default: return -EINVAL; } switch (state->Vpp) { case 0: break; case 33: reg |= CB_SC_VPP_3V; break; case 50: reg |= CB_SC_VPP_5V; break; case 120: reg |= CB_SC_VPP_12V; break; default: return -EINVAL; } if (reg != cb_readl(s, CB_SOCKET_CONTROL)) cb_writel(s, CB_SOCKET_CONTROL, reg); return 0;}#endif/*====================================================================== Generic routines to get and set controller options ======================================================================*/static void __init get_bridge_state(socket_info_t *s){ if (s->flags & IS_CIRRUS) cirrus_get_state(s);#ifdef CONFIG_ISA else if (s->flags & IS_VADEM) vg46x_get_state(s);#endif#ifdef CONFIG_PCI else if (s->flags & IS_O2MICRO) o2micro_get_state(s); else if (s->flags & IS_TI) ti113x_get_state(s); else if (s->flags & IS_RICOH) ricoh_get_state(s); else if (s->flags & IS_TOPIC) topic_get_state(s); if (s->flags & IS_CARDBUS) cb_get_state(s);#endif}static void set_bridge_state(socket_info_t *s){#ifdef CONFIG_PCI if (s->flags & IS_CARDBUS) cb_set_state(s);#endif if (s->flags & IS_CIRRUS) { cirrus_set_state(s); } else { i365_set(s, I365_GBLCTL, 0x00); i365_set(s, I365_GENCTL, 0x00); /* Trouble: changes timing of memory operations */ /* i365_bset(s, I365_ADDRWIN, I365_ADDR_MEMCS16); */ } i365_bflip(s, I365_INTCTL, I365_INTR_ENA, s->intr);#ifdef CONFIG_ISA if (s->flags & IS_VADEM) vg46x_set_state(s);#endif#ifdef CONFIG_PCI if (s->flags & IS_O2MICRO) o2micro_set_state(s); else if (s->flags & IS_TI) ti113x_set_state(s); else if (s->flags & IS_RICOH) ricoh_set_state(s); else if (s->flags & IS_TOPIC) topic_set_state(s);#endif}static u_int __init set_bridge_opts(socket_info_t *s, u_short ns){ u_short i; u_int m = 0xffff; char buf[128]; for (i = 0; i < ns; i++) { if (s[i].flags & IS_ALIVE) { printk(KERN_INFO " host opts [%d]: already alive!\n", i); continue; } buf[0] = '\0'; get_bridge_state(s+i); if (s[i].flags & IS_CIRRUS) m = cirrus_set_opts(s+i, buf);#ifdef CONFIG_ISA else if (s[i].flags & IS_VADEM) m = vg46x_set_opts(s+i, buf);#endif#ifdef CONFIG_PCI else if (s[i].flags & IS_O2MICRO) m = o2micro_set_opts(s+i, buf); else if (s[i].flags & IS_TI) m = ti113x_set_opts(s+i, buf); else if (s[i].flags & IS_RICOH) m = ricoh_set_opts(s+i, buf); else if (s[i].flags & IS_TOPIC) m = topic_set_opts(s+i, buf); if (s[i].flags & IS_CARDBUS) cb_set_opts(s+i, buf+strlen(buf));#endif set_bridge_state(s+i); printk(KERN_INFO " host opts [%d]:%s\n", i, (*buf) ? buf : " none"); }#ifdef CONFIG_PCI m &= ~pci_irq_mask;#endif return m;}/*====================================================================== Interrupt testing code, for ISA and PCI interrupts ======================================================================*/static volatile u_int irq_hits, irq_shared;static volatile socket_info_t *irq_sock;static void irq_count(int irq, void *dev, struct pt_regs *regs){ irq_hits++; DEBUG(2, "-> hit on irq %d\n", irq); if (!irq_shared && (irq_hits > 100)) { printk(KERN_INFO " PCI irq %d seems to be wedged!\n", irq); disable_irq(irq); return; }#ifdef CONFIG_PCI if (irq_sock->flags & IS_CARDBUS) { cb_writel(irq_sock, CB_SOCKET_EVENT, -1); } else#endif i365_get((socket_info_t *)irq_sock, I365_CSC); return;}static u_int __init test_irq(socket_info_t *s, int irq, int pci){ u_char csc = (pci) ? 0 : irq;#ifdef CONFIG_PNP_BIOS extern int check_pnp_irq(int); if (!pci && check_pnp_irq(irq)) return 1;#endif DEBUG(2, " testing %s irq %d\n", pci ? "PCI" : "ISA", irq); irq_sock = s; irq_shared = irq_hits = 0; if (request_irq(irq, irq_count, 0, "scan", socket)) { irq_shared++; if (!pci || request_irq(irq, irq_count, SA_SHIRQ, "scan", socket)) return 1; } irq_hits = 0; __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/100); if (irq_hits && !irq_shared) { free_irq(irq, socket); DEBUG(2, " spurious hit!\n"); return 1; } /* Generate one interrupt */#ifdef CONFIG_PCI if (s->flags & IS_CARDBUS) { cb_writel(s, CB_SOCKET_EVENT, -1); i365_set(s, I365_CSCINT, I365_CSC_STSCHG | (csc << 4)); cb_writel(s, CB_SOCKET_EVENT, -1); cb_writel(s, CB_SOCKET_MASK, CB_SM_CSTSCHG); cb_writel(s, CB_SOCKET_FORCE, CB_SE_CSTSCHG); mdelay(1); cb_writel(s, CB_SOCKET_EVENT, -1); cb_writel(s, CB_SOCKET_MASK, 0); } else#endif { i365_set(s, I365_CSCINT, I365_CSC_DETECT | (csc << 4)); i365_bset(s, I365_GENCTL, I365_CTL_SW_IRQ); mdelay(1); } free_irq(irq, socket); /* mask all interrupts */ i365_set(s, I365_CSCINT, 0); DEBUG(2, " hits = %d\n", irq_hits); return pci ? (irq_hits == 0) : (irq_hits != 1);}#ifdef CONFIG_ISAstatic int _check_irq(int irq, int flags){#ifdef CONFIG_PNP_BIOS extern int check_pnp_irq(int); if ((flags != SA_SHIRQ) && check_pnp_irq(irq)) return -1;#endif if (request_irq(irq, irq_count, flags, "x", irq_count) != 0) return -1; free_irq(irq, irq_count); return 0;}static u_int __init isa_scan(socket_info_t *s, u_int mask0){ u_int mask1 = 0; int i;#ifdef CONFIG_PCI /* Only scan if we can select ISA csc irq's */ if (!(s->flags & IS_CARDBUS) || (cb_set_irq_mode(s, 0, 0) == 0))#endif if (do_scan) { set_bridge_state(s); i365_set(s, I365_CSCINT, 0); for (i = 0; i < 16; i++) if ((mask0 & (1 << i)) && (test_irq(s, i, 0) == 0)) mask1 |= (1 << i); for (i = 0; i < 16; i++) if ((mask1 & (1 << i)) && (test_irq(s, i, 0) != 0)) mask1 ^= (1 << i); } printk(KERN_INFO " ISA irqs ("); /* we trust TI bridges to do this right */ if (mask1 || (s->flags & IS_TI)) { printk("scanned"); } else { /* Fallback: just find interrupts that aren't in use */ for (i = 0; i < 16; i++) if ((mask0 & (1 << i)) && (_check_irq(i, 0) == 0)) 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_ISA */#ifdef CONFIG_PCIstatic int __init pci_scan(socket_info_t *s){ int ret; if ((s->flags & IS_RICOH) || !(s->flags & IS_CARDBUS) || !do_scan) { /* for PCI-to-PCMCIA bridges, just check for wedged irq */ irq_sock = s; irq_hits = 0; if (request_irq(s->cap.pci_irq, irq_count, 0, "scan", socket)) return 1; udelay(50); free_irq(s->cap.pci_irq, socket); return (!irq_hits); } cb_set_irq_mode(s, 1, 0); set_bridge_state(s); i365_set(s, I365_CSCINT, 0); ret = ((test_irq(s, s->cap.pci_irq, 1) == 0) && (test_irq(s, s->cap.pci_irq, 1) == 0)); if (!ret) printk(KERN_INFO " PCI irq %d test failed\n", s->cap.pci_irq); return ret;}#endif /* CONFIG_PCI *//*====================================================================*/#ifdef CONFIG_ISAstatic int __init isa_identify(u_short port, u_short sock){ socket_info_t *s = socket+sockets; u_char val; int type = -1; /* Use the next free entry in the socket table */ s->ioaddr = port; s->psock = sock; /* Wake up a sleepy Cirrus controller */ if (wakeup) { i365_bclr(s, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -