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

📄 i82365.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        status = i365_get(sock, I365_STATUS);    *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)	? SS_DETECT : 0;	    if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)	*value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;    else {	*value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;	*value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;    }    *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;    *value |= (status & I365_CS_READY) ? SS_READY : 0;    *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;    if (socket[sock].type == IS_VG469) {	status = i365_get(sock, VG469_VSENSE);	if (socket[sock].psock & 1) {	    *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD;	    *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD;	} else {	    *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD;	    *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;	}    }        debug(1, "GetStatus(%d) = %#4.4x\n", sock, *value);    return 0;} /* i365_get_status *//*====================================================================*/static int i365_set_socket(u_short sock, socket_state_t *state){    struct i82365_socket *t = &socket[sock];    u_char reg;        debug(1, "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;    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_set_io_map(u_short sock, struct pccard_io_map *io){    u_char map, ioctl;        debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "	  "%#lx-%#lx)\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_set_mem_map(u_short sock, struct pccard_mem_map *mem){    u_short base, i;    u_char map;        debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, %#llx-%#llx, "	  "%#x)\n", sock, mem->map, mem->flags, mem->speed,	  (unsigned long long)mem->res->start,	  (unsigned long long)mem->res->end, mem->card_start);    map = mem->map;    if ((map > 4) || (mem->card_start > 0x3ffffff) ||	(mem->res->start > mem->res->end) || (mem->speed > 1000))	return -EINVAL;    if ((mem->res->start > 0xffffff) || (mem->res->end > 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->res->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->res->end >> 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->res->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 */#if 0 /* driver model ordering issue *//*======================================================================    Routines for accessing socket information and register dumps via    /sys/class/pcmcia_socket/...    ======================================================================*/static ssize_t show_info(struct class_device *class_dev, char *buf){	struct i82365_socket *s = container_of(class_dev, struct i82365_socket, socket.dev);	return sprintf(buf, "type:     %s\npsock:    %d\n",		       pcic[s->type].name, s->psock);}static ssize_t show_exca(struct class_device *class_dev, char *buf){	struct i82365_socket *s = container_of(class_dev, struct i82365_socket, socket.dev);	unsigned short sock;	int i;	ssize_t ret = 0;	unsigned long flags = 0;	sock = s->number;	ISA_LOCK(sock, flags);	for (i = 0; i < 0x40; i += 4) {		ret += sprintf(buf, "%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" : " ");		buf += ret;	}	ISA_UNLOCK(sock, flags);	return ret;}static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL);static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL);#endif/*====================================================================*//* this is horribly ugly... proper locking needs to be done here at  * some time... */#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)	static int pcic_get_status(struct pcmcia_socket *s, u_int *value){	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE) {		*value = 0;		return -EINVAL;	}	LOCKED(i365_get_status(sock, value));}static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state){	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE)		return -EINVAL;	LOCKED(i365_set_socket(sock, state));}static int pcic_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io){	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE)		return -EINVAL;	LOCKED(i365_set_io_map(sock, io));}static int pcic_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem){	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE)		return -EINVAL;	LOCKED(i365_set_mem_map(sock, mem));}static int pcic_init(struct pcmcia_socket *s){	int i;	struct resource res = { .start = 0, .end = 0x1000 };	pccard_io_map io = { 0, 0, 0, 0, 1 };	pccard_mem_map mem = { .res = &res, };	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 struct pccard_operations pcic_operations = {	.init			= pcic_init,	.get_status		= pcic_get_status,	.set_socket		= pcic_set_socket,	.set_io_map		= pcic_set_io_map,	.set_mem_map		= pcic_set_mem_map,};/*====================================================================*/static struct device_driver i82365_driver = {	.name = "i82365",	.bus = &platform_bus_type,	.suspend = pcmcia_socket_dev_suspend,	.resume = pcmcia_socket_dev_resume,};static struct platform_device *i82365_device;static int __init init_i82365(void){    int i, ret;    ret = driver_register(&i82365_driver);    if (ret)	return ret;    i82365_device = platform_device_alloc("i82365", 0);    if (i82365_device) {	    ret = platform_device_add(i82365_device);	    if (ret)		    platform_device_put(i82365_device);    } else	    ret = -ENOMEM;    if (ret) {	driver_unregister(&i82365_driver);	return ret;    }    printk(KERN_INFO "Intel ISA PCIC probe: ");    sockets = 0;    isa_probe();    if (sockets == 0) {	printk("not found.\n");	platform_device_unregister(i82365_device);	release_region(i365_base, 2);	driver_unregister(&i82365_driver);	return -ENODEV;    }    /* Set up interrupt handler(s) */    if (grab_irq != 0)	request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);        /* register sockets with the pcmcia core */    for (i = 0; i < sockets; i++) {	    socket[i].socket.dev.parent = &i82365_device->dev;	    socket[i].socket.ops = &pcic_operations;	    socket[i].socket.resource_ops = &pccard_nonstatic_ops;	    socket[i].socket.owner = THIS_MODULE;	    socket[i].number = i;	    ret = pcmcia_register_socket(&socket[i].socket);	    if (!ret)		    socket[i].flags |= IS_REGISTERED;#if 0 /* driver model ordering issue */	   class_device_create_file(&socket[i].socket.dev,			   	    &class_device_attr_info);	   class_device_create_file(&socket[i].socket.dev,			   	    &class_device_attr_exca);#endif    }    /* 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;    for (i = 0; i < sockets; i++) {	    if (socket[i].flags & IS_REGISTERED)		    pcmcia_unregister_socket(&socket[i].socket);    }    platform_device_unregister(i82365_device);    if (poll_interval != 0)	del_timer_sync(&poll_timer);    if (grab_irq != 0)	free_irq(cs_irq, pcic_interrupt);    for (i = 0; i < sockets; i++) {	/* Turn off all interrupt sources! */	i365_set(i, I365_CSCINT, 0);	release_region(socket[i].ioaddr, 2);    }    release_region(i365_base, 2);#ifdef CONFIG_PNP    if (i82365_pnpdev)    		pnp_disable_dev(i82365_pnpdev);#endif    driver_unregister(&i82365_driver);} /* exit_i82365 */module_init(init_i82365);module_exit(exit_i82365);MODULE_LICENSE("Dual MPL/GPL");/*====================================================================*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -