⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i82365.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* 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 + -