i82092.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 809 行 · 第 1/2 页

C
809
字号
{	enter("set_bridge_state");	indirect_write(sock, I365_GBLCTL,0x00);	indirect_write(sock, I365_GENCTL,0x00);		indirect_setbit(sock, I365_INTCTL,0x08);	leave("set_bridge_state");}      static int i82092aa_init(struct pcmcia_socket *sock){	int i;	struct resource res = { .start = 0, .end = 0x0fff };        pccard_io_map io = { 0, 0, 0, 0, 1 };	pccard_mem_map mem = { .res = &res, };                enter("i82092aa_init");                                for (i = 0; i < 2; i++) {        	io.map = i;                i82092aa_set_io_map(sock, &io);	}        for (i = 0; i < 5; i++) {        	mem.map = i;                i82092aa_set_mem_map(sock, &mem);	}		leave("i82092aa_init");	return 0;}                                                                                                                                                                                                                                              static int i82092aa_suspend(struct pcmcia_socket *sock){	int retval;	enter("i82092aa_suspend");        retval =  i82092aa_set_socket(sock, &dead_socket);        leave("i82092aa_suspend");        return retval;}       static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value){	unsigned int sock = container_of(socket, struct socket_info, socket)->number;	unsigned int status;		enter("i82092aa_get_status");		status = indirect_read(sock,I365_STATUS); /* Interface Status Register */	*value = 0;		if ((status & I365_CS_DETECT) == I365_CS_DETECT) {		*value |= SS_DETECT;	}			/* IO cards have a different meaning of bits 0,1 */	/* Also notice the inverse-logic on the bits */	 if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD)	{	 	/* IO card */	 	if (!(status & I365_CS_STSCHG))	 		*value |= SS_STSCHG;	 } else { /* non I/O card */	 	if (!(status & I365_CS_BVD1))	 		*value |= SS_BATDEAD;	 	if (!(status & I365_CS_BVD2))	 		*value |= SS_BATWARN;	 			 }	 	 if (status & I365_CS_WRPROT)	 	(*value) |= SS_WRPROT;	/* card is write protected */	 	 if (status & I365_CS_READY)	 	(*value) |= SS_READY;    /* card is not busy */	 		 if (status & I365_CS_POWERON)	 	(*value) |= SS_POWERON;  /* power is applied to the card */	leave("i82092aa_get_status");	return 0;}static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state) {	unsigned int sock = container_of(socket, struct socket_info, socket)->number;	unsigned char reg,vcc,vpp;		enter("i82092aa_get_socket");	state->flags    = 0;	state->Vcc      = 0;	state->Vpp      = 0;	state->io_irq   = 0;	state->csc_mask = 0;	/* First the power status of the socket */	reg = indirect_read(sock,I365_POWER); /* PCTRL - Power Control Register */	if (reg & I365_PWR_AUTO)		state->flags |= SS_PWR_AUTO;  /* Automatic Power Switch */			if (reg & I365_PWR_OUT)		state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */			vcc = reg & I365_VCC_MASK;    vpp = reg & I365_VPP1_MASK;		if (reg & I365_VCC_5V) { /* Can still be 3.3V, in this case the Vcc value will be overwritten later */		state->Vcc = 50;				if (vpp == I365_VPP1_5V)			state->Vpp = 50;		if (vpp == I365_VPP1_12V)			state->Vpp = 120;				}		if ((reg & I365_VCC_3V)==I365_VCC_3V)		state->Vcc = 33;			/* Now the IO card, RESET flags and IO interrupt */		reg = indirect_read(sock, I365_INTCTL); /* IGENC, Interrupt and General Control */		if ((reg & I365_PC_RESET)==0)		state->flags |= SS_RESET;	if (reg & I365_PC_IOCARD) 		state->flags |= SS_IOCARD; /* This is an IO card */		/* Set the IRQ number */	if (sockets[sock].dev!=NULL)		state->io_irq = sockets[sock].dev->irq;		/* Card status change */	reg = indirect_read(sock, I365_CSCINT); /* CSCICR, Card Status Change Interrupt Configuration */		if (reg & I365_CSC_DETECT) 		state->csc_mask |= SS_DETECT; /* Card detect is enabled */		if (state->flags & SS_IOCARD) {/* IO Cards behave different */		if (reg & I365_CSC_STSCHG)			state->csc_mask |= SS_STSCHG;	} else {		if (reg & I365_CSC_BVD1) 			state->csc_mask |= SS_BATDEAD;		if (reg & I365_CSC_BVD2) 			state->csc_mask |= SS_BATWARN;		if (reg & I365_CSC_READY) 			state->csc_mask |= SS_READY;	}			leave("i82092aa_get_socket");	return 0;}static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state) {	unsigned int sock = container_of(socket, struct socket_info, socket)->number;	unsigned char reg;		enter("i82092aa_set_socket");		/* First, set the global controller options */		set_bridge_state(sock);		/* Values for the IGENC register */		reg = 0;	if (!(state->flags & SS_RESET)) 	/* The reset bit has "inverse" logic */		reg = reg | I365_PC_RESET;  	if (state->flags & SS_IOCARD) 		reg = reg | I365_PC_IOCARD;			indirect_write(sock,I365_INTCTL,reg); /* IGENC, Interrupt and General Control Register */		/* Power registers */		reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */		if (state->flags & SS_PWR_AUTO) {		printk("Auto power\n");		reg |= I365_PWR_AUTO;	/* automatic power mngmnt */	}	if (state->flags & SS_OUTPUT_ENA) {		printk("Power Enabled \n");		reg |= I365_PWR_OUT;	/* enable power */	}		switch (state->Vcc) {		case 0:				break;		case 50: 			printk("setting voltage to Vcc to 5V on socket %i\n",sock);			reg |= I365_VCC_5V;			break;		default:			printk("i82092aa: i82092aa_set_socket called with invalid VCC power value: %i ", state->Vcc);			leave("i82092aa_set_socket");			return -EINVAL;	}			switch (state->Vpp) {		case 0:				printk("not setting Vpp on socket %i\n",sock);			break;		case 50: 			printk("setting Vpp to 5.0 for socket %i\n",sock);			reg |= I365_VPP1_5V | I365_VPP2_5V;			break;		case 120: 			printk("setting Vpp to 12.0\n");			reg |= I365_VPP1_12V | I365_VPP2_12V;			break;		default:			printk("i82092aa: i82092aa_set_socket called with invalid VPP power value: %i ", state->Vcc);			leave("i82092aa_set_socket");			return -EINVAL;	}		if (reg != indirect_read(sock,I365_POWER)) /* only write if changed */		indirect_write(sock,I365_POWER,reg);			/* Enable specific interrupt events */		reg = 0x00;	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; 		                        	}		/* now write the value and clear the (probably bogus) pending stuff by doing a dummy read*/		indirect_write(sock,I365_CSCINT,reg);	(void)indirect_read(sock,I365_CSC);	leave("i82092aa_set_socket");	return 0;}static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io){	unsigned int sock = container_of(socket, struct socket_info, socket)->number;	unsigned char map, ioctl;		enter("i82092aa_set_io_map");		map = io->map;		/* Check error conditions */		if (map > 1) {		leave("i82092aa_set_io_map with invalid map");		return -EINVAL;	}	if ((io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)){		leave("i82092aa_set_io_map with invalid io");		return -EINVAL;	}	/* Turn off the window before changing anything */ 	if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map))		indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map));/*	printk("set_io_map: Setting range to %x - %x \n",io->start,io->stop);  */		/* write the new values */	indirect_write16(sock,I365_IO(map)+I365_W_START,io->start);            		indirect_write16(sock,I365_IO(map)+I365_W_STOP,io->stop);            		            		ioctl = indirect_read(sock,I365_IOCTL) & ~I365_IOCTL_MASK(map);		if (io->flags & (MAP_16BIT|MAP_AUTOSZ))		ioctl |= I365_IOCTL_16BIT(map);			indirect_write(sock,I365_IOCTL,ioctl);		/* Turn the window back on if needed */	if (io->flags & MAP_ACTIVE)		indirect_setbit(sock,I365_ADDRWIN,I365_ENA_IO(map));				leave("i82092aa_set_io_map");		return 0;}static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem){	struct socket_info *sock_info = container_of(socket, struct socket_info, socket);	unsigned int sock = sock_info->number;	struct pci_bus_region region;	unsigned short base, i;	unsigned char map;		enter("i82092aa_set_mem_map");	pcibios_resource_to_bus(sock_info->dev, &region, mem->res);		map = mem->map;	if (map > 4) {		leave("i82092aa_set_mem_map: invalid map");		return -EINVAL;	}			if ( (mem->card_start > 0x3ffffff) || (region.start > region.end) ||	     (mem->speed > 1000) ) {		leave("i82092aa_set_mem_map: invalid address / speed");		printk("invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,region.start, region.end, mem->card_start);		return -EINVAL;	}		/* Turn off the window before changing anything */	if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map))	              indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));	                 	                 /* 	printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, region.start,region.end,sock,mem->speed,mem->flags & MAP_ACTIVE);  */	/* write the start address */	base = I365_MEM(map);	i = (region.start >> 12) & 0x0fff;	if (mem->flags & MAP_16BIT) 		i |= I365_MEM_16BIT;	if (mem->flags & MAP_0WS)		i |= I365_MEM_0WS;		indirect_write16(sock,base+I365_W_START,i);		               	/* write the stop address */		i= (region.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;	}		indirect_write16(sock,base+I365_W_STOP,i);		/* card start */		i = ((mem->card_start - region.start) >> 12) & 0x3fff;	if (mem->flags & MAP_WRPROT)		i |= I365_MEM_WRPROT;	if (mem->flags & MAP_ATTRIB) {/*		printk("requesting attribute memory for socket %i\n",sock);*/		i |= I365_MEM_REG;	} else {/*		printk("requesting normal memory for socket %i\n",sock);*/	}	indirect_write16(sock,base+I365_W_OFF,i);		/* Enable the window if necessary */	if (mem->flags & MAP_ACTIVE)		indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));	            	leave("i82092aa_set_mem_map");	return 0;}static int i82092aa_module_init(void){	enter("i82092aa_module_init");	pci_register_driver(&i82092aa_pci_drv);	leave("i82092aa_module_init");	return 0;}static void i82092aa_module_exit(void){	enter("i82092aa_module_exit");	pci_unregister_driver(&i82092aa_pci_drv);	if (sockets[0].io_base>0)			 release_region(sockets[0].io_base, 2);	leave("i82092aa_module_exit");}module_init(i82092aa_module_init);module_exit(i82092aa_module_exit);

⌨️ 快捷键说明

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