m32r_pcc.c

来自「linux 内核源代码」· C语言 代码 · 共 772 行 · 第 1/2 页

C
772
字号
	if (j == 20)		printk(KERN_NOTICE "m32r-pcc: infinite loop in interrupt handler\n");	debug(4, "m32r-pcc: interrupt done\n");	return IRQ_RETVAL(handled);} /* pcc_interrupt */static void pcc_interrupt_wrapper(u_long data){	pcc_interrupt(0, NULL);	init_timer(&poll_timer);	poll_timer.expires = jiffies + poll_interval;	add_timer(&poll_timer);}/*====================================================================*/static int _pcc_get_status(u_short sock, u_int *value){	u_int status;	status = pcc_get(sock,PCIRC);	*value = ((status & PCIRC_CDIN1) && (status & PCIRC_CDIN2))		? SS_DETECT : 0;	status = pcc_get(sock,PCCR);#if 0	*value |= (status & PCCR_PCEN) ? SS_READY : 0;#else	*value |= SS_READY; /* XXX: always */#endif	status = pcc_get(sock,PCCSIGCR);	*value |= (status & PCCSIGCR_VEN) ? SS_POWERON : 0;	debug(3, "m32r-pcc: GetStatus(%d) = %#4.4x\n", sock, *value);	return 0;} /* _get_status *//*====================================================================*/static int _pcc_set_socket(u_short sock, socket_state_t *state){	u_long reg = 0;	debug(3, "m32r-pcc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "		  "io_irq %d, csc_mask %#2.2x)", sock, state->flags,		  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);	if (state->Vcc) {		/*		 * 5V only		 */		if (state->Vcc == 50) {			reg |= PCCSIGCR_VEN;		} else {			return -EINVAL;		}	}	if (state->flags & SS_RESET) {		debug(3, ":RESET\n");		reg |= PCCSIGCR_CRST;	}	if (state->flags & SS_OUTPUT_ENA){		debug(3, ":OUTPUT_ENA\n");		/* bit clear */	} else {		reg |= PCCSIGCR_SEN;	}	pcc_set(sock,PCCSIGCR,reg);#ifdef DEBUG	if(state->flags & SS_IOCARD){		debug(3, ":IOCARD");	}	if (state->flags & SS_PWR_AUTO) {		debug(3, ":PWR_AUTO");	}	if (state->csc_mask & SS_DETECT)		debug(3, ":csc-SS_DETECT");	if (state->flags & SS_IOCARD) {		if (state->csc_mask & SS_STSCHG)			debug(3, ":STSCHG");	} else {		if (state->csc_mask & SS_BATDEAD)			debug(3, ":BATDEAD");		if (state->csc_mask & SS_BATWARN)			debug(3, ":BATWARN");		if (state->csc_mask & SS_READY)			debug(3, ":READY");	}	debug(3, "\n");#endif	return 0;} /* _set_socket *//*====================================================================*/static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io){	u_char map;	debug(3, "m32r-pcc: SetIOMap(%d, %d, %#2.2x, %d ns, "		  "%#lx-%#lx)\n", sock, io->map, io->flags,		  io->speed, io->start, io->stop);	map = io->map;	return 0;} /* _set_io_map *//*====================================================================*/static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem){	u_char map = mem->map;	u_long mode;	u_long addr;	pcc_socket_t *t = &socket[sock];#ifdef CHAOS_PCC_DEBUG#if 0	pcc_as_t last = t->current_space;#endif#endif	debug(3, "m32r-pcc: SetMemMap(%d, %d, %#2.2x, %d ns, "		 "%#lx,  %#x)\n", sock, map, mem->flags,		 mem->speed, mem->static_start, mem->card_start);	/*	 * sanity check	 */	if ((map > MAX_WIN) || (mem->card_start > 0x3ffffff)){		return -EINVAL;	}	/*	 * de-activate	 */	if ((mem->flags & MAP_ACTIVE) == 0) {		t->current_space = as_none;		return 0;	}	/*	 * Disable first	 */	pcc_set(sock, PCCR, 0);	/*	 * Set mode	 */	if (mem->flags & MAP_ATTRIB) {		mode = PCMOD_AS_ATTRIB | PCMOD_CBSZ;		t->current_space = as_attr;	} else {		mode = 0; /* common memory */		t->current_space = as_comm;	}	pcc_set(sock, PCMOD, mode);	/*	 * Set address	 */	addr = t->mapaddr + (mem->card_start & M32R_PCC_MAPMASK);	pcc_set(sock, PCADR, addr);	mem->static_start = addr + mem->card_start;	/*	 * Enable again	 */	pcc_set(sock, PCCR, 1);#ifdef CHAOS_PCC_DEBUG#if 0	if (last != as_attr) {#else	if (1) {#endif		dummy_readbuf = *(u_char *)(addr + KSEG1);	}#endif	return 0;} /* _set_mem_map */#if 0 /* driver model ordering issue *//*======================================================================	Routines for accessing socket information and register dumps via	/proc/bus/pccard/...======================================================================*/static ssize_t show_info(struct class_device *class_dev, char *buf){	pcc_socket_t *s = container_of(class_dev, struct pcc_socket,		socket.dev);	return sprintf(buf, "type:     %s\nbase addr:    0x%08lx\n",		pcc[s->type].name, s->base);}static ssize_t show_exca(struct class_device *class_dev, char *buf){	/* FIXME */	return 0;}static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL);static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, 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(&pcc_lock, flags);		\	retval = x;					\	spin_unlock_irqrestore(&pcc_lock, flags);	\	return retval;					\} while (0)static int pcc_get_status(struct pcmcia_socket *s, u_int *value){	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE) {		*value = 0;		return -EINVAL;	}	LOCKED(_pcc_get_status(sock, value));}static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state){	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE)		return -EINVAL;	LOCKED(_pcc_set_socket(sock, state));}static int pcc_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io){	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE)		return -EINVAL;	LOCKED(_pcc_set_io_map(sock, io));}static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem){	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE)		return -EINVAL;	LOCKED(_pcc_set_mem_map(sock, mem));}static int pcc_init(struct pcmcia_socket *s){	debug(4, "m32r-pcc: init call\n");	return 0;}static struct pccard_operations pcc_operations = {	.init			= pcc_init,	.get_status		= pcc_get_status,	.set_socket		= pcc_set_socket,	.set_io_map		= pcc_set_io_map,	.set_mem_map		= pcc_set_mem_map,};/*====================================================================*/static struct device_driver pcc_driver = {	.name = "pcc",	.bus = &platform_bus_type,	.suspend = pcmcia_socket_dev_suspend,	.resume = pcmcia_socket_dev_resume,};static struct platform_device pcc_device = {	.name = "pcc",	.id = 0,};/*====================================================================*/static int __init init_m32r_pcc(void){	int i, ret;	ret = driver_register(&pcc_driver);	if (ret)		return ret;	ret = platform_device_register(&pcc_device);	if (ret){		driver_unregister(&pcc_driver);		return ret;	}	printk(KERN_INFO "m32r PCC probe:\n");	pcc_sockets = 0;	add_pcc_socket(M32R_PCC0_BASE, PCC0_IRQ, M32R_PCC0_MAPBASE, 0x1000);#ifdef CONFIG_M32RPCC_SLOT2	add_pcc_socket(M32R_PCC1_BASE, PCC1_IRQ, M32R_PCC1_MAPBASE, 0x2000);#endif	if (pcc_sockets == 0) {		printk("socket is not found.\n");		platform_device_unregister(&pcc_device);		driver_unregister(&pcc_driver);		return -ENODEV;	}	/* Set up interrupt handler(s) */	for (i = 0 ; i < pcc_sockets ; i++) {		socket[i].socket.dev.parent = &pcc_device.dev;		socket[i].socket.ops = &pcc_operations;		socket[i].socket.resource_ops = &pccard_static_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 = pcc_interrupt_wrapper;		poll_timer.data = 0;		init_timer(&poll_timer);		poll_timer.expires = jiffies + poll_interval;		add_timer(&poll_timer);	}	return 0;} /* init_m32r_pcc */static void __exit exit_m32r_pcc(void){	int i;	for (i = 0; i < pcc_sockets; i++)		if (socket[i].flags & IS_REGISTERED)			pcmcia_unregister_socket(&socket[i].socket);	platform_device_unregister(&pcc_device);	if (poll_interval != 0)		del_timer_sync(&poll_timer);	driver_unregister(&pcc_driver);} /* exit_m32r_pcc */module_init(init_m32r_pcc);module_exit(exit_m32r_pcc);MODULE_LICENSE("Dual MPL/GPL");/*====================================================================*/

⌨️ 快捷键说明

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