📄 m8xx_pcmcia.c
字号:
"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 + -