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

📄 m8xx_pcmcia.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 3 页
字号:
	      "io_irq %d, csc_mask %#2.2x\n", lsock, state->flags,	      state->Vcc, state->Vpp, state->io_irq, state->csc_mask);	return 0;}/* ------------------------------------------------------------------------- */static int m8xx_set_socket(u_short lsock, socket_state_t *state){	socket_info_t *s = &socket[lsock];	event_table_t *e;	u_int reg;	u_long flags;#if (PCMCIA_SOCKETS_NO == 2)	u_int _slot_ = s->slot;#endif    	DEBUG(3, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "	      "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,	      state->Vcc, state->Vpp, state->io_irq, state->csc_mask);	/* First, set voltage - bail out if invalid */    	if(voltage_set(_slot_, state->Vcc, state->Vpp))		return -EINVAL;	/* Take care of reset... */	if(state->flags & SS_RESET) 		M8XX_PGCRX(_slot_) |=  M8XX_PGCRX_CXRESET; /* active high */	else		M8XX_PGCRX(_slot_) &= ~M8XX_PGCRX_CXRESET; 	/* ... and output enable. */	/* The CxOE signal is connected to a 74541 on the ADS.	   I guess most other boards used the ADS as a reference.	   I tried to control the CxOE signal with SS_OUTPUT_ENA,	   but the reset signal seems connected via the 541. 	   If the CxOE is left high are some signals tristated and	   no pullups are present -> the cards act wierd.	   So right now the buffers are enabled if the power is on. */	if(state->Vcc || state->Vpp)		M8XX_PGCRX(_slot_) &= ~M8XX_PGCRX_CXOE; /* active low */	else		M8XX_PGCRX(_slot_) |=  M8XX_PGCRX_CXOE;		/* 	 * We'd better turn off interrupts before 	 * we mess with the events-table..	 */	save_flags(flags);	cli();	/*	 * Play around with the interrupt mask to be able to	 * give the events the generic pcmcia driver wants us to.	 */	e = &s->events[0]; 	reg = 0;	if(state->csc_mask & SS_DETECT) {		e->eventbit = SS_DETECT;		reg |= e->regbit = (M8XX_PCMCIA_CD2(_slot_) 				    | M8XX_PCMCIA_CD1(_slot_));		e++;	}	if(state->flags & SS_IOCARD) {		/* 		 * I/O card		 */		if(state->csc_mask & SS_STSCHG) {			e->eventbit = SS_STSCHG;			reg |= e->regbit = M8XX_PCMCIA_BVD1(_slot_);			e++;		}				/*		 * If io_irq is non-zero we should enable irq.		 */		if(state->io_irq) {			M8XX_PGCRX(_slot_) |= 				mk_int_int_mask(state->io_irq) << 24;			/*			 * Strange thing here:			 * The manual does not tell us which interrupt			 * the sources generate.			 * Anyhow, I found out that RDY_L generates IREQLVL.			 *			 * We use level triggerd interrupts, and they don't			 * have to be cleared in PSCR in the interrupt handler.			 */			reg |= M8XX_PCMCIA_RDY_L(_slot_);  		}		else			M8XX_PGCRX(_slot_) &= 0x00ffffff;		#if 0		if(state->flags & SS_SPKR_ENA)			enablespeaker();		else			disablespeaker();				if(state->flags & SS_DMA_MODE)			enabledma();		else			disabledma();#endif			}	else {				/*		 * Memory card		 */				if(state->csc_mask & SS_BATDEAD) {			e->eventbit = SS_BATDEAD;			reg |= e->regbit = M8XX_PCMCIA_BVD1(_slot_);			e++;		}				if(state->csc_mask & SS_BATWARN) {			e->eventbit = SS_BATWARN;			reg |= e->regbit = M8XX_PCMCIA_BVD2(_slot_);			e++;		}				/* What should I trigger on - low/high,raise,fall? */		if(state->csc_mask & SS_READY) {			e->eventbit = SS_READY;			reg |= e->regbit = 0; //??			e++;		}	}		e->regbit = 0;  /* terminate list */		/* 	 * Clear the status changed .	 * Port A and Port B share the same port.	 * Writing ones will clear the bits.	 */		((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = reg;		/*	 * Write the mask.	 * Port A and Port B share the same port.	 * Need for read-modify-write. 	 * Ones will enable the interrupt.	 */	reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per 		& M8XX_PCMCIA_MASK(_slot_);		((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per = reg;		restore_flags(flags);	/* copy the struct and modify the copy */		s->state = *state;		return 0;}/* ------------------------------------------------------------------------- */static int m8xx_get_io_map(u_short lsock, struct pccard_io_map *io){	if(io->map >= PCMCIA_IO_WIN_NO)		return -EINVAL;	*io = socket[lsock].io_win[io->map]; /* copy the struct */	DEBUG(3,"GetIOMap(%d, %d) = %#2.2x, %d ns, "	      "%#4.4x-%#4.4x\n", lsock, io->map, io->flags,	      io->speed, io->start, io->stop);	return 0;}/* ------------------------------------------------------------------------- */static int m8xx_set_io_map(u_short lsock, struct pccard_io_map *io){	socket_info_t *s = &socket[lsock];	pcmcia_win_t *w;	u_int reg, winnr;	#if (PCMCIA_SOCKETS_NO == 2)	u_int _slot_ = s->slot;#endif    #if 1  #define M8XX_SIZE (io->stop - io->start + 1)   #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)#else/* only for testing */#define M8XX_SIZE 0x400 // 0x10000      #define M8XX_BASE PCMCIA_IO_WIN_BASE#endif	DEBUG(3, "SetIOMap(%d, %d, %#2.2x, %d ns, "	      "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,	      io->speed, io->start, io->stop);	if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff) 	    || (io->stop > 0xffff) || (io->stop < io->start)) 		return -EINVAL;		if((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)		return -EINVAL;	if(io->flags & MAP_ACTIVE) {		winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO) 			+ (lsock * PCMCIA_IO_WIN_NO) + io->map;			/* setup registers */		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;		w += winnr;			w->or = 0; /* turn off window first */		w->br = M8XX_BASE;			reg <<= 27;       		reg |= 0x00018 + (_slot_ << 2);		reg |= m8xx_get_speed(io->speed, 1);		if(io->flags & MAP_WRPROT) 			reg |= 0x00000002;				if(io->flags & (MAP_16BIT | MAP_AUTOSZ))			reg |= 0x00000040;			if(io->flags & MAP_ACTIVE) 			reg |= 0x00000001;			w->or = reg;		DEBUG(3,"Socket %u: Mapped io window %u at %#8.8x, "		      "OR = %#8.8x.\n", lsock, io->map, w->br, w->or);#if 0		if(0) {			u_int k;			printk("dumping map from 0x%02x\n", M8XX_BASE);						for(k = M8XX_BASE; k < (M8XX_BASE+M8XX_SIZE); k++) {				if(!(k & 0x0f))					printk("0x%04x: ", k);								printk("%02x ", *((char *) k));								if((k & 0x0f) == 0x0f)					printk("\n");			}			printk("\n");		}#endif	}	/* copy the struct and modify the copy */		s->io_win[io->map] = *io; 	s->io_win[io->map].flags &= (MAP_WRPROT 				     | MAP_16BIT				     | MAP_ACTIVE);	return 0;}/* ------------------------------------------------------------------------- */static int m8xx_get_mem_map(u_short lsock, struct pccard_mem_map *mem){	if(mem->map >= PCMCIA_MEM_WIN_NO)		return -EINVAL;		*mem = socket[lsock].mem_win[mem->map]; /* copy the struct */		DEBUG(3, "GetMemMap(%d, %d) = %#2.2x, %d ns, "	      "%#5.5lx-%#5.5lx, %#5.5x\n", lsock, mem->map, mem->flags,	      mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);	return 0;}/* ------------------------------------------------------------------------- */static int m8xx_set_mem_map(u_short lsock, struct pccard_mem_map *mem){	socket_info_t *s = &socket[lsock];	pcmcia_win_t *w;	struct pccard_mem_map *old;	u_int reg, winnr;	#if (PCMCIA_SOCKETS_NO == 2)	u_int _slot_ = s->slot;#endif    	DEBUG(3, "SetMemMap(%d, %d, %#2.2x, %d ns, "	      "%#5.5lx-%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,	      mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);	if ((mem->map >= PCMCIA_MEM_WIN_NO) || (mem->sys_start > mem->sys_stop)	    || ((mem->sys_stop - mem->sys_start) >= PCMCIA_MEM_WIN_SIZE)	    || (mem->card_start >= 0x04000000) 	    || (mem->sys_start & 0xfff)                /* 4KByte resolution */	    || (mem->card_start & 0xfff))                   		return -EINVAL;		if((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {		printk( "Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);		return -EINVAL;	}	winnr = (lsock * PCMCIA_MEM_WIN_NO) + mem->map;		/* Setup the window in the pcmcia controller */		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;	w += winnr;		reg <<= 27;	reg |= _slot_ << 2;		reg |= m8xx_get_speed(mem->speed, 0);	if(mem->flags & MAP_ATTRIB) 		reg |= 0x00000010;		if(mem->flags & MAP_WRPROT) 		reg |= 0x00000002;		if(mem->flags & MAP_16BIT) 		reg |= 0x00000040;		if(mem->flags & MAP_ACTIVE) 		reg |= 0x00000001;		w->or = reg;	DEBUG(3, "Socket %u: Mapped memory window %u at %#8.8x, "	      "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);	if(mem->flags & MAP_ACTIVE) {		mem->sys_stop -= mem->sys_start;		/* get the new base address */				mem->sys_start = PCMCIA_MEM_WIN_BASE + 			(PCMCIA_MEM_WIN_SIZE * winnr)			+ mem->card_start; 		mem->sys_stop += mem->sys_start;	}DEBUG(3, "SetMemMap(%d, %d, %#2.2x, %d ns, "	      "%#5.5lx-%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,	      mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);	/* copy the struct and modify the copy */		old = &s->mem_win[mem->map];		*old = *mem;	old->flags &= (MAP_ATTRIB		       | MAP_WRPROT 		       | MAP_16BIT		       | MAP_ACTIVE);	return 0;}/* ------------------------------------------------------------------------- */    static void *m8xx_services[] = {	&m8xx_register_callback,	&m8xx_inquire_socket,	&m8xx_get_status,	&m8xx_get_socket,	&m8xx_set_socket,	&m8xx_get_io_map,	&m8xx_set_io_map,	&m8xx_get_mem_map,	&m8xx_set_mem_map,};#define NFUNC (sizeof(m8xx_services)/sizeof(void *))static int m8xx_service(u_int lsock, u_int cmd, void *arg){	DEBUG(3, "Service(%d, %d, 0x%p)\n", lsock, cmd, arg);	if(cmd < NFUNC)	    return ((int (*)(u_short, void *))m8xx_services[cmd])(lsock, arg);	return -EINVAL;}/* ------------------------------------------------------------------------- */module_init(m8xx_init);module_exit(m8xx_exit);

⌨️ 快捷键说明

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