📄 pd6700.c
字号:
{ socket[sockets].ioaddr = port; // CPU与接口控制器地址 socket[sockets].psock = psock; // 接口偏移 socket[sockets].type = type; // 控制器类型 socket[sockets].flags = pcic[type].flags; // 标记接口桥类型 if (is_alive(sockets)) // 查询当前接口是否活动的,已被使用 socket[sockets].flags |= IS_ALIVE; // 接口是活动的 sockets++; // 系统接口数加1}/*********************************************************************************************************** Function name: add_pcmcia_bridge** Descriptions: 添加PCMCIA桥接口处理函数,仅在ini_pcmcia_bridge()函数中被使用** Input: ns , 接口数** type ,接口类型** Output :** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static void __init add_pcmcia_bridge(int ns, int type){ u_int mask = 0, i, base; socket_info_t *t = &socket[sockets-ns]; // 接口描述数据结构 base = sockets-ns; // 系统当前操作接口序号 if (t->ioaddr > 0) request_region(t->ioaddr, 2, "pd6700"); // 申请IO地址 if (base == 0) printk("\n"); printk(KERN_INFO " %s", pcic[type].name); // 打印接口名称 printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x", t->ioaddr, t->psock*0x40); printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : "")); set_bridge_opts(base, ns); if (!cs_irq) { // 如果不使用硬件中断就用定时器查询 if (poll_interval == 0) poll_interval = HZ; printk(" polling interval = %d ms\n", poll_interval * 1000 / HZ); } /* Update socket interrupt information, capabilities */ // 与硬件系统相关的初始化 for (i = 0; i < ns; i++) { /* Use SS_CAP_STATIC_MAP which disables the memory resource database check and SS_CAP_PAGE_REGS which disable io port maximun limit 0xffff */ t[i].cap.features |= SS_CAP_PCCARD | SS_CAP_STATIC_MAP | SS_CAP_PAGE_REGS; /* We just pass up an offset which is applied to client-requested base I/O addresses in alloc_io_space() */ t[i].cap.io_offset = vCF_IO_BASE; // IO基地址 /* Map Size */ t[i].cap.map_size = 0x1000; // IO地址范围 /* Do not use ISA irq */ t[i].cap.irq_mask = 0; t[i].cap.pci_irq = IRQ_CF_RDY; // 卡上中断 /* Card Detect IRQ */ t[i].cs_irq = cs_irq; // 卡检测中断 /* Enable Management Interrupt for card detect */ t[i].intr = PD67_INTR_ENA; // 使能卡检测中断 /* PD6710 IRQ3 is only connected to IRQ_CF_RDY */ t[i].intr |= 3 << 0; // 卡中断 }} /* add_pcmcia_bridge *//*********************************************************************************************************** Function name: ini_pcmcia_bridge** Descriptions: 初始化PCMCIA桥芯片,并分配系统硬件资源,仅在init_pd6700()函数中使用.** Input: 无** Output : 无** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static void __init ini_pcmcia_bridge(void){ int id; if (check_region(pd67_base, 2) != 0) { // 检查基地址是否被使用 if (sockets == 0) printk("port conflict at %#x\n", pd67_base); return; } id = identify(pd67_base, 0); // 识别芯片ID PD6710返回08 if( id == -1) return; // 芯片不存在或无法识别 add_socket(pd67_base, 0, id); // 添加1个PCMCIA接口 if(id == IS_PD6710) add_pcmcia_bridge(1, id); // 添加设备到系统 if(id == IS_PD6722) add_pcmcia_bridge(2, id); // 添加设备到系统}/*====================================================================*/static u_int pending_events[8];static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;/*********************************************************************************************************** Function name: pcic_bh** Descriptions: 中断下半部处理函数** Input:** Output :** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static void pcic_bh(void *dummy){ u_int events; int i; for (i=0; i < sockets; i++) { spin_lock_irq(&pending_event_lock); // 禁止本地中断并获取指定的锁 events = pending_events[i]; // 获取处理事件 pending_events[i] = 0; // 清零事件 spin_unlock_irq(&pending_event_lock); // 释放指定的锁,并激活本地中断 /* SS_DETECT events need a small delay here. The reason for this is that the "is there a card" electronics need time to see the card after the "we have a card coming in" electronics have seen it. */ if (events & SS_DETECT) // 检测到卡插入,需延迟一定时间,直到卡内部工作稳定 mdelay(4); if (socket[i].handler) socket[i].handler(socket[i].info, events); // 调用接口事件处理函数 }}static struct tq_struct pcic_task = { routine: pcic_bh};static unsigned long last_detect_jiffies;/*********************************************************************************************************** Function name: pcic_interrupt** Descriptions: PCMCIA卡中断服务程序** Input: irq, 中断号** *dev,** *regs,** Output : 无** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static void pcic_interrupt(int irq, void *dev, struct pt_regs *regs){ int i, j, csc; u_int events, active; u_long flags = 0; for (j = 0; j < 20; j++) { active = 0; for (i = 0; i < sockets; i++) { if ((socket[i].cs_irq != irq) && (socket[i].cap.pci_irq != irq)) continue; // 非本接口中断 ISA_LOCK(i, flags); csc = pd67_get(i, PD67_CSC); // 读取状态寄存器 if ((csc == 0) || (!socket[i].handler) || // 事件处理句柄为空 (pd67_get(i, PD67_IDENT) & 0x70)) { // 未知控制器,PD6710的位4~5为0 ISA_UNLOCK(i, flags); continue; // 非本接口中断 } events = (csc & PD67_CSC_DETECT) ? SS_DETECT : 0; // 记录事件,卡状态改变 /* Several sockets will send multiple "new card detected" events in rapid succession. However, the rest of the pcmcia expects only one such event. We just ignore these events by having a timeout */ if (events) { if ((jiffies - last_detect_jiffies)<(HZ/20)) // 超时,忽略中断 events = 0; last_detect_jiffies = jiffies; } if (pd67_get(i, PD67_INTCTL) & PD67_PC_IOCARD) events |= (csc & PD67_CSC_STSCHG) ? SS_STSCHG : 0; // IO卡模式 else { events |= (csc & PD67_CSC_BVD1) ? SS_BATDEAD : 0; events |= (csc & PD67_CSC_BVD2) ? SS_BATWARN : 0; events |= (csc & PD67_CSC_READY) ? SS_READY : 0; } ISA_UNLOCK(i, flags); DEBUG(2, "pd6700: socket %d event 0x%02x\n", i, events); if (events) { spin_lock(&pending_event_lock); // pending_events[i] |= events; // spin_unlock(&pending_event_lock); // schedule_task(&pcic_task); // 下半部处理 } active |= events; }//end for(i = 0; i < sockets; i++) if (!active) break; }// end for (j = 0; j < 20; j++) if (j == 20) printk(KERN_NOTICE "pd6700: infinite loop in interrupt handler\n"); DEBUG(4, "pd6700: interrupt done\n");} /* pcic_interrupt *//*********************************************************************************************************** Function name: pcic_interrupt_wrapper** Descriptions: 通过使用定时器轮询中断** Input: data ,不使用** Output : 无** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static void pcic_interrupt_wrapper(u_long data){ pcic_interrupt(0, NULL, NULL); poll_timer.expires = jiffies + poll_interval; add_timer(&poll_timer);}/*====================================================================*//*********************************************************************************************************** Function name: pd67_register_callback** Descriptions: 注册回调函数.当有事件产生时,通过调用handler函数解析。** Input: sock,接口号** *handler,事件处理函数** * info, ** Output :** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************///注册回调函数static int pd67_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info){ socket[sock].handler = handler; // 事件解析处理函数 socket[sock].info = info; // if (handler == NULL) { MOD_DEC_USE_COUNT; } else { MOD_INC_USE_COUNT; } return 0;} /* pd67_register_callback *//*====================================================================*//*********************************************************************************************************** Function name: pd67_inquire_socket** Descriptions: 查询PCMCIA接口的能力,设备驱都需要得知PCMCIA接口的所能提供的资源。** Input: sock, 接口索引** cap, 描述能力信息数据结构指针** Output : 0** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static int pd67_inquire_socket(unsigned int sock, socket_cap_t *cap){ *cap = socket[sock].cap; return 0;} /* pd67_inquire_socket *//*====================================================================*//*********************************************************************************************************** Function name: pd67_get_status** Descriptions: 获取接口当前状态,主要是状态寄存器的一些值** Input: sock, 接口索引** *value, 返回的状态值** Output : 返回0** Created by:** Created Date: **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/static int pd67_get_status(unsigned int sock, u_int *value){ u_int status; if (socket[sock].flags & IS_ALIVE) return -EINVAL; status = pd67_get(sock, PD67_STATUS); *value = ((status & PD67_CS_DETECT) == PD67_CS_DETECT) ? SS_DETECT : 0; if (pd67_get(sock, PD67_INTCTL) & PD67_PC_IOCARD) *value |= (status & PD67_CS_STSCHG) ? 0 : SS_STSCHG; // IO卡 else { *value |= (status & PD67_CS_BVD1) ? 0 : SS_BATDEAD; // 非IO卡 *value |= (status & PD67_CS_BVD2) ? 0 : SS_BATWARN; } *value |= (status & PD67_CS_WRPROT) ? SS_WRPROT : 0; *value |= (status & PD67_CS_READY) ? SS_READY : 0; *value |= (status & PD67_CS_POWERON) ? SS_POWERON : 0; DEBUG(1, "pd6700: GetStatus(%d) = %#4.4x\n", sock, *value); return 0;} /* pd67_get_status *//*====================================================================*//*********************************************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -