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

📄 tcic.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 2 页
字号:
    /* jump start interrupt handler, if needed */    tcic_interrupt(0, NULL, NULL);    if (register_ss_entry(sockets, &tcic_service) != 0) {	printk(KERN_NOTICE "tcic: register_ss_entry() failed\n");	release_region(tcic_base, 16);	if (cs_irq != 0)	    free_irq(cs_irq, tcic_interrupt);	return -ENODEV;    }    return 0;    } /* init_tcic *//*====================================================================*/static void __exit exit_tcic(void){    u_long flags;    unregister_ss_entry(&tcic_service);    save_flags(flags);    cli();    if (cs_irq != 0) {	tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);	free_irq(cs_irq, tcic_interrupt);    }    del_timer(&poll_timer);    restore_flags(flags);    release_region(tcic_base, 16);} /* exit_tcic *//*====================================================================*/static void tcic_interrupt(int irq, void *dev, struct pt_regs *regs){    int i, quick = 0;    u_char latch, sstat;    u_short psock;    u_int events;    static volatile int active = 0;    if (active) {	printk(KERN_NOTICE "tcic: reentered interrupt handler!\n");	return;    } else	active = 1;    DEBUG(2, "tcic: tcic_interrupt()\n");        for (i = 0; i < sockets; i++) {	psock = socket_table[i].psock;	tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)		  | TCIC_ADDR_INDREG | TCIC_SCF1(psock));	sstat = tcic_getb(TCIC_SSTAT);	latch = sstat ^ socket_table[psock].last_sstat;	socket_table[i].last_sstat = sstat;	if (tcic_getb(TCIC_ICSR) & TCIC_ICSR_CDCHG) {	    tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR);	    quick = 1;	}	if ((latch == 0) || (socket_table[psock].handler == NULL))	    continue;	events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0;	events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0;	if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {	    events |= (latch & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;	} else {	    events |= (latch & TCIC_SSTAT_RDY) ? SS_READY : 0;	    events |= (latch & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;	    events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;	}	DEBUG(1, "tcic: socket %d event 0x%04x\n", i, events);	if (events)	    socket_table[i].handler(socket_table[i].info, events);    }    /* Schedule next poll, if needed */    if (((cs_irq == 0) || quick) && !timer_pending(&poll_timer)) {	poll_timer.expires = jiffies + (quick ? poll_quick : poll_interval);	add_timer(&poll_timer);    }    active = 0;        DEBUG(2, "tcic: interrupt done\n");    } /* tcic_interrupt */static void tcic_timer(u_long data){    DEBUG(2, "tcic: tcic_timer()\n");    tcic_interrupt(0, NULL, NULL);}/*====================================================================*/static int tcic_register_callback(u_short lsock, ss_callback_t *call){    if (call == NULL) {	socket_table[lsock].handler = NULL;	MOD_DEC_USE_COUNT;    } else {	MOD_INC_USE_COUNT;	socket_table[lsock].handler = call->handler;	socket_table[lsock].info = call->info;    }    return 0;} /* tcic_register_callback *//*====================================================================*/static int tcic_get_status(u_short lsock, u_int *value){    u_short psock = socket_table[lsock].psock;    u_char reg;    tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)	      | TCIC_ADDR_INDREG | TCIC_SCF1(psock));    reg = tcic_getb(TCIC_SSTAT);    *value  = (reg & TCIC_SSTAT_CD) ? SS_DETECT : 0;    *value |= (reg & TCIC_SSTAT_WP) ? SS_WRPROT : 0;    if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {	*value |= (reg & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;    } else {	*value |= (reg & TCIC_SSTAT_RDY) ? SS_READY : 0;	*value |= (reg & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;	*value |= (reg & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;    }    reg = tcic_getb(TCIC_PWR);    if (reg & (TCIC_PWR_VCC(psock)|TCIC_PWR_VPP(psock)))	*value |= SS_POWERON;    DEBUG(1, "tcic: GetStatus(%d) = %#2.2x\n", lsock, *value);    return 0;} /* tcic_get_status */  /*====================================================================*/static int tcic_inquire_socket(u_short lsock, socket_cap_t *cap){    *cap = tcic_cap;    return 0;} /* tcic_inquire_socket *//*====================================================================*/static int tcic_get_socket(u_short lsock, socket_state_t *state){    u_short psock = socket_table[lsock].psock;    u_char reg;    u_short scf1, scf2;        tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)	      | TCIC_ADDR_INDREG | TCIC_SCF1(psock));    scf1 = tcic_getw(TCIC_DATA);    state->flags = (scf1 & TCIC_SCF1_IOSTS) ? SS_IOCARD : 0;    state->flags |= (scf1 & TCIC_SCF1_DMA_MASK) ? SS_DMA_MODE : 0;    state->flags |= (scf1 & TCIC_SCF1_SPKR) ? SS_SPKR_ENA : 0;    if (tcic_getb(TCIC_SCTRL) & TCIC_SCTRL_ENA)	state->flags |= SS_OUTPUT_ENA;    state->io_irq = scf1 & TCIC_SCF1_IRQ_MASK;    if (state->io_irq == 1) state->io_irq = 11;    reg = tcic_getb(TCIC_PWR);    state->Vcc = state->Vpp = 0;    if (reg & TCIC_PWR_VCC(psock)) {	if (reg & TCIC_PWR_VPP(psock))	    state->Vcc = 50;	else	    state->Vcc = state->Vpp = 50;    } else {	if (reg & TCIC_PWR_VPP(psock)) {	    state->Vcc = 50;	    state->Vpp = 120;	}    }    reg = tcic_aux_getb(TCIC_AUX_ILOCK);    state->flags |= (reg & TCIC_ILOCK_CRESET) ? SS_RESET : 0;    /* Card status change interrupt mask */    tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));    scf2 = tcic_getw(TCIC_DATA);    state->csc_mask = (scf2 & TCIC_SCF2_MCD) ? 0 : SS_DETECT;    if (state->flags & SS_IOCARD) {	state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_STSCHG;    } else {	state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_BATDEAD;	state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT2) ? 0 : SS_BATWARN;	state->csc_mask |= (scf2 & TCIC_SCF2_MRDY) ? 0 : SS_READY;    }    DEBUG(1, "tcic: GetSocket(%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);    return 0;} /* tcic_get_socket *//*====================================================================*/static int tcic_set_socket(u_short lsock, socket_state_t *state){    u_short psock = socket_table[lsock].psock;    u_char reg;    u_short scf1, scf2;    DEBUG(1, "tcic: 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);    tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);    reg = tcic_getb(TCIC_PWR);    reg &= ~(TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock));    if (state->Vcc == 50) {	switch (state->Vpp) {	case 0:   reg |= TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock); break;	case 50:  reg |= TCIC_PWR_VCC(psock); break;	case 120: reg |= TCIC_PWR_VPP(psock); break;	default:  return -EINVAL;	}    } else if (state->Vcc != 0)	return -EINVAL;    if (reg != tcic_getb(TCIC_PWR))	tcic_setb(TCIC_PWR, reg);    reg = TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT;    if (state->flags & SS_OUTPUT_ENA) {	tcic_setb(TCIC_SCTRL, TCIC_SCTRL_ENA);	reg |= TCIC_ILOCK_CRESENA;    } else	tcic_setb(TCIC_SCTRL, 0);    if (state->flags & SS_RESET)	reg |= TCIC_ILOCK_CRESET;    tcic_aux_setb(TCIC_AUX_ILOCK, reg);        tcic_setw(TCIC_ADDR, TCIC_SCF1(psock));    scf1 = TCIC_SCF1_FINPACK;    scf1 |= TCIC_IRQ(state->io_irq);    if (state->flags & SS_IOCARD) {	scf1 |= TCIC_SCF1_IOSTS;	if (state->flags & SS_SPKR_ENA)	    scf1 |= TCIC_SCF1_SPKR;	if (state->flags & SS_DMA_MODE)	    scf1 |= TCIC_SCF1_DREQ2 << TCIC_SCF1_DMA_SHIFT;    }    tcic_setw(TCIC_DATA, scf1);    /* Some general setup stuff, and configure status interrupt */    reg = TCIC_WAIT_ASYNC | TCIC_WAIT_SENSE | to_cycles(250);    tcic_aux_setb(TCIC_AUX_WCTL, reg);    tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00|		  TCIC_IRQ(cs_irq));        /* Card status change interrupt mask */    tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));    scf2 = TCIC_SCF2_MALL;    if (state->csc_mask & SS_DETECT) scf2 &= ~TCIC_SCF2_MCD;    if (state->flags & SS_IOCARD) {	if (state->csc_mask & SS_STSCHG) reg &= ~TCIC_SCF2_MLBAT1;    } else {	if (state->csc_mask & SS_BATDEAD) reg &= ~TCIC_SCF2_MLBAT1;	if (state->csc_mask & SS_BATWARN) reg &= ~TCIC_SCF2_MLBAT2;	if (state->csc_mask & SS_READY) reg &= ~TCIC_SCF2_MRDY;    }    tcic_setw(TCIC_DATA, scf2);    /* For the ISA bus, the irq should be active-high totem-pole */    tcic_setb(TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH);    return 0;} /* tcic_set_socket */  /*====================================================================*/static int tcic_get_io_map(u_short lsock, struct pccard_io_map *io){    u_short psock = socket_table[lsock].psock;    u_short base, ioctl;    u_int addr;        if (io->map > 1) return -EINVAL;    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));    addr = TCIC_IWIN(psock, io->map);    tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);    base = tcic_getw(TCIC_DATA);    tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);    ioctl = tcic_getw(TCIC_DATA);    if (ioctl & TCIC_ICTL_TINY)	io->start = io->stop = base;    else {	io->start = base & (base-1);	io->stop = io->start + (base ^ (base-1));    }    io->speed = to_ns(ioctl & TCIC_ICTL_WSCNT_MASK);    io->flags  = (ioctl & TCIC_ICTL_ENA) ? MAP_ACTIVE : 0;    switch (ioctl & TCIC_ICTL_BW_MASK) {    case TCIC_ICTL_BW_DYN:	io->flags |= MAP_AUTOSZ; break;    case TCIC_ICTL_BW_16:	io->flags |= MAP_16BIT; break;    default:	break;    }    DEBUG(3, "tcic: 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;} /* tcic_get_io_map *//*====================================================================*/static int tcic_set_io_map(u_short lsock, struct pccard_io_map *io){    u_short psock = socket_table[lsock].psock;    u_int addr;    u_short base, len, ioctl;        DEBUG(3, "tcic: 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 > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||	(io->stop < io->start)) return -EINVAL;    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));    addr = TCIC_IWIN(psock, io->map);    base = io->start; len = io->stop - io->start;    /* Check to see that len+1 is power of two, etc */    if ((len & (len+1)) || (base & len)) return -EINVAL;    base |= (len+1)>>1;    tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);    tcic_setw(TCIC_DATA, base);        ioctl  = (psock << TCIC_ICTL_SS_SHFT);    ioctl |= (len == 0) ? TCIC_ICTL_TINY : 0;    ioctl |= (io->flags & MAP_ACTIVE) ? TCIC_ICTL_ENA : 0;    ioctl |= to_cycles(io->speed) & TCIC_ICTL_WSCNT_MASK;    if (!(io->flags & MAP_AUTOSZ)) {	ioctl |= TCIC_ICTL_QUIET;	ioctl |= (io->flags & MAP_16BIT) ? TCIC_ICTL_BW_16 : TCIC_ICTL_BW_8;    }    tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);    tcic_setw(TCIC_DATA, ioctl);        return 0;} /* tcic_set_io_map *//*====================================================================*/static int tcic_get_mem_map(u_short lsock, struct pccard_mem_map *mem){    u_short psock = socket_table[lsock].psock;    u_short addr, ctl;    u_long base, mmap;        if (mem->map > 3) return -EINVAL;    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));    addr = TCIC_MWIN(psock, mem->map);        tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);    base = tcic_getw(TCIC_DATA);    if (base & TCIC_MBASE_4K_BIT) {	mem->sys_start = base & TCIC_MBASE_HA_MASK;	mem->sys_stop = mem->sys_start;    } else {	base &= TCIC_MBASE_HA_MASK;	mem->sys_start = (base & (base-1));	mem->sys_stop = mem->sys_start + (base ^ (base-1));    }    mem->sys_start = mem->sys_start << TCIC_MBASE_HA_SHFT;    mem->sys_stop = (mem->sys_stop << TCIC_MBASE_HA_SHFT) + 0x0fff;        tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);    mmap = tcic_getw(TCIC_DATA);    mem->flags = (mmap & TCIC_MMAP_REG) ? MAP_ATTRIB : 0;    mmap &= TCIC_MMAP_CA_MASK;    mem->card_start = mem->sys_start + (mmap << TCIC_MMAP_CA_SHFT);    mem->card_start &= 0x3ffffff;        tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);    ctl = tcic_getw(TCIC_DATA);    mem->flags |= (ctl & TCIC_MCTL_ENA) ? MAP_ACTIVE : 0;    mem->flags |= (ctl & TCIC_MCTL_B8) ? 0 : MAP_16BIT;    mem->flags |= (ctl & TCIC_MCTL_WP) ? MAP_WRPROT : 0;    mem->speed = to_ns(ctl & TCIC_MCTL_WSCNT_MASK);        DEBUG(3, "tcic: 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;} /* tcic_get_mem_map *//*====================================================================*/  static int tcic_set_mem_map(u_short lsock, struct pccard_mem_map *mem){    u_short psock = socket_table[lsock].psock;    u_short addr, ctl;    u_long base, len, mmap;    DEBUG(3, "tcic: 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 > 3) || (mem->card_start > 0x3ffffff) ||	(mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff) ||	(mem->sys_start > mem->sys_stop) || (mem->speed > 1000))	return -EINVAL;    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));    addr = TCIC_MWIN(psock, mem->map);    base = mem->sys_start; len = mem->sys_stop - mem->sys_start;    if ((len & (len+1)) || (base & len)) return -EINVAL;    if (len == 0x0fff)	base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT;    else	base = (base | (len+1)>>1) >> TCIC_MBASE_HA_SHFT;    tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);    tcic_setw(TCIC_DATA, base);        mmap = mem->card_start - mem->sys_start;    mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK;    if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG;    tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);    tcic_setw(TCIC_DATA, mmap);    ctl  = TCIC_MCTL_QUIET | (psock << TCIC_MCTL_SS_SHFT);    ctl |= to_cycles(mem->speed) & TCIC_MCTL_WSCNT_MASK;    ctl |= (mem->flags & MAP_16BIT) ? 0 : TCIC_MCTL_B8;    ctl |= (mem->flags & MAP_WRPROT) ? TCIC_MCTL_WP : 0;    ctl |= (mem->flags & MAP_ACTIVE) ? TCIC_MCTL_ENA : 0;    tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);    tcic_setw(TCIC_DATA, ctl);        return 0;} /* tcic_set_mem_map *//*====================================================================*/typedef int (*subfn_t)(u_short, void *);    static subfn_t service_table[] = {    (subfn_t)&tcic_register_callback,    (subfn_t)&tcic_inquire_socket,    (subfn_t)&tcic_get_status,    (subfn_t)&tcic_get_socket,    (subfn_t)&tcic_set_socket,    (subfn_t)&tcic_get_io_map,    (subfn_t)&tcic_set_io_map,    (subfn_t)&tcic_get_mem_map,    (subfn_t)&tcic_set_mem_map,};#define NFUNC (sizeof(service_table)/sizeof(subfn_t))static int tcic_service(u_int lsock, u_int cmd, void *arg){    return (cmd < NFUNC) ? service_table[cmd](lsock, arg) : -EINVAL; }/*====================================================================*/module_init(init_tcic);module_exit(exit_tcic);

⌨️ 快捷键说明

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