📄 pd6700.c
字号:
static int pd67_set_mem_map(unsigned int sock, struct pccard_mem_map *mem){ u_short base, i; u_char map; if (socket[sock].flags & IS_ALIVE) return -EINVAL; if (mem->sys_start >= pCF_MEM_BASE) mem->sys_start -= pCF_MEM_BASE; if (mem->sys_stop >= pCF_MEM_BASE) mem->sys_stop -= pCF_MEM_BASE; DEBUG(1, "pd6700: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5" "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed, mem->sys_start, mem->sys_stop, mem->card_start); map = mem->map; if ((map > 4) || (mem->card_start > 0x3ffffff) || (mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) return -EINVAL; // 检验设置 MEMORY MAP 的合法性 /* Turn off the window before changing anything */ if (pd67_get(sock, PD67_MAP_ENA) & PD67_ENA_MEM(map)) pd67_bclr(sock, PD67_MAP_ENA, PD67_ENA_MEM(map)); // 禁止MEMORY MAP base = PD67_MEM(map); i = (mem->sys_start >> 12) & 0x0fff; // 设置MEMORY MAP 开始地址参数 if (mem->flags & MAP_16BIT) i |= PD67_MEM_16BIT; // 总线宽度 if (mem->flags & MAP_0WS) i |= PD67_MEM_0WS; // PD6710无效,为了兼容 pd67_set_pair(sock, base+PD67_W_START, i); // 设置MEMORY MAP 开始地址寄存器 i = (mem->sys_stop >> 12) & 0x0fff; // 设置MEMORY MAP 结束地址参数 switch (to_cycles(mem->speed)) { case 0: break; case 1: i |= PD67_MEM_WS0; break; case 2: i |= PD67_MEM_WS1; break; default: i |= PD67_MEM_WS1 | PD67_MEM_WS0; break; } pd67_set_pair(sock, base+PD67_W_STOP, i); // 设置MEMORY MAP 结束地址寄存器 i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;// 设置MEMORY MAP OFFSET参数 if (mem->flags & MAP_WRPROT) i |= PD67_MEM_WRPROT; if (mem->flags & MAP_ATTRIB) i |= PD67_MEM_REG; // 访问属性寄存器 pd67_set_pair(sock, base+PD67_W_OFF, i); // 设置MEMORY MAP OFFSET寄存器 /* Turn on the window if necessary */ if (mem->flags & MAP_ACTIVE) pd67_bset(sock, PD67_MAP_ENA, PD67_ENA_MEM(map)); // 激活 MEMORY MAP mem->sys_start += pCF_MEM_BASE; mem->sys_stop += pCF_MEM_BASE; return 0;} /* pd67_set_mem_map *//*====================================================================== Routines for accessing socket information and register dumps via /proc/bus/pccard/... ======================================================================*/#ifdef CONFIG_PROC_FSstatic int proc_read_info(char *buf, char **start, off_t pos, int count, int *eof, void *data){ socket_info_t *s = data; char *p = buf; p += sprintf(p, "type: %s\npsock: %d\n", pcic[s->type].name, s->psock); return (p - buf);}static int proc_read_exca(char *buf, char **start, off_t pos, int count, int *eof, void *data){ u_short sock = (socket_info_t *)data - socket; char *p = buf; int i, top; #ifdef CONFIG_ISA u_long flags = 0;#endif ISA_LOCK(sock, flags); top = 0x40; for (i = 0; i < top; i += 4) { if (i == 0x50) { p += sprintf(p, "\n"); i = 0x100; } p += sprintf(p, "%02x %02x %02x %02x%s", pd67_get(sock,i), pd67_get(sock,i+1), pd67_get(sock,i+2), pd67_get(sock,i+3), ((i % 16) == 12) ? "\n" : " "); } ISA_UNLOCK(sock, flags); return (p - buf);}static void pd67_proc_setup(unsigned int sock, struct proc_dir_entry *base){ socket_info_t *s = &socket[sock]; if (s->flags & IS_ALIVE) return; create_proc_read_entry("info", 0, base, proc_read_info, s); create_proc_read_entry("exca", 0, base, proc_read_exca, s); s->proc = base;}static void pd67_proc_remove(unsigned int sock){ struct proc_dir_entry *base = socket[sock].proc; if (base == NULL) return; remove_proc_entry("info", base); remove_proc_entry("exca", base);}#else#define pd67_proc_setup NULL#endif /* CONFIG_PROC_FS *//*====================================================================*//* * The locking is rather broken. Why do we only lock for ISA, not for * all other cases? If there are reasons to lock, we should lock. Not * this silly conditional. * * Plan: make it bug-for-bug compatible with the old stuff, and clean * it up when the infrastructure is done. */#ifdef CONFIG_ISA#define LOCKED(x) do { \ int retval; \ unsigned long flags; \ spin_lock_irqsave(&isa_lock, flags); \ retval = x; \ spin_unlock_irqrestore(&isa_lock, flags); \ return retval; \} while (0)#else#define LOCKED(x) return x#endif /*********************************************************************************************************** Function name: pd67_init** Descriptions: PCMCIA接口初始化** Input: s,接口序号** Output :出错返回非0** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static int pd67_init(unsigned int s) // Socket Interface init{ int i; pccard_io_map io = { 0, 0, 0, 0, 1 }; pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 }; mem.sys_stop = 0x1000; pd67_set_socket(s, &dead_socket); // 初始化接口 for (i = 0; i < 2; i++) { io.map = i; pd67_set_io_map(s, &io); // 初始化设置IO口 } for (i = 0; i < 5; i++) { mem.map = i; pd67_set_mem_map(s, &mem); // 初始化设置MEM接口 } return 0;}/*********************************************************************************************************** Function name: pd67_suspend** Descriptions: 接口挂起处理。** Input:sock,接口序号** Output :** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static int pd67_suspend(unsigned int sock){ return pd67_set_socket(sock, &dead_socket); //dead_socket 在cs.c中定义}static struct pccard_operations pcic_operations = { pd67_init, // PCMCIA接口初始化 pd67_suspend, // 挂起处理 pd67_register_callback, // 注册Call Back函数 pd67_inquire_socket, // 询问接口能力 pd67_get_status, // 获取接口状态 pd67_get_socket, // 获取接口置配 pd67_set_socket, // 设置接口 pd67_get_io_map, // 获取IO MAP 设置函数 pd67_set_io_map, // 设置IO MAP 处理函数 pd67_get_mem_map, // 获取MEMORY MAP 设置函数 pd67_set_mem_map, // 设置MEMORY MAP 处理函数 pd67_proc_setup // };/*====================================================================*//*********************************************************************************************************** Function name: init_pd6700** Descriptions: 系统相关初始化,如:注册PCMCIA桥接口设备\申请IO和中断等。安装模块时使用该函数** Input: 无** Output : 无** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static int __init init_pd6700(void){ servinfo_t serv;// 配置S3C2410总线接口与 /* nGCS2 = nUB/nLB(nSBHE), nWAIT, 16-bit */ BWSCON = (BWSCON & ~(BWSCON_ST2 | BWSCON_WS2 | BWSCON_DW2)) | (BWSCON_ST2 | BWSCON_WS2 | BWSCON_DW(2, BWSCON_DW_16)); BANKCON2 = BANKCON_Tacs4 | BANKCON_Tcos4 | BANKCON_Tacc14 | BANKCON_Toch1 | BANKCON_Tcah4 | BANKCON_Tacp6 | BANKCON_PMC1; set_external_irq(IRQ_nCF_INS, EXT_FALLING_EDGE, GPIO_PULLUP_EN); // set_external_irq(IRQ_CF_RDY, EXT_RISING_EDGE, GPIO_PULLUP_EN); // pcmcia_get_card_services_info(&serv); // 获取卡服务驱动信息 if (serv.Revision != CS_RELEASE_CODE) { // 检验版本是否匹配 printk(KERN_NOTICE "pd6700: Card Services release " "does not match!\n"); return -1; } DEBUG(0, "%s\n", version); printk(KERN_INFO "Intel PCIC probe: "); sockets = 0; // 初始化接口数为0 ini_pcmcia_bridge(); // 添加PCMCIA桥接口处理函数,更改sockets值 if (sockets == 0) { printk("not found.\n"); return -ENODEV; } /* Set up interrupt handler(s) */ if (cs_irq != 0) if( request_irq(cs_irq, pcic_interrupt, SA_INTERRUPT, "pd6700", pcic_interrupt)) { printk(KERN_NOTICE "IRQ failed\n"); } // 申请中断(快速处理) if (register_ss_entry(sockets, &pcic_operations) != 0) // 注册一个Socket Driver入口 printk(KERN_NOTICE "pd6700: register_ss_entry() failed\n"); /* Finally, schedule a polling interrupt */ // 调度中断轮询 if (poll_interval != 0) { poll_timer.function = pcic_interrupt_wrapper; // 中断处理函数 poll_timer.data = 0; // 中断处理函数的参数 init_timer(&poll_timer); // 初始化 poll_timer.expires = jiffies + poll_interval; // 轮询中断间隔 add_timer(&poll_timer); // 添加的定时器队列 } return 0;} /* init_pd6700 *//*********************************************************************************************************** Function name: exit_pd6700** Descriptions: 卸载本模块处理函数** Input: 无** Output : 无** Created by: ** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static void __exit exit_pd6700(void){ int i;#ifdef CONFIG_PROC_FS for (i = 0; i < sockets; i++) pd67_proc_remove(i);#endif unregister_ss_entry(&pcic_operations); if (poll_interval != 0) del_timer(&poll_timer); // 删除定时器事件 if (cs_irq != 0) free_irq(cs_irq, pcic_interrupt); // 释放中断 for (i = 0; i < sockets; i++) { /* Turn off all interrupt sources! */ pd67_set(i, PD67_CSCINT, 0); // 关闭所有中断输出 release_region(socket[i].ioaddr, 2); // 释放IO口资源 }} /* exit_pd6700 */module_init(init_pd6700);module_exit(exit_pd6700);MODULE_LICENSE("Zhou Linshan MPL/GPL");/*====================================================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -