📄 i82365.c
字号:
/* Card status change mask */ reg = i365_get(sock, I365_CSCINT); state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0; if (state->flags & SS_IOCARD) state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0; else { state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0; state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0; state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0; } DEBUG(1, "i82365: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, " "io_irq %d, csc_mask %#2.2x\n", sock, state->flags, state->Vcc, state->Vpp, state->io_irq, state->csc_mask); return 0;} /* i365_get_socket *//*====================================================================*/static int i365_set_socket(u_short sock, socket_state_t *state){ socket_info_t *t = &socket[sock]; u_char reg; DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags, state->Vcc, state->Vpp, state->io_irq, state->csc_mask); /* First set global controller options */ set_bridge_state(sock); /* IO card, RESET flag, IO interrupt */ reg = t->intr; if (state->io_irq != t->cap.pci_irq) reg |= state->io_irq; reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; i365_set(sock, I365_INTCTL, reg); reg = I365_PWR_NORESET; if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO; if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT; if (t->flags & IS_CIRRUS) { if (state->Vpp != 0) { if (state->Vpp == 120) reg |= I365_VPP1_12V; else if (state->Vpp == state->Vcc) reg |= I365_VPP1_5V; else return -EINVAL; } if (state->Vcc != 0) { reg |= I365_VCC_5V; if (state->Vcc == 33) i365_bset(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); else if (state->Vcc == 50) i365_bclr(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); else return -EINVAL; } } else if (t->flags & IS_VG_PWR) { if (state->Vpp != 0) { if (state->Vpp == 120) reg |= I365_VPP1_12V; else if (state->Vpp == state->Vcc) reg |= I365_VPP1_5V; else return -EINVAL; } if (state->Vcc != 0) { reg |= I365_VCC_5V; if (state->Vcc == 33) i365_bset(sock, VG469_VSELECT, VG469_VSEL_VCC); else if (state->Vcc == 50) i365_bclr(sock, VG469_VSELECT, VG469_VSEL_VCC); else return -EINVAL; } } else if (t->flags & IS_DF_PWR) { switch (state->Vcc) { case 0: break; case 33: reg |= I365_VCC_3V; break; case 50: reg |= I365_VCC_5V; break; default: return -EINVAL; } switch (state->Vpp) { case 0: break; case 50: reg |= I365_VPP1_5V; break; case 120: reg |= I365_VPP1_12V; break; default: return -EINVAL; } } else { switch (state->Vcc) { case 0: break; case 50: reg |= I365_VCC_5V; break; default: return -EINVAL; } switch (state->Vpp) { case 0: break; case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break; case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break; default: return -EINVAL; } } if (reg != i365_get(sock, I365_POWER)) i365_set(sock, I365_POWER, reg); /* Chipset-specific functions */ if (t->flags & IS_CIRRUS) { /* Speaker control */ i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA, state->flags & SS_SPKR_ENA); } /* Card status change interrupt mask */ reg = t->cs_irq << 4; if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT; if (state->flags & SS_IOCARD) { if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG; } else { if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1; if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2; if (state->csc_mask & SS_READY) reg |= I365_CSC_READY; } i365_set(sock, I365_CSCINT, reg); i365_get(sock, I365_CSC); return 0;} /* i365_set_socket *//*====================================================================*/static int i365_get_io_map(u_short sock, struct pccard_io_map *io){ u_char map, ioctl, addr; map = io->map; if (map > 1) return -EINVAL; io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START); io->stop = i365_get_pair(sock, I365_IO(map)+I365_W_STOP); ioctl = i365_get(sock, I365_IOCTL); addr = i365_get(sock, I365_ADDRWIN); io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0; io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0; io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0; io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0; DEBUG(1, "i82365: GetIOMap(%d, %d) = %#2.2x, %d ns, " "%#4.4x-%#4.4x\n", sock, map, io->flags, io->speed, io->start, io->stop); return 0;} /* i365_get_io_map *//*====================================================================*/static int i365_set_io_map(u_short sock, struct pccard_io_map *io){ u_char map, ioctl; DEBUG(1, "i82365: SetIOMap(%d, %d, %#2.2x, %d ns, " "%#4.4x-%#4.4x)\n", sock, io->map, io->flags, io->speed, io->start, io->stop); map = io->map; if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)) return -EINVAL; /* Turn off the window before changing anything */ if (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(map)) i365_bclr(sock, I365_ADDRWIN, I365_ENA_IO(map)); i365_set_pair(sock, I365_IO(map)+I365_W_START, io->start); i365_set_pair(sock, I365_IO(map)+I365_W_STOP, io->stop); ioctl = i365_get(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map); if (io->speed) ioctl |= I365_IOCTL_WAIT(map); if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); i365_set(sock, I365_IOCTL, ioctl); /* Turn on the window if necessary */ if (io->flags & MAP_ACTIVE) i365_bset(sock, I365_ADDRWIN, I365_ENA_IO(map)); return 0;} /* i365_set_io_map *//*====================================================================*/static int i365_get_mem_map(u_short sock, struct pccard_mem_map *mem){ u_short base, i; u_char map, addr; map = mem->map; if (map > 4) return -EINVAL; addr = i365_get(sock, I365_ADDRWIN); mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0; base = I365_MEM(map); i = i365_get_pair(sock, base+I365_W_START); mem->flags |= (i & I365_MEM_16BIT) ? MAP_16BIT : 0; mem->flags |= (i & I365_MEM_0WS) ? MAP_0WS : 0; mem->sys_start += ((u_long)(i & 0x0fff) << 12); i = i365_get_pair(sock, base+I365_W_STOP); mem->speed = (i & I365_MEM_WS0) ? 1 : 0; mem->speed += (i & I365_MEM_WS1) ? 2 : 0; mem->speed = to_ns(mem->speed); mem->sys_stop = ((u_long)(i & 0x0fff) << 12) + 0x0fff; i = i365_get_pair(sock, base+I365_W_OFF); mem->flags |= (i & I365_MEM_WRPROT) ? MAP_WRPROT : 0; mem->flags |= (i & I365_MEM_REG) ? MAP_ATTRIB : 0; mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start; mem->card_start &= 0x3ffffff; DEBUG(1, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5." "5lx, %#5.5x\n", sock, mem->map, mem->flags, mem->speed, mem->sys_start, mem->sys_stop, mem->card_start); return 0;} /* i365_get_mem_map *//*====================================================================*/ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem){ u_short base, i; u_char map; DEBUG(1, "i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5" "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed, mem->sys_start, mem->sys_stop, mem->card_start); map = mem->map; if ((map > 4) || (mem->card_start > 0x3ffffff) || (mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) return -EINVAL; if (!(socket[sock].flags & IS_PCI) && ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff))) return -EINVAL; /* Turn off the window before changing anything */ if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map)) i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map)); base = I365_MEM(map); i = (mem->sys_start >> 12) & 0x0fff; if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT; if (mem->flags & MAP_0WS) i |= I365_MEM_0WS; i365_set_pair(sock, base+I365_W_START, i); i = (mem->sys_stop >> 12) & 0x0fff; switch (to_cycles(mem->speed)) { case 0: break; case 1: i |= I365_MEM_WS0; break; case 2: i |= I365_MEM_WS1; break; default: i |= I365_MEM_WS1 | I365_MEM_WS0; break; } i365_set_pair(sock, base+I365_W_STOP, i); i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT; if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG; i365_set_pair(sock, base+I365_W_OFF, i); /* Turn on the window if necessary */ if (mem->flags & MAP_ACTIVE) i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map)); return 0;} /* i365_set_mem_map *//*====================================================================== Routines for accessing socket information and register dumps via /proc/bus/pccard/... ======================================================================*/#ifdef CONFIG_PROC_FSstatic int proc_read_info(char *buf, char **start, off_t pos, int count, int *eof, void *data){ socket_info_t *s = data; char *p = buf; p += sprintf(p, "type: %s\npsock: %d\n", pcic[s->type].name, s->psock); return (p - buf);}static int proc_read_exca(char *buf, char **start, off_t pos, int count, int *eof, void *data){ u_short sock = (socket_info_t *)data - socket; char *p = buf; int i, top; #ifdef CONFIG_ISA u_long flags = 0;#endif ISA_LOCK(sock, flags); top = 0x40; for (i = 0; i < top; i += 4) { if (i == 0x50) { p += sprintf(p, "\n"); i = 0x100; } p += sprintf(p, "%02x %02x %02x %02x%s", i365_get(sock,i), i365_get(sock,i+1), i365_get(sock,i+2), i365_get(sock,i+3), ((i % 16) == 12) ? "\n" : " "); } ISA_UNLOCK(sock, flags); return (p - buf);}static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base){ socket_info_t *s = &socket[sock]; if (s->flags & IS_ALIVE) return; create_proc_read_entry("info", 0, base, proc_read_info, s); create_proc_read_entry("exca", 0, base, proc_read_exca, s); s->proc = base;}static void pcic_proc_remove(u_short sock){ struct proc_dir_entry *base = socket[sock].proc; if (base == NULL) return; remove_proc_entry("info", base); remove_proc_entry("exca", base);}#else#define pcic_proc_setup NULL#endif /* CONFIG_PROC_FS *//*====================================================================*//* * The locking is rather broken. Why do we only lock for ISA, not for * all other cases? If there are reasons to lock, we should lock. Not * this silly conditional. * * Plan: make it bug-for-bug compatible with the old stuff, and clean * it up when the infrastructure is done. */#ifdef CONFIG_ISA#define LOCKED(x) do { \ int retval; \ unsigned long flags; \ spin_lock_irqsave(&isa_lock, flags); \ retval = x; \ spin_unlock_irqrestore(&isa_lock, flags); \ return retval; \} while (0)#else#define LOCKED(x) return x#endif static int pcic_get_status(unsigned int sock, u_int *value){ if (socket[sock].flags & IS_ALIVE) { *value = 0; return -EINVAL; } LOCKED(i365_get_status(sock, value));}static int pcic_get_socket(unsigned int sock, socket_state_t *state){ if (socket[sock].flags & IS_ALIVE) return -EINVAL; LOCKED(i365_get_socket(sock, state));}static int pcic_set_socket(unsigned int sock, socket_state_t *state){ if (socket[sock].flags & IS_ALIVE) return -EINVAL; LOCKED(i365_set_socket(sock, state));}static int pcic_get_io_map(unsigned int sock, struct pccard_io_map *io){ if (socket[sock].flags & IS_ALIVE) return -EINVAL; LOCKED(i365_get_io_map(sock, io));}static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io){ if (socket[sock].flags & IS_ALIVE) return -EINVAL; LOCKED(i365_set_io_map(sock, io));}static int pcic_get_mem_map(unsigned int sock, struct pccard_mem_map *mem){ if (socket[sock].flags & IS_ALIVE) return -EINVAL; LOCKED(i365_get_mem_map(sock, mem));}static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem){ if (socket[sock].flags & IS_ALIVE) return -EINVAL; LOCKED(i365_set_mem_map(sock, mem));}static int pcic_init(unsigned int s){ int i; pccard_io_map io = { 0, 0, 0, 0, 1 }; pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 }; mem.sys_stop = 0x1000; pcic_set_socket(s, &dead_socket); for (i = 0; i < 2; i++) { io.map = i; pcic_set_io_map(s, &io); } for (i = 0; i < 5; i++) { mem.map = i; pcic_set_mem_map(s, &mem); } return 0;}static int pcic_suspend(unsigned int sock){ return pcic_set_socket(sock, &dead_socket);}static struct pccard_operations pcic_operations = { pcic_init, pcic_suspend, pcic_register_callback, pcic_inquire_socket, pcic_get_status, pcic_get_socket, pcic_set_socket, pcic_get_io_map, pcic_set_io_map, pcic_get_mem_map, pcic_set_mem_map, pcic_proc_setup};/*====================================================================*/static int __init init_i82365(void){ servinfo_t serv; pcmcia_get_card_services_info(&serv); if (serv.Revision != CS_RELEASE_CODE) { printk(KERN_NOTICE "i82365: Card Services release " "does not match!\n"); return -1; } DEBUG(0, "%s\n", version); printk(KERN_INFO "Intel PCIC probe: "); sockets = 0;#ifdef CONFIG_ISA isa_probe();#endif if (sockets == 0) { printk("not found.\n"); return -ENODEV; } /* Set up interrupt handler(s) */#ifdef CONFIG_ISA if (grab_irq != 0) request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);#endif if (register_ss_entry(sockets, &pcic_operations) != 0) printk(KERN_NOTICE "i82365: register_ss_entry() failed\n"); /* Finally, schedule a polling interrupt */ if (poll_interval != 0) { poll_timer.function = pcic_interrupt_wrapper; poll_timer.data = 0; init_timer(&poll_timer); poll_timer.expires = jiffies + poll_interval; add_timer(&poll_timer); } return 0; } /* init_i82365 */static void __exit exit_i82365(void){ int i;#ifdef CONFIG_PROC_FS for (i = 0; i < sockets; i++) pcic_proc_remove(i);#endif unregister_ss_entry(&pcic_operations); if (poll_interval != 0) del_timer(&poll_timer);#ifdef CONFIG_ISA if (grab_irq != 0) free_irq(cs_irq, pcic_interrupt);#endif for (i = 0; i < sockets; i++) { /* Turn off all interrupt sources! */ i365_set(i, I365_CSCINT, 0); release_region(socket[i].ioaddr, 2); }} /* exit_i82365 */module_init(init_i82365);module_exit(exit_i82365);/*====================================================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -