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

📄 i82365.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
static volatile u_int irq_hits;static u_short irq_sock;static void irq_count(int irq, void *dev, struct pt_regs *regs){    i365_get(irq_sock, I365_CSC);    irq_hits++;    DEBUG(2, "-> hit on irq %d\n", irq);}static u_int __init test_irq(u_short sock, int irq){    DEBUG(2, "  testing ISA irq %d\n", irq);    if (request_irq(irq, irq_count, 0, "scan", irq_count) != 0)	return 1;    irq_hits = 0; irq_sock = sock;    __set_current_state(TASK_UNINTERRUPTIBLE);    schedule_timeout(HZ/100);    if (irq_hits) {	free_irq(irq, irq_count);	DEBUG(2, "    spurious hit!\n");	return 1;    }    /* Generate one interrupt */    i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4));    i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);    udelay(1000);    free_irq(irq, irq_count);    /* mask all interrupts */    i365_set(sock, I365_CSCINT, 0);    DEBUG(2, "    hits = %d\n", irq_hits);        return (irq_hits != 1);}#ifdef CONFIG_ISAstatic u_int __init isa_scan(u_short sock, u_int mask0){    u_int mask1 = 0;    int i;#ifdef __alpha__#define PIC 0x4d0    /* Don't probe level-triggered interrupts -- reserved for PCI */    mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));#endif        if (do_scan) {	set_bridge_state(sock);	i365_set(sock, I365_CSCINT, 0);	for (i = 0; i < 16; i++)	    if ((mask0 & (1 << i)) && (test_irq(sock, i) == 0))		mask1 |= (1 << i);	for (i = 0; i < 16; i++)	    if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0))		mask1 ^= (1 << i);    }        printk(KERN_INFO "    ISA irqs (");    if (mask1) {	printk("scanned");    } else {	/* Fallback: just find interrupts that aren't in use */	for (i = 0; i < 16; i++)	    if ((mask0 & (1 << i)) && (_check_irq(i, 0) == 0))		mask1 |= (1 << i);	printk("default");	/* If scan failed, default to polled status */	if (!cs_irq && (poll_interval == 0)) poll_interval = HZ;    }    printk(") = ");        for (i = 0; i < 16; i++)	if (mask1 & (1<<i))	    printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);    if (mask1 == 0) printk("none!");        return mask1;}#endif /* CONFIG_ISA *//*====================================================================*//* Time conversion functions */static int to_cycles(int ns){    return ns/cycle_time;}static int to_ns(int cycles){    return cycle_time*cycles;}/*====================================================================*/#ifdef CONFIG_ISAstatic int __init identify(u_short port, u_short sock){    u_char val;    int type = -1;    /* Use the next free entry in the socket table */    socket[sockets].ioaddr = port;    socket[sockets].psock = sock;        /* Wake up a sleepy Cirrus controller */    if (wakeup) {	i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);	/* Pause at least 50 ms */	mdelay(50);    }        if ((val = i365_get(sockets, I365_IDENT)) & 0x70)	return -1;    switch (val) {    case 0x82:	type = IS_I82365A; break;    case 0x83:	type = IS_I82365B; break;    case 0x84:	type = IS_I82365DF; break;    case 0x88: case 0x89: case 0x8a:	type = IS_IBM; break;    }        /* Check for Vadem VG-468 chips */    outb(0x0e, port);    outb(0x37, port);    i365_bset(sockets, VG468_MISC, VG468_MISC_VADEMREV);    val = i365_get(sockets, I365_IDENT);    if (val & I365_IDENT_VADEM) {	i365_bclr(sockets, VG468_MISC, VG468_MISC_VADEMREV);	type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468;    }    /* Check for Ricoh chips */    val = i365_get(sockets, RF5C_CHIP_ID);    if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396))	type = IS_RF5Cx96;        /* Check for Cirrus CL-PD67xx chips */    i365_set(sockets, PD67_CHIP_INFO, 0);    val = i365_get(sockets, PD67_CHIP_INFO);    if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {	val = i365_get(sockets, PD67_CHIP_INFO);	if ((val & PD67_INFO_CHIP_ID) == 0) {	    type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;	    i365_set(sockets, PD67_EXT_INDEX, 0xe5);	    if (i365_get(sockets, PD67_EXT_INDEX) != 0xe5)		type = IS_VT83C469;	}    }    return type;} /* identify */#endif/*======================================================================    See if a card is present, powered up, in IO mode, and already    bound to a (non PC Card) Linux driver.  We leave these alone.    We make an exception for cards that seem to be serial devices.    ======================================================================*/static int __init is_alive(u_short sock){    u_char stat;    u_short start, stop;        stat = i365_get(sock, I365_STATUS);    start = i365_get_pair(sock, I365_IO(0)+I365_W_START);    stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP);    if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) &&	(i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) &&	(i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) &&	(check_region(start, stop-start+1) != 0) &&	((start & 0xfeef) != 0x02e8))	return 1;    else	return 0;}/*====================================================================*/static void __init add_socket(u_short port, int psock, int type){    socket[sockets].ioaddr = port;    socket[sockets].psock = psock;    socket[sockets].type = type;    socket[sockets].flags = pcic[type].flags;    if (is_alive(sockets))	socket[sockets].flags |= IS_ALIVE;    sockets++;}static void __init add_pcic(int ns, int type){    u_int mask = 0, i, base;    int use_pci = 0, isa_irq = 0;    socket_info_t *t = &socket[sockets-ns];    base = sockets-ns;    if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365");        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" : ""));#ifdef CONFIG_ISA    /* Set host options, build basic interrupt mask */    if (irq_list[0] == -1)	mask = irq_mask;    else	for (i = mask = 0; i < 16; i++)	    mask |= (1<<irq_list[i]);#endif    mask &= I365_MASK & set_bridge_opts(base, ns);#ifdef CONFIG_ISA    /* Scan for ISA interrupts */    mask = isa_scan(base, mask);#else    printk(KERN_INFO "    PCI card interrupts,");#endif        #ifdef CONFIG_ISA    /* Poll if only two interrupts available */    if (!use_pci && !poll_interval) {	u_int tmp = (mask & 0xff20);	tmp = tmp & (tmp-1);	if ((tmp & (tmp-1)) == 0)	    poll_interval = HZ;    }    /* Only try an ISA cs_irq if this is the first controller */    if (!use_pci && !grab_irq && (cs_irq || !poll_interval)) {	/* Avoid irq 12 unless it is explicitly requested */	u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));	for (cs_irq = 15; cs_irq > 0; cs_irq--)	    if ((cs_mask & (1 << cs_irq)) &&		(_check_irq(cs_irq, 0) == 0))		break;	if (cs_irq) {	    grab_irq = 1;	    isa_irq = cs_irq;	    printk(" status change on irq %d\n", cs_irq);	}    }#endif        if (!use_pci && !isa_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++) {	t[i].cap.features |= SS_CAP_PCCARD;	t[i].cap.map_size = 0x1000;	t[i].cap.irq_mask = mask;	t[i].cs_irq = isa_irq;    }} /* add_pcic *//*====================================================================*/#ifdef CONFIG_ISAstatic void __init isa_probe(void){    int i, j, sock, k, ns, id;    ioaddr_t port;    if (check_region(i365_base, 2) != 0) {	if (sockets == 0)	    printk("port conflict at %#x\n", i365_base);	return;    }    id = identify(i365_base, 0);    if ((id == IS_I82365DF) && (identify(i365_base, 1) != id)) {	for (i = 0; i < 4; i++) {	    if (i == ignore) continue;	    port = i365_base + ((i & 1) << 2) + ((i & 2) << 1);	    sock = (i & 1) << 1;	    if (identify(port, sock) == IS_I82365DF) {		add_socket(port, sock, IS_VLSI);		add_pcic(1, IS_VLSI);	    }	}    } else {	for (i = 0; i < (extra_sockets ? 8 : 4); i += 2) {	    port = i365_base + 2*(i>>2);	    sock = (i & 3);	    id = identify(port, sock);	    if (id < 0) continue;	    for (j = ns = 0; j < 2; j++) {		/* Does the socket exist? */		if ((ignore == i+j) || (identify(port, sock+j) < 0))		    continue;		/* Check for bad socket decode */		for (k = 0; k <= sockets; k++)		    i365_set(k, I365_MEM(0)+I365_W_OFF, k);		for (k = 0; k <= sockets; k++)		    if (i365_get(k, I365_MEM(0)+I365_W_OFF) != k)			break;		if (k <= sockets) break;		add_socket(port, sock+j, id); ns++;	    }	    if (ns != 0) add_pcic(ns, id);	}    }}#endif/*====================================================================*/static u_int pending_events[8];static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;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);		if (socket[i].handler)			socket[i].handler(socket[i].info, events);	}}static struct tq_struct pcic_task = {	routine:	pcic_bh};static void pcic_interrupt(int irq, void *dev,				    struct pt_regs *regs){    int i, j, csc;    u_int events, active;#ifdef CONFIG_ISA    u_long flags = 0;#endif        DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq);    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 = i365_get(i, I365_CSC);	    if ((csc == 0) || (!socket[i].handler) ||		(i365_get(i, I365_IDENT) & 0x70)) {		ISA_UNLOCK(i, flags);		continue;	    }	    events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;	    if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)		events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;	    else {		events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;		events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;		events |= (csc & I365_CSC_READY) ? SS_READY : 0;	    }	    ISA_UNLOCK(i, flags);	    DEBUG(2, "i82365: 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;	}	if (!active) break;    }    if (j == 20)	printk(KERN_NOTICE "i82365: infinite loop in interrupt handler\n");    DEBUG(4, "i82365: interrupt done\n");} /* pcic_interrupt */static void pcic_interrupt_wrapper(u_long data){    pcic_interrupt(0, NULL, NULL);    poll_timer.expires = jiffies + poll_interval;    add_timer(&poll_timer);}/*====================================================================*/static int pcic_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;} /* pcic_register_callback *//*====================================================================*/static int pcic_inquire_socket(unsigned int sock, socket_cap_t *cap){    *cap = socket[sock].cap;    return 0;} /* pcic_inquire_socket *//*====================================================================*/static int i365_get_status(u_short sock, u_int *value){    u_int status;        status = i365_get(sock, I365_STATUS);    *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)	? SS_DETECT : 0;    if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)	*value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;    else {	*value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;	*value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;    }    *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;    *value |= (status & I365_CS_READY) ? SS_READY : 0;    *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;#ifdef CONFIG_ISA    if (socket[sock].type == IS_VG469) {	status = i365_get(sock, VG469_VSENSE);	if (socket[sock].psock & 1) {	    *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD;	    *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD;	} else {	    *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD;	    *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;	}    }#endif        DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", sock, *value);    return 0;} /* i365_get_status *//*====================================================================*/static int i365_get_socket(u_short sock, socket_state_t *state){    socket_info_t *t = &socket[sock];    u_char reg, vcc, vpp;        reg = i365_get(sock, I365_POWER);    state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;    state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;    vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;    state->Vcc = state->Vpp = 0;    if (t->flags & IS_CIRRUS) {	if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) {	    if (reg & I365_VCC_5V) state->Vcc = 33;	    if (vpp == I365_VPP1_5V) state->Vpp = 33;	} else {	    if (reg & I365_VCC_5V) state->Vcc = 50;	    if (vpp == I365_VPP1_5V) state->Vpp = 50;	}	if (vpp == I365_VPP1_12V) state->Vpp = 120;    } else if (t->flags & IS_VG_PWR) {	if (i365_get(sock, VG469_VSELECT) & VG469_VSEL_VCC) {	    if (reg & I365_VCC_5V) state->Vcc = 33;	    if (vpp == I365_VPP1_5V) state->Vpp = 33;	} else {	    if (reg & I365_VCC_5V) state->Vcc = 50;	    if (vpp == I365_VPP1_5V) state->Vpp = 50;	}	if (vpp == I365_VPP1_12V) state->Vpp = 120;    } else if (t->flags & IS_DF_PWR) {	if (vcc == I365_VCC_3V) state->Vcc = 33;	if (vcc == I365_VCC_5V) state->Vcc = 50;	if (vpp == I365_VPP1_5V) state->Vpp = 50;	if (vpp == I365_VPP1_12V) state->Vpp = 120;    } else {	if (reg & I365_VCC_5V) {	    state->Vcc = 50;	    if (vpp == I365_VPP1_5V) state->Vpp = 50;	    if (vpp == I365_VPP1_12V) state->Vpp = 120;	}    }    /* IO card, RESET flags, IO interrupt */    reg = i365_get(sock, I365_INTCTL);    state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;    if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;    state->io_irq = reg & I365_IRQ_MASK;        /* speaker control */    if (t->flags & IS_CIRRUS) {	if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)	    state->flags |= SS_SPKR_ENA;    }    

⌨️ 快捷键说明

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