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

📄 m8xx_pcmcia.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 3 页
字号:
			M8XX_PCMCIA_MASK(_slot_); 		((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per 			&= ~M8XX_PCMCIA_MASK(_slot_); 		/* turn off interrupt and disable CxOE */		M8XX_PGCRX(_slot_) = M8XX_PGCRX_CXOE;		/* turn off memory windows */		for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {			w->or = 0;  /* set to not valid */			w++;		}		/* turn off voltage */		voltage_set(_slot_, 0, 0);		/* disable external hardware */			hardware_disable(_slot_);	}	free_irq(pcmcia_schlvl, NULL);}/* ------------------------------------------------------------------------- */static int __init m8xx_init(void){	servinfo_t serv;	pcmcia_win_t *w;	u_int k, m;#if (PCMCIA_SOCKETS_NO == 2)	u_int _slot_;#endif    	PCMCIA_INFO("%s\n", version);	CardServices(GetCardServicesInfo, &serv);	if (serv.Revision != CS_RELEASE_CODE) {		PCMCIA_ERROR("Card Services release does not match!\n");		return -EINVAL;	}	PCMCIA_INFO(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG 		    " with IRQ %u.\n", pcmcia_schlvl); 	/* Configure Status change interrupt */	if(request_8xxirq(pcmcia_schlvl, m8xx_interrupt, 0, 			   "m8xx_pcmcia", NULL)) {		PCMCIA_ERROR("Cannot allocate IRQ %u for SCHLVL!\n", 			     pcmcia_schlvl);		return -1;	}	w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;	for(k = 0; k < PCMCIA_SOCKETS_NO; k++) {		/* Setup internal hardware */#if (PCMCIA_SOCKETS_NO == 2)		_slot_ = socket[k].slot = k;#else		socket[k].slot = _slot_;#endif	    		((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = 			M8XX_PCMCIA_MASK(_slot_); 		((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per 			&= ~M8XX_PCMCIA_MASK(_slot_); 		/* connect interrupt and disable CxOE */		M8XX_PGCRX(_slot_) = M8XX_PGCRX_CXOE |			(mk_int_int_mask(pcmcia_schlvl) << 16);		/* intialize the fixed memory windows */		for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {			w->br = PCMCIA_MEM_WIN_BASE + 				(PCMCIA_MEM_WIN_SIZE 				 * (m + k * PCMCIA_MEM_WIN_NO));			w->or = 0;  /* set to not valid */			DEBUG(3,"Socket %u: MemWin %u: Base 0x%08x.\n",			      k, m, w->br);			w++;		}		/* turn off voltage */		voltage_set(_slot_, 0, 0);		/* Enable external hardware */	    		hardware_enable(_slot_);	}	if(register_ss_entry(PCMCIA_SOCKETS_NO, &m8xx_service) != 0) {	    PCMCIA_ERROR("register_ss_entry() failed.\n");	    m8xx_shutdown();	    return -ENODEV;	}	return 0;    }/* ------------------------------------------------------------------------- */static void __exit m8xx_exit(void){	unregister_ss_entry(&m8xx_service);	m8xx_shutdown();}/* ------------------------------------------------------------------------- */static void m8xx_interrupt(int irq, void *dev, struct pt_regs *regs){	socket_info_t *s;	event_table_t *e;	u_int events, pscr, pipr, k;#if (PCMCIA_SOCKETS_NO == 2)	u_int _slot_;#endif    	DEBUG(3,"Interrupt!\n");	/* get interrupt sources */	pscr = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr;	pipr = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr;	s = &socket[0];	for(k = 0; k < PCMCIA_SOCKETS_NO; k++) { 	    if(s->handler) {		    e = &s->events[0]; 		    events = 0;#if (PCMCIA_SOCKETS_NO == 2)		    _slot_ = s->slot;#endif    		    while(e->regbit) {			    if(pscr & e->regbit)				    events |= e->eventbit;		    			    e++;		    }		    /* 		     * report only if both card detect signals are the same 		     * not too nice done, 		     * we depend on that CD2 is the bit to the left of CD1...		     */		    if(events & SS_DETECT)			    if(((pipr & M8XX_PCMCIA_CD2(_slot_)) >> 1)				    ^ (pipr & M8XX_PCMCIA_CD1(_slot_)))				    events &= ~SS_DETECT;#ifdef PCMCIA_GLITCHY_CD		    		    /*		     * I've experienced CD problems with my ADS board.		     * We make an extra check to see if there was a		     * real change of Card detection.		     */		    if((events & SS_DETECT) && 		       ((pipr &			 (M8XX_PCMCIA_CD2(_slot_) | M8XX_PCMCIA_CD1(_slot_)))			== 0) && (s->state.Vcc | s->state.Vpp)) {			  events &= ~SS_DETECT;			  printk( "CD glitch workaround - CD = 0x%08x!\n",				(pipr & (M8XX_PCMCIA_CD2(_slot_) 					 | M8XX_PCMCIA_CD1(_slot_))));		    }#endif		    /* call the handler */		    DEBUG(3,"slot %u: events = 0x%02x, pscr = 0x%08x, "			  "pipr = 0x%08x\n", 			  _slot_, events, pscr, pipr);		    if(events)			    s->handler(s->info, events);	    }	    s++;    }    /* clear the interrupt sources */    ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr;        DEBUG(3,"Interrupt done.\n");    }/* ------------------------------------------------------------------------- */static u_int m8xx_get_graycode(u_int size){	u_int k;	for(k = 0; k < M8XX_SIZES_NO; k++)		if(m8xx_size_to_gray[k] == size)			break;	if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))		k = -1;	return k;}/* ------------------------------------------------------------------------- */static u_int m8xx_get_speed(u_int ns, u_int is_io){	u_int reg, clocks, psst, psl, psht;	if(!ns) {		/*		 * We get called with IO maps setup to 0ns		 * if not specified by the user.		 * They should be 255ns.		 */		if(is_io)			ns = 255;		else 			ns = 100;  /* fast memory if 0 */	}	/* 	 * In PSST, PSL, PSHT fields we tell the controller	 * timing parameters in CLKOUT clock cycles.	 * CLKOUT is the same as GCLK2_50.	 *//* how we want to adjust the timing - in percent */#define ADJ 180 /* 80 % longer accesstime - to be sure */	clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;	clocks = (clocks * ADJ) / (100*1000);	if(clocks >= PCMCIA_BMT_LIMIT) {		printk( "Max access time limit reached\n");		clocks = PCMCIA_BMT_LIMIT-1;	}	psst = clocks / 7;          /* setup time */	psht = clocks / 7;          /* hold time */	psl  = (clocks * 5) / 7;    /* strobe length */	psst += clocks - (psst + psht + psl);	reg =  psst << 12;	reg |= psl  << 7; 	reg |= psht << 16;	return reg;}/* ------------------------------------------------------------------------- */	static int m8xx_register_callback(u_short lsock, ss_callback_t *call){	if (call == NULL) {		socket[lsock].handler = NULL;		MOD_DEC_USE_COUNT;	} 	else {		MOD_INC_USE_COUNT;		socket[lsock].handler = call->handler;		socket[lsock].info = call->info;	}	return 0;}/* ------------------------------------------------------------------------- */static int m8xx_get_status(u_short lsock, u_int *value){	socket_info_t *s = &socket[lsock];	u_int pipr, reg;#if (PCMCIA_SOCKETS_NO == 2)	u_int _slot_ = s->slot;#endif    	pipr = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr;	*value  = ((pipr & (M8XX_PCMCIA_CD1(_slot_) 			    | M8XX_PCMCIA_CD2(_slot_))) == 0) ? SS_DETECT : 0;	*value |= (pipr & M8XX_PCMCIA_WP(_slot_)) ? SS_WRPROT : 0;	if (s->state.flags & SS_IOCARD)		*value |= (pipr & M8XX_PCMCIA_BVD1(_slot_)) ? SS_STSCHG : 0;	else {		*value |= (pipr & M8XX_PCMCIA_RDY(_slot_)) ? SS_READY : 0;		*value |= (pipr & M8XX_PCMCIA_BVD1(_slot_)) ? SS_BATDEAD : 0;		*value |= (pipr & M8XX_PCMCIA_BVD2(_slot_)) ? SS_BATWARN : 0;	}		if (s->state.Vcc | s->state.Vpp)		*value |= SS_POWERON;		/*	 * Voltage detection:	 * This driver only supports 16-Bit pc-cards.	 * Cardbus is not handled here.	 * 	 * To determine what voltage to use we must read the VS1 and VS2 pin.	 * Depending on what socket type is present,	 * different combinations mean different things.	 *	 * Card Key  Socket Key   VS1   VS2   Card         Vcc for CIS parse	 *   	 * 5V        5V, LV*      NC    NC    5V only       5V (if available)	 *           	 * 5V        5V, LV*      GND   NC    5 or 3.3V     as low as possible	 *	 * 5V        5V, LV*      GND   GND   5, 3.3, x.xV  as low as possible	 *	 * LV*       5V            -     -    shall not fit into socket	 *	 * LV*       LV*          GND   NC    3.3V only     3.3V	 *	 * LV*       LV*          NC    GND   x.xV          x.xV (if avail.)	 *	 * LV*       LV*          GND   GND   3.3 or x.xV   as low as possible	 *	 * *LV means Low Voltage	 *	 *	 * That gives us the following table:	 *	 * Socket    VS1  VS2   Voltage	 *	 * 5V        NC   NC    5V	 * 5V        NC   GND   none (should not be possible)	 * 5V        GND  NC    >= 3.3V	 * 5V        GND  GND   >= x.xV 	 *	 * LV        NC   NC    5V   (if available)	 * LV        NC   GND   x.xV (if available)	 * LV        GND  NC    3.3V 	 * LV        GND  GND   >= x.xV 	 * 	 * So, how do I determine if I have a 5V or a LV	 * socket on my board?  Look at the socket!	 *	 * 	 * Socket with 5V key:	 * ++--------------------------------------------+	 * ||                                            |	 * ||                                           ||	 * ||                                           ||	 * |                                             |	 * +---------------------------------------------+	 *	 * Socket with LV key:	 * ++--------------------------------------------+	 * ||                                            |	 * |                                            ||	 * |                                            ||	 * |                                             |	 * +---------------------------------------------+	 *	 *	 * With other words - LV only cards does not fit	 * into the 5V socket!	 */	/* read out VS1 and VS2 */	reg = (pipr & M8XX_PCMCIA_VS_MASK(_slot_)) 		>> M8XX_PCMCIA_VS_SHIFT(_slot_);	if(socket_get(_slot_) == PCMCIA_SOCKET_KEY_LV) {		switch(reg) {		case 1: *value |= SS_3VCARD; break; /* GND, NC - 3.3V only */		case 2: *value |= SS_XVCARD; break; /* NC. GND - x.xV only */		};	}	DEBUG(3,"GetStatus(%d) = %#2.2x\n", lsock, *value);	return 0;}  /* ------------------------------------------------------------------------- */static int m8xx_inquire_socket(u_short lsock, socket_cap_t *cap){	*cap = capabilities;	return 0;}/* ------------------------------------------------------------------------- */static int m8xx_get_socket(u_short lsock, socket_state_t *state){	*state = socket[lsock].state; /* copy the whole structure */	DEBUG(3,"GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "

⌨️ 快捷键说明

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