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

📄 wavelan.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *	WaveLAN ISA driver * *		Jean II - HPLB '96 * * Reorganisation and extension of the driver. * Original copyright follows (also see the end of this file). * See wavelan.p.h for details. * * * * AT&T GIS (nee NCR) WaveLAN card: *	An Ethernet-like radio transceiver *	controlled by an Intel 82586 coprocessor. */#include "wavelan.p.h"		/* Private header *//************************* MISC SUBROUTINES **************************//* * Subroutines which won't fit in one of the following category * (WaveLAN modem or i82586) *//*------------------------------------------------------------------*//* * Translate irq number to PSA irq parameter */static u8 wv_irq_to_psa(int irq){	if (irq < 0 || irq >= NELS(irqvals))		return 0;	return irqvals[irq];}/*------------------------------------------------------------------*//* * Translate PSA irq parameter to irq number  */static int __init wv_psa_to_irq(u8 irqval){	int irq;	for (irq = 0; irq < NELS(irqvals); irq++)		if (irqvals[irq] == irqval)			return irq;	return -1;}#ifdef STRUCT_CHECK/*------------------------------------------------------------------*//* * Sanity routine to verify the sizes of the various WaveLAN interface * structures. */static char *wv_struct_check(void){#define	SC(t,s,n)	if (sizeof(t) != s) return(n);	SC(psa_t, PSA_SIZE, "psa_t");	SC(mmw_t, MMW_SIZE, "mmw_t");	SC(mmr_t, MMR_SIZE, "mmr_t");	SC(ha_t, HA_SIZE, "ha_t");#undef	SC	return ((char *) NULL);}				/* wv_struct_check */#endif				/* STRUCT_CHECK *//********************* HOST ADAPTER SUBROUTINES *********************//* * Useful subroutines to manage the WaveLAN ISA interface * * One major difference with the PCMCIA hardware (except the port mapping) * is that we have to keep the state of the Host Control Register * because of the interrupt enable & bus size flags. *//*------------------------------------------------------------------*//* * Read from card's Host Adaptor Status Register. */static inline u16 hasr_read(unsigned long ioaddr){	return (inw(HASR(ioaddr)));}				/* hasr_read *//*------------------------------------------------------------------*//* * Write to card's Host Adapter Command Register. */static inline void hacr_write(unsigned long ioaddr, u16 hacr){	outw(hacr, HACR(ioaddr));}				/* hacr_write *//*------------------------------------------------------------------*//* * Write to card's Host Adapter Command Register. Include a delay for * those times when it is needed. */static inline void hacr_write_slow(unsigned long ioaddr, u16 hacr){	hacr_write(ioaddr, hacr);	/* delay might only be needed sometimes */	mdelay(1);}				/* hacr_write_slow *//*------------------------------------------------------------------*//* * Set the channel attention bit. */static inline void set_chan_attn(unsigned long ioaddr, u16 hacr){	hacr_write(ioaddr, hacr | HACR_CA);}				/* set_chan_attn *//*------------------------------------------------------------------*//* * Reset, and then set host adaptor into default mode. */static inline void wv_hacr_reset(unsigned long ioaddr){	hacr_write_slow(ioaddr, HACR_RESET);	hacr_write(ioaddr, HACR_DEFAULT);}				/* wv_hacr_reset *//*------------------------------------------------------------------*//* * Set the I/O transfer over the ISA bus to 8-bit mode */static inline void wv_16_off(unsigned long ioaddr, u16 hacr){	hacr &= ~HACR_16BITS;	hacr_write(ioaddr, hacr);}				/* wv_16_off *//*------------------------------------------------------------------*//* * Set the I/O transfer over the ISA bus to 8-bit mode */static inline void wv_16_on(unsigned long ioaddr, u16 hacr){	hacr |= HACR_16BITS;	hacr_write(ioaddr, hacr);}				/* wv_16_on *//*------------------------------------------------------------------*//* * Disable interrupts on the WaveLAN hardware. * (called by wv_82586_stop()) */static inline void wv_ints_off(struct net_device * dev){	net_local *lp = (net_local *) dev->priv;	unsigned long ioaddr = dev->base_addr;		lp->hacr &= ~HACR_INTRON;	hacr_write(ioaddr, lp->hacr);}				/* wv_ints_off *//*------------------------------------------------------------------*//* * Enable interrupts on the WaveLAN hardware. * (called by wv_hw_reset()) */static inline void wv_ints_on(struct net_device * dev){	net_local *lp = (net_local *) dev->priv;	unsigned long ioaddr = dev->base_addr;	lp->hacr |= HACR_INTRON;	hacr_write(ioaddr, lp->hacr);}				/* wv_ints_on *//******************* MODEM MANAGEMENT SUBROUTINES *******************//* * Useful subroutines to manage the modem of the WaveLAN *//*------------------------------------------------------------------*//* * Read the Parameter Storage Area from the WaveLAN card's memory *//* * Read bytes from the PSA. */static void psa_read(unsigned long ioaddr, u16 hacr, int o,	/* offset in PSA */		     u8 * b,	/* buffer to fill */		     int n){				/* size to read */	wv_16_off(ioaddr, hacr);	while (n-- > 0) {		outw(o, PIOR2(ioaddr));		o++;		*b++ = inb(PIOP2(ioaddr));	}	wv_16_on(ioaddr, hacr);}				/* psa_read *//*------------------------------------------------------------------*//* * Write the Parameter Storage Area to the WaveLAN card's memory. */static void psa_write(unsigned long ioaddr, u16 hacr, int o,	/* Offset in PSA */		      u8 * b,	/* Buffer in memory */		      int n){				/* Length of buffer */	int count = 0;	wv_16_off(ioaddr, hacr);	while (n-- > 0) {		outw(o, PIOR2(ioaddr));		o++;		outb(*b, PIOP2(ioaddr));		b++;		/* Wait for the memory to finish its write cycle */		count = 0;		while ((count++ < 100) &&		       (hasr_read(ioaddr) & HASR_PSA_BUSY)) mdelay(1);	}	wv_16_on(ioaddr, hacr);}				/* psa_write */#ifdef SET_PSA_CRC/*------------------------------------------------------------------*//* * Calculate the PSA CRC * Thanks to Valster, Nico <NVALSTER@wcnd.nl.lucent.com> for the code * NOTE: By specifying a length including the CRC position the * returned value should be zero. (i.e. a correct checksum in the PSA) * * The Windows drivers don't use the CRC, but the AP and the PtP tool * depend on it. */static inline u16 psa_crc(u8 * psa,	/* The PSA */			      int size){				/* Number of short for CRC */	int byte_cnt;		/* Loop on the PSA */	u16 crc_bytes = 0;	/* Data in the PSA */	int bit_cnt;		/* Loop on the bits of the short */	for (byte_cnt = 0; byte_cnt < size; byte_cnt++) {		crc_bytes ^= psa[byte_cnt];	/* Its an xor */		for (bit_cnt = 1; bit_cnt < 9; bit_cnt++) {			if (crc_bytes & 0x0001)				crc_bytes = (crc_bytes >> 1) ^ 0xA001;			else				crc_bytes >>= 1;		}	}	return crc_bytes;}				/* psa_crc */#endif				/* SET_PSA_CRC *//*------------------------------------------------------------------*//* * update the checksum field in the Wavelan's PSA */static void update_psa_checksum(struct net_device * dev, unsigned long ioaddr, u16 hacr){#ifdef SET_PSA_CRC	psa_t psa;	u16 crc;	/* read the parameter storage area */	psa_read(ioaddr, hacr, 0, (unsigned char *) &psa, sizeof(psa));	/* update the checksum */	crc = psa_crc((unsigned char *) &psa,		      sizeof(psa) - sizeof(psa.psa_crc[0]) -		      sizeof(psa.psa_crc[1])		      - sizeof(psa.psa_crc_status));	psa.psa_crc[0] = crc & 0xFF;	psa.psa_crc[1] = (crc & 0xFF00) >> 8;	/* Write it ! */	psa_write(ioaddr, hacr, (char *) &psa.psa_crc - (char *) &psa,		  (unsigned char *) &psa.psa_crc, 2);#ifdef DEBUG_IOCTL_INFO	printk(KERN_DEBUG "%s: update_psa_checksum(): crc = 0x%02x%02x\n",	       dev->name, psa.psa_crc[0], psa.psa_crc[1]);	/* Check again (luxury !) */	crc = psa_crc((unsigned char *) &psa,		      sizeof(psa) - sizeof(psa.psa_crc_status));	if (crc != 0)		printk(KERN_WARNING		       "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n",		       dev->name);#endif				/* DEBUG_IOCTL_INFO */#endif				/* SET_PSA_CRC */}				/* update_psa_checksum *//*------------------------------------------------------------------*//* * Write 1 byte to the MMC. */static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d){	int count = 0;	/* Wait for MMC to go idle */	while ((count++ < 100) && (inw(HASR(ioaddr)) & HASR_MMC_BUSY))		udelay(10);	outw((u16) (((u16) d << 8) | (o << 1) | 1), MMCR(ioaddr));}/*------------------------------------------------------------------*//* * Routine to write bytes to the Modem Management Controller. * We start at the end because it is the way it should be! */static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n){	o += n;	b += n;	while (n-- > 0)		mmc_out(ioaddr, --o, *(--b));}				/* mmc_write *//*------------------------------------------------------------------*//* * Read a byte from the MMC. * Optimised version for 1 byte, avoid using memory. */static inline u8 mmc_in(unsigned long ioaddr, u16 o){	int count = 0;	while ((count++ < 100) && (inw(HASR(ioaddr)) & HASR_MMC_BUSY))		udelay(10);	outw(o << 1, MMCR(ioaddr));	while ((count++ < 100) && (inw(HASR(ioaddr)) & HASR_MMC_BUSY))		udelay(10);	return (u8) (inw(MMCR(ioaddr)) >> 8);}/*------------------------------------------------------------------*//* * Routine to read bytes from the Modem Management Controller. * The implementation is complicated by a lack of address lines, * which prevents decoding of the low-order bit. * (code has just been moved in the above function) * We start at the end because it is the way it should be! */static inline void mmc_read(unsigned long ioaddr, u8 o, u8 * b, int n){	o += n;	b += n;	while (n-- > 0)		*(--b) = mmc_in(ioaddr, --o);}				/* mmc_read *//*------------------------------------------------------------------*//* * Get the type of encryption available. */static inline int mmc_encr(unsigned long ioaddr){				/* I/O port of the card */	int temp;	temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail));	if ((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES))		return 0;	else		return temp;}/*------------------------------------------------------------------*//* * Wait for the frequency EEPROM to complete a command. * I hope this one will be optimally inlined. */static inline void fee_wait(unsigned long ioaddr,	/* I/O port of the card */			    int delay,	/* Base delay to wait for */			    int number){				/* Number of time to wait */	int count = 0;		/* Wait only a limited time */	while ((count++ < number) &&	       (mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &		MMR_FEE_STATUS_BUSY)) udelay(delay);}/*------------------------------------------------------------------*//* * Read bytes from the Frequency EEPROM (frequency select cards). */static void fee_read(unsigned long ioaddr,	/* I/O port of the card */		     u16 o,	/* destination offset */		     u16 * b,	/* data buffer */		     int n){				/* number of registers */	b += n;			/* Position at the end of the area */	/* Write the address */	mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);	/* Loop on all buffer */	while (n-- > 0) {		/* Write the read command */		mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),			MMW_FEE_CTRL_READ);		/* Wait until EEPROM is ready (should be quick). */		fee_wait(ioaddr, 10, 100);		/* Read the value. */		*--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) |			mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));	}}#ifdef WIRELESS_EXT		/* if the wireless extension exists in the kernel *//*------------------------------------------------------------------*//* * Write bytes from the Frequency EEPROM (frequency select cards). * This is a bit complicated, because the frequency EEPROM has to * be unprotected and the write enabled. * Jean II */static void fee_write(unsigned long ioaddr,	/* I/O port of the card */		      u16 o,	/* destination offset */		      u16 * b,	/* data buffer */		      int n){				/* number of registers */	b += n;			/* Position at the end of the area. */#ifdef EEPROM_IS_PROTECTED	/* disabled */#ifdef DOESNT_SEEM_TO_WORK	/* disabled */	/* Ask to read the protected register */	mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD);	fee_wait(ioaddr, 10, 100);	/* Read the protected register. */	printk("Protected 2:  %02X-%02X\n",	       mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)),

⌨️ 快捷键说明

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