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

📄 smsc-ircc2.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Fill FIFO with current frame */	while (fifo_size-- > 0 && actual < len) {		/* Transmit next byte */		outb(buf[actual], iobase + UART_TX);		actual++;	}	return actual;}/* * Function smsc_ircc_is_receiving (self) * *    Returns true is we are currently receiving data * */static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self){	return (self->rx_buff.state != OUTSIDE_FRAME);}/* * Function smsc_ircc_probe_transceiver(self) * *    Tries to find the used Transceiver * */static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self){	unsigned int	i;	IRDA_ASSERT(self != NULL, return;);	for (i = 0; smsc_transceivers[i].name != NULL; i++)		if (smsc_transceivers[i].probe(self->io.fir_base)) {			IRDA_MESSAGE(" %s transceiver found\n",				     smsc_transceivers[i].name);			self->transceiver= i + 1;			return;		}	IRDA_MESSAGE("No transceiver found. Defaulting to %s\n",		     smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name);	self->transceiver = SMSC_IRCC2_C_DEFAULT_TRANSCEIVER;}/* * Function smsc_ircc_set_transceiver_for_speed(self, speed) * *    Set the transceiver according to the speed * */static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed){	unsigned int trx;	trx = self->transceiver;	if (trx > 0)		smsc_transceivers[trx - 1].set_for_speed(self->io.fir_base, speed);}/* * Function smsc_ircc_wait_hw_transmitter_finish () * *    Wait for the real end of HW transmission * * The UART is a strict FIFO, and we get called only when we have finished * pushing data to the FIFO, so the maximum amount of time we must wait * is only for the FIFO to drain out. * * We use a simple calibrated loop. We may need to adjust the loop * delay (udelay) to balance I/O traffic and latency. And we also need to * adjust the maximum timeout. * It would probably be better to wait for the proper interrupt, * but it doesn't seem to be available. * * We can't use jiffies or kernel timers because : * 1) We are called from the interrupt handler, which disable softirqs, * so jiffies won't be increased * 2) Jiffies granularity is usually very coarse (10ms), and we don't * want to wait that long to detect stuck hardware. * Jean II */static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self){	int iobase = self->io.sir_base;	int count = SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US;	/* Calibrated busy loop */	while (count-- > 0 && !(inb(iobase + UART_LSR) & UART_LSR_TEMT))		udelay(1);	if (count == 0)		IRDA_DEBUG(0, "%s(): stuck transmitter\n", __FUNCTION__);}/* PROBING * * */static int __init smsc_ircc_look_for_chips(void){	struct smsc_chip_address *address;	char *type;	unsigned int cfg_base, found;	found = 0;	address = possible_addresses;	while (address->cfg_base) {		cfg_base = address->cfg_base;		/*printk(KERN_WARNING "%s(): probing: 0x%02x for: 0x%02x\n", __FUNCTION__, cfg_base, address->type);*/		if (address->type & SMSCSIO_TYPE_FDC) {			type = "FDC";			if (address->type & SMSCSIO_TYPE_FLAT)				if (!smsc_superio_flat(fdc_chips_flat, cfg_base, type))					found++;			if (address->type & SMSCSIO_TYPE_PAGED)				if (!smsc_superio_paged(fdc_chips_paged, cfg_base, type))					found++;		}		if (address->type & SMSCSIO_TYPE_LPC) {			type = "LPC";			if (address->type & SMSCSIO_TYPE_FLAT)				if (!smsc_superio_flat(lpc_chips_flat, cfg_base, type))					found++;			if (address->type & SMSCSIO_TYPE_PAGED)				if (!smsc_superio_paged(lpc_chips_paged, cfg_base, type))					found++;		}		address++;	}	return found;}/* * Function smsc_superio_flat (chip, base, type) * *    Try to get configuration of a smc SuperIO chip with flat register model * */static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfgbase, char *type){	unsigned short firbase, sirbase;	u8 mode, dma, irq;	int ret = -ENODEV;	IRDA_DEBUG(1, "%s\n", __FUNCTION__);	if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type) == NULL)		return ret;	outb(SMSCSIOFLAT_UARTMODE0C_REG, cfgbase);	mode = inb(cfgbase + 1);	/*printk(KERN_WARNING "%s(): mode: 0x%02x\n", __FUNCTION__, mode);*/	if (!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA))		IRDA_WARNING("%s(): IrDA not enabled\n", __FUNCTION__);	outb(SMSCSIOFLAT_UART2BASEADDR_REG, cfgbase);	sirbase = inb(cfgbase + 1) << 2;	/* FIR iobase */	outb(SMSCSIOFLAT_FIRBASEADDR_REG, cfgbase);	firbase = inb(cfgbase + 1) << 3;	/* DMA */	outb(SMSCSIOFLAT_FIRDMASELECT_REG, cfgbase);	dma = inb(cfgbase + 1) & SMSCSIOFLAT_FIRDMASELECT_MASK;	/* IRQ */	outb(SMSCSIOFLAT_UARTIRQSELECT_REG, cfgbase);	irq = inb(cfgbase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;	IRDA_MESSAGE("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", __FUNCTION__, firbase, sirbase, dma, irq, mode);	if (firbase && smsc_ircc_open(firbase, sirbase, dma, irq) == 0)		ret = 0;	/* Exit configuration */	outb(SMSCSIO_CFGEXITKEY, cfgbase);	return ret;}/* * Function smsc_superio_paged (chip, base, type) * *    Try  to get configuration of a smc SuperIO chip with paged register model * */static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type){	unsigned short fir_io, sir_io;	int ret = -ENODEV;	IRDA_DEBUG(1, "%s\n", __FUNCTION__);	if (smsc_ircc_probe(cfg_base, 0x20, chips, type) == NULL)		return ret;	/* Select logical device (UART2) */	outb(0x07, cfg_base);	outb(0x05, cfg_base + 1);	/* SIR iobase */	outb(0x60, cfg_base);	sir_io = inb(cfg_base + 1) << 8;	outb(0x61, cfg_base);	sir_io |= inb(cfg_base + 1);	/* Read FIR base */	outb(0x62, cfg_base);	fir_io = inb(cfg_base + 1) << 8;	outb(0x63, cfg_base);	fir_io |= inb(cfg_base + 1);	outb(0x2b, cfg_base); /* ??? */	if (fir_io && smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0)		ret = 0;	/* Exit configuration */	outb(SMSCSIO_CFGEXITKEY, cfg_base);	return ret;}static int __init smsc_access(unsigned short cfg_base, unsigned char reg){	IRDA_DEBUG(1, "%s\n", __FUNCTION__);	outb(reg, cfg_base);	return inb(cfg_base) != reg ? -1 : 0;}static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type){	u8 devid, xdevid, rev;	IRDA_DEBUG(1, "%s\n", __FUNCTION__);	/* Leave configuration */	outb(SMSCSIO_CFGEXITKEY, cfg_base);	if (inb(cfg_base) == SMSCSIO_CFGEXITKEY)	/* not a smc superio chip */		return NULL;	outb(reg, cfg_base);	xdevid = inb(cfg_base + 1);	/* Enter configuration */	outb(SMSCSIO_CFGACCESSKEY, cfg_base);	#if 0	if (smsc_access(cfg_base,0x55))	/* send second key and check */		return NULL;	#endif	/* probe device ID */	if (smsc_access(cfg_base, reg))		return NULL;	devid = inb(cfg_base + 1);	if (devid == 0 || devid == 0xff)	/* typical values for unused port */		return NULL;	/* probe revision ID */	if (smsc_access(cfg_base, reg + 1))		return NULL;	rev = inb(cfg_base + 1);	if (rev >= 128)			/* i think this will make no sense */		return NULL;	if (devid == xdevid)		/* protection against false positives */		return NULL;	/* Check for expected device ID; are there others? */	while (chip->devid != devid) {		chip++;		if (chip->name == NULL)			return NULL;	}	IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",		     devid, rev, cfg_base, type, chip->name);	if (chip->rev > rev) {		IRDA_MESSAGE("Revision higher than expected\n");		return NULL;	}	if (chip->flags & NoIRDA)		IRDA_MESSAGE("chipset does not support IRDA\n");	return chip;}static int __init smsc_superio_fdc(unsigned short cfg_base){	int ret = -1;	if (!request_region(cfg_base, 2, driver_name)) {		IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n",			     __FUNCTION__, cfg_base);	} else {		if (!smsc_superio_flat(fdc_chips_flat, cfg_base, "FDC") ||		    !smsc_superio_paged(fdc_chips_paged, cfg_base, "FDC"))			ret =  0;		release_region(cfg_base, 2);	}	return ret;}static int __init smsc_superio_lpc(unsigned short cfg_base){	int ret = -1;	if (!request_region(cfg_base, 2, driver_name)) {		IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n",			     __FUNCTION__, cfg_base);	} else {		if (!smsc_superio_flat(lpc_chips_flat, cfg_base, "LPC") ||		    !smsc_superio_paged(lpc_chips_paged, cfg_base, "LPC"))			ret = 0;		release_region(cfg_base, 2);	}	return ret;}/************************************************ * * Transceivers specific functions * ************************************************//* * Function smsc_ircc_set_transceiver_smsc_ircc_atc(fir_base, speed) * *    Program transceiver through smsc-ircc ATC circuitry * */static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed){	unsigned long jiffies_now, jiffies_timeout;	u8 val;	jiffies_now = jiffies;	jiffies_timeout = jiffies + SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES;	/* ATC */	register_bank(fir_base, 4);	outb((inb(fir_base + IRCC_ATC) & IRCC_ATC_MASK) | IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE,	     fir_base + IRCC_ATC);	while ((val = (inb(fir_base + IRCC_ATC) & IRCC_ATC_nPROGREADY)) &&		!time_after(jiffies, jiffies_timeout))		/* empty */;	if (val)		IRDA_WARNING("%s(): ATC: 0x%02x\n", __FUNCTION__,			     inb(fir_base + IRCC_ATC));}/* * Function smsc_ircc_probe_transceiver_smsc_ircc_atc(fir_base) * *    Probe transceiver smsc-ircc ATC circuitry * */static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base){	return 0;}/* * Function smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(self, speed) * *    Set transceiver * */static void smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(int fir_base, u32 speed){	u8 fast_mode;	switch (speed) {	default:	case 576000 :		fast_mode = 0;		break;	case 1152000 :	case 4000000 :		fast_mode = IRCC_LCR_A_FAST;		break;	}	register_bank(fir_base, 0);	outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast_mode, fir_base + IRCC_LCR_A);}/* * Function smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(fir_base) * *    Probe transceiver * */static int smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(int fir_base){	return 0;}/* * Function smsc_ircc_set_transceiver_toshiba_sat1800(fir_base, speed) * *    Set transceiver * */static void smsc_ircc_set_transceiver_toshiba_sat1800(int fir_base, u32 speed){	u8 fast_mode;	switch (speed) {	default:	case 576000 :		fast_mode = 0;		break;	case 1152000 :	case 4000000 :		fast_mode = /*IRCC_LCR_A_FAST |*/ IRCC_LCR_A_GP_DATA;		break;	}	/* This causes an interrupt */	register_bank(fir_base, 0);	outb((inb(fir_base + IRCC_LCR_A) &  0xbf) | fast_mode, fir_base + IRCC_LCR_A);}/* * Function smsc_ircc_probe_transceiver_toshiba_sat1800(fir_base) * *    Probe transceiver * */static int smsc_ircc_probe_transceiver_toshiba_sat1800(int fir_base){	return 0;}module_init(smsc_ircc_init);module_exit(smsc_ircc_cleanup);

⌨️ 快捷键说明

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