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

📄 pcic.c

📁 WaveLAN无线网卡Linux驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	 */	cinfo.mapmem = pcic_memory;	cinfo.mapio = pcic_io;	cinfo.ioctl = pcic_ioctl;	cinfo.power = pcic_power;	cinfo.mapirq = pcic_mapirq;	cinfo.reset = pcic_reset;	cinfo.disable = pcic_disable;	cinfo.resume = pcic_resume;	cinfo.maxmem = PCIC_MEM_WIN;	cinfo.maxio = PCIC_IO_WIN;	cinfo.irqs = free_irqs;	cinfo.imask = &pcic_imask;#ifdef	LKM	bzero(pcic_slots, sizeof(pcic_slots));#endif	sp = pcic_slots;	for (slotnum = 0; slotnum < PCIC_MAX_SLOTS; slotnum++, sp++) {		/*		 *	Initialise the PCIC slot table.		 */		sp->getb = getb1;		sp->putb = putb1;		if (slotnum < 4) {			sp->index = PCIC_INDEX_0;			sp->data = PCIC_DATA_0;			sp->offset = slotnum * PCIC_SLOT_SIZE;		} else {			sp->index = PCIC_INDEX_1;			sp->data = PCIC_DATA_1;			sp->offset = (slotnum - 4) * PCIC_SLOT_SIZE;		}		/* 		 * XXX - Screwed up slot 1 on the VLSI chips.  According to		 * the Linux PCMCIA code from David Hinds, working chipsets		 * return 0x84 from their (correct) ID ports, while the broken		 * ones would need to be probed at the new offset we set after		 * we assume it's broken.		 */		if (slotnum == 1 && maybe_vlsi && sp->getb(sp, PCIC_ID_REV) != 0x84) {			sp->index += 4;			sp->data += 4;			sp->offset = PCIC_SLOT_SIZE << 1;		}		/*		 * see if there's a PCMCIA controller here		 * Intel PCMCIA controllers use 0x82 and 0x83		 * IBM clone chips use 0x88 and 0x89, apparently		 */		c = sp->getb(sp, PCIC_ID_REV);		sp->revision = -1;		switch(c) {		/*		 *	82365 or clones.		 */		case 0x82:		case 0x83:			sp->controller = PCIC_I82365;			sp->revision = c & 1;			/*			 *	Now check for VADEM chips.			 */			outb(sp->index, 0x0E);			outb(sp->index, 0x37);			setb(sp, 0x3A, 0x40);			c = sp->getb(sp, PCIC_ID_REV);			if (c & 0x08) {				sp->controller = ((sp->revision = c & 7) == 4) ?						PCIC_VG469 : PCIC_VG468 ;				clrb(sp, 0x3A, 0x40);			}			/*			 * Check for RICOH RF5C396 PCMCIA Controller			 */			c = sp->getb(sp, 0x3a);			if (c == 0xb2) {				sp->controller = PCIC_RF5C396;			}			break;		/*		 *	VLSI chips.		 */		case 0x84:			sp->controller = PCIC_VLSI;			maybe_vlsi = 1;			break;		case 0x88:		case 0x89:			sp->controller = PCIC_IBM;			sp->revision = c & 1;			break;		case 0x8a:			sp->controller = PCIC_IBM_KING;			sp->revision = c & 1;			break;		default:			continue;		}		/*		 *	Check for Cirrus logic chips.		 */		sp->putb(sp, 0x1F, 0);		c = sp->getb(sp, 0x1F);		if ((c & 0xC0) == 0xC0) {			c = sp->getb(sp, 0x1F);			if ((c & 0xC0) == 0) {				if (c & 0x20)					sp->controller = PCIC_PD672X;				else					sp->controller = PCIC_PD6710;				sp->revision = 8 - ((c & 0x1F) >> 2);			}		}		switch(sp->controller) {		case PCIC_I82365:			cinfo.name = "Intel 82365";			break;		case PCIC_IBM:			cinfo.name = "IBM PCIC";			break;		case PCIC_IBM_KING:			cinfo.name = "IBM KING PCMCIA Controller";			break;		case PCIC_PD672X:			cinfo.name = "Cirrus Logic PD672X";			break;		case PCIC_PD6710:			cinfo.name = "Cirrus Logic PD6710";			break;		case PCIC_VG468:			cinfo.name = "Vadem 468";			break;		case PCIC_VG469:			cinfo.name = "Vadem 469";			break;		case PCIC_RF5C396:			cinfo.name = "Ricoh RF5C396";			break;		case PCIC_VLSI:			cinfo.name = "VLSI 82C146";			break;		default:			cinfo.name = "Unknown!";			break;		}		/*		 *	OK it seems we have a PCIC or lookalike.		 *	Allocate a slot and initialise the data structures.		 */		validslots++;		sp->slotnum = slotnum;		slt = pccard_alloc_slot(&cinfo);		if (slt == 0)			continue;		slt->cdata = sp;		sp->slt = slt;		/*		 *	If we haven't allocated an interrupt for the controller,		 *	then attempt to get one.		 */		if (pcic_irq == 0) {			pcic_imask = SWI_MASK;			pcic_irq = pccard_alloc_intr(free_irqs,				pcicintr, 0, &pcic_imask, NULL);			if (pcic_irq < 0)				printf("pcic: failed to allocate IRQ\n");			else				printf("pcic: controller irq %d\n", pcic_irq);		}		/*		 * Modem cards send the speaker audio (dialing noises)		 * to the host's speaker.  Cirrus Logic PCIC chips must		 * enable this.  There is also a Low Power Dynamic Mode bit		 * that claims to reduce power consumption by 30%, so		 * enable it and hope for the best.		 */		if (sp->controller == PCIC_PD672X) {			setb(sp, PCIC_MISC1, PCIC_SPKR_EN);			setb(sp, PCIC_MISC2, PCIC_LPDM_EN);		}		/*		 *	Check for a card in this slot.		 */		setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST);		if ((sp->getb(sp, PCIC_STATUS) & PCIC_CD) != PCIC_CD) {			slt->laststate = slt->state = empty;		} else {			slt->laststate = slt->state = filled;			pccard_event(sp->slt, card_inserted);		}		/*		 *	Assign IRQ for slot changes		 */		if (pcic_irq > 0)			sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF);	}#ifdef	PC98	if (validslots == 0) {	    sp = pcic_slots;	    slotnum = 0;	    if (inb(PCIC98_REG0) != 0xff) {		sp->controller = PCIC_PC98;		sp->revision = 0;		cinfo.name = "PC98 Original";		cinfo.maxmem = 1;		cinfo.maxio = 1;/*		cinfo.irqs = PCIC_INT_MASK_ALLOWED;*/		cinfo.irqs = 0x1468;		validslots++;		sp->slotnum = slotnum;		slt = pccard_alloc_slot(&cinfo);		if (slt == 0) {		    printf("pcic98: slt == NULL\n");		    goto pcic98_probe_end;		}		slt->cdata = sp;		sp->slt = slt;		/* Check for a card in this slot */		if (inb(PCIC98_REG1) & PCIC98_CARDEXIST) {		    /* PCMCIA card exist */		    slt->laststate = slt->state = filled;		    pccard_event(sp->slt, card_inserted);		} else {		    slt->laststate = slt->state = empty;		}	    }	pcic98_probe_end:	}#endif	/* PC98 */	if (validslots)		timeout(pcictimeout, 0, hz/2);	return(validslots);}/* *	ioctl calls - Controller specific ioctls */static intpcic_ioctl(struct slot *slt, int cmd, caddr_t data){	struct pcic_slot *sp = slt->cdata;	switch(cmd) {	default:		return(EINVAL);	/*	 * Get/set PCIC registers	 */	case PIOCGREG:		((struct pcic_reg *)data)->value =			sp->getb(sp, ((struct pcic_reg *)data)->reg);		break;	case PIOCSREG:		sp->putb(sp, ((struct pcic_reg *)data)->reg,			((struct pcic_reg *)data)->value);		break;	}	return(0);}/* *	pcic_power - Enable the power of the slot according to *	the parameters in the power structure(s). */static intpcic_power(struct slot *slt){	unsigned char reg = PCIC_DISRST|PCIC_PCPWRE;	struct pcic_slot *sp = slt->cdata;	switch(sp->controller) {#ifdef	PC98	case PCIC_PC98:	    reg = inb(PCIC98_REG6) & (~PCIC98_VPP12V);	    switch(slt->pwr.vpp) {	    default:		return(EINVAL);	    case 50:		break;	    case 120:		reg |= PCIC98_VPP12V;		break;	    }	    outb(PCIC98_REG6, reg);	    DELAY(100*1000);	    reg = inb(PCIC98_REG2) & (~PCIC98_VCC3P3V);	    switch(slt->pwr.vcc) {	    default:		return(EINVAL);	    case 33:		reg |= PCIC98_VCC3P3V;		break;	    case 50:		break;	    }	    outb(PCIC98_REG2, reg);	    DELAY(100*1000);	    return (0);#endif	case PCIC_PD672X:	case PCIC_PD6710:	case PCIC_VG468:	case PCIC_VG469:	case PCIC_RF5C396:	case PCIC_VLSI:	case PCIC_IBM_KING:		switch(slt->pwr.vpp) {		default:			return(EINVAL);		case 0:			break;		case 50:		case 33:			reg |= PCIC_VPP_5V;			break;		case 120:			reg |= PCIC_VPP_12V;			break;		}		switch(slt->pwr.vcc) {		default:			return(EINVAL);		case 0:			break;		case 33:			if (sp->controller == PCIC_IBM_KING) {				reg |= PCIC_VCC_5V_KING;				break;			}			reg |= PCIC_VCC_3V;			if ((sp->controller == PCIC_VG468)||				(sp->controller == PCIC_VG469))				setb(sp, 0x2f, 0x03) ;			else				setb(sp, 0x16, 0x02);			break;		case 50:                        if (sp->controller == PCIC_IBM_KING) {                                reg |= PCIC_VCC_5V_KING;                                break;                        }			reg |= PCIC_VCC_5V;			if ((sp->controller == PCIC_VG468)||				(sp->controller == PCIC_VG469))				clrb(sp, 0x2f, 0x03) ;			else				clrb(sp, 0x16, 0x02);			break;		}		break;	}	sp->putb(sp, PCIC_POWER, reg);	DELAY(300*1000);	if (slt->pwr.vcc) {		reg |= PCIC_OUTENA;		sp->putb(sp, PCIC_POWER, reg);		DELAY(100*1000);	}	/* Some chips are smarter than us it seems, so if we weren't	 * allowed to use 5V, try 3.3 instead	 */	if (!(sp->getb(sp, PCIC_STATUS) &  0x40) && slt->pwr.vcc == 50) {		slt->pwr.vcc = 33;		slt->pwr.vpp = 0;		return (pcic_power(slt));	}	return(0);}/* * tell the PCIC which irq we want to use.  only the following are legal: * 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 */static voidpcic_mapirq(struct slot *slt, int irq){	struct pcic_slot *sp = slt->cdata;#ifdef	PC98	if (sp->controller == PCIC_PC98) {	    unsigned char x;	    switch (irq) {	    case 3:		x = PCIC98_INT0; break;	    case 5:		x = PCIC98_INT1; break;	    case 6:		x = PCIC98_INT2; break;	    case 10:		x = PCIC98_INT4; break;	    case 12:		x = PCIC98_INT5; break;	    case 0:		/* disable */		x = PCIC98_INTDISABLE;		break;	    default:		printf("pcic98: illegal irq %d\n", irq);		return;	    }#ifdef	PCIC_DEBUG	    printf("pcic98: irq=%d mapped.\n", irq);#endif	    outb(PCIC98_REG3, x);	    return;	}	#endif	if (irq == 0)		clrb(sp, PCIC_INT_GEN, 0xF);	else		sp->putb(sp, PCIC_INT_GEN, 		    (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq);}/* *	pcic_reset - Reset the card and enable initial power. */static voidpcic_reset(void *chan){	struct slot *slt = chan;	struct pcic_slot *sp = slt->cdata;#ifdef	PC98	if (sp->controller == PCIC_PC98) {	    outb(PCIC98_REG0, 0);	    outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_IOMEMORY));	    outb(PCIC98_REG3, PCIC98_INTDISABLE);	    outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_VCC3P3V));	    outb(PCIC98_REG6, inb(PCIC98_REG6) & (~PCIC98_VPP12V));	    outb(PCIC98_REG1, 0);	    selwakeup(&slt->selp);	    return;	}#endif	switch (slt->insert_seq) {	    case 0: /* Something funny happended on the way to the pub... */		return;	    case 1: /* Assert reset */		clrb(sp, PCIC_INT_GEN, PCIC_CARDRESET);		slt->insert_seq = 2;		timeout(pcic_reset, (void *)slt, hz/4);		return;	    case 2: /* Deassert it again */		setb(sp, PCIC_INT_GEN, PCIC_CARDRESET|PCIC_IOCARD);		slt->insert_seq = 3;		timeout(pcic_reset, (void *)slt, hz/4);		return;	    case 3: /* Wait if card needs more time */		if (!sp->getb(sp, PCIC_STATUS) & PCIC_READY) {			timeout(pcic_reset, (void *)slt, hz/10);			return;		}	}	slt->insert_seq = 0;	if (sp->controller == PCIC_PD672X || sp->controller == PCIC_PD6710) {		sp->putb(sp, PCIC_TIME_SETUP0, 0x1);		sp->putb(sp, PCIC_TIME_CMD0, 0x6);		sp->putb(sp, PCIC_TIME_RECOV0, 0x0);		sp->putb(sp, PCIC_TIME_SETUP1, 1);		sp->putb(sp, PCIC_TIME_CMD1, 0xf);		sp->putb(sp, PCIC_TIME_RECOV1, 0);	}	selwakeup(&slt->selp);}/* *	pcic_disable - Disable the slot. */static voidpcic_disable(struct slot *slt){	struct pcic_slot *sp = slt->cdata;#ifdef	PC98	if (sp->controller == PCIC_PC98) {	    return;	}#endif	sp->putb(sp, PCIC_INT_GEN, 0);	sp->putb(sp, PCIC_POWER, 0);}/* *	PCIC timer, it seems that we lose interrupts sometimes *	so poll just in case... */static voidpcictimeout(void *chan){	pcicintr(0);	timeout(pcictimeout, 0, hz/2);}/* *	PCIC Interrupt handler. *	Check each slot in turn, and read the card status change *	register. If this is non-zero, then a change has occurred *	on this card, so send an event to the main code. */static voidpcicintr(int unit){	int	slot, s;	unsigned char chg;	struct pcic_slot *sp = pcic_slots;#ifdef	PC98	if (sp->controller == PCIC_PC98) {	    slot = 0;	    s = splhigh();	    /* Check for a card in this slot */	    if (inb(PCIC98_REG1) & PCIC98_CARDEXIST) {		if (sp->slt->laststate != filled) {		    pccard_event(sp->slt, card_inserted);		}	    } else {		if (sp->slt->laststate != empty) {		    pccard_event(sp->slt, card_removed);		}	    }	    splx(s);	    return;	}#endif	/* PC98 */	s = splhigh();	for (slot = 0; slot < PCIC_MAX_SLOTS; slot++, sp++)		if (sp->slt && (chg = sp->getb(sp, PCIC_STAT_CHG)) != 0)			if (chg & PCIC_CDTCH) {				if ((sp->getb(sp, PCIC_STATUS) & PCIC_CD) ==						PCIC_CD) {					pccard_event(sp->slt, card_inserted);				} else {					pccard_event(sp->slt, card_removed);				}			}	splx(s);}/* *	pcic_resume - Suspend/resume support for PCIC */static voidpcic_resume(struct slot *slt){	struct pcic_slot *sp = slt->cdata;	if (pcic_irq > 0)		sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF);	if (sp->controller == PCIC_PD672X) {		setb(sp, PCIC_MISC1, PCIC_SPKR_EN);		setb(sp, PCIC_MISC2, PCIC_LPDM_EN);	}}

⌨️ 快捷键说明

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