|
|
1.1 ! root 1: #include <linux/if_ether.h> ! 2: #include <linux/types.h> ! 3: #include <asm/io.h> ! 4: ! 5: struct net_local { ! 6: #ifdef __KERNEL__ ! 7: struct enet_statistics stats; ! 8: #endif ! 9: ushort saved_tx_size; ! 10: unsigned char ! 11: re_tx, /* Number of packet retransmissions. */ ! 12: tx_unit_busy, ! 13: addr_mode, /* Current Rx filter e.g. promiscuous, etc. */ ! 14: pac_cnt_in_tx_buf; ! 15: }; ! 16: ! 17: struct rx_header { ! 18: ushort pad; /* The first read is always corrupted. */ ! 19: ushort rx_count; ! 20: ushort rx_status; /* Unknown bit assignments :-<. */ ! 21: ushort cur_addr; /* Apparently the current buffer address(?) */ ! 22: }; ! 23: ! 24: #define PAR_DATA 0 ! 25: #define PAR_STATUS 1 ! 26: #define PAR_CONTROL 2 ! 27: ! 28: #define Ctrl_LNibRead 0x08 /* LP_PSELECP */ ! 29: #define Ctrl_HNibRead 0 ! 30: #define Ctrl_LNibWrite 0x08 /* LP_PSELECP */ ! 31: #define Ctrl_HNibWrite 0 ! 32: #define Ctrl_SelData 0x04 /* LP_PINITP */ ! 33: #define Ctrl_IRQEN 0x10 /* LP_PINTEN */ ! 34: ! 35: #define EOW 0xE0 ! 36: #define EOC 0xE0 ! 37: #define WrAddr 0x40 /* Set address of EPLC read, write register. */ ! 38: #define RdAddr 0xC0 ! 39: #define HNib 0x10 ! 40: ! 41: enum page0_regs ! 42: { ! 43: /* The first six registers hold the ethernet physical station address. */ ! 44: PAR0 = 0, PAR1 = 1, PAR2 = 2, PAR3 = 3, PAR4 = 4, PAR5 = 5, ! 45: TxCNT0 = 6, TxCNT1 = 7, /* The transmit byte count. */ ! 46: TxSTAT = 8, RxSTAT = 9, /* Tx and Rx status. */ ! 47: ISR = 10, IMR = 11, /* Interrupt status and mask. */ ! 48: CMR1 = 12, /* Command register 1. */ ! 49: CMR2 = 13, /* Command register 2. */ ! 50: MAR = 14, /* Memory address register. */ ! 51: CMR2_h = 0x1d, }; ! 52: ! 53: enum eepage_regs ! 54: { PROM_CMD = 6, PROM_DATA = 7 }; /* Note that PROM_CMD is in the "high" bits. */ ! 55: ! 56: ! 57: #define ISR_TxOK 0x01 ! 58: #define ISR_RxOK 0x04 ! 59: #define ISR_TxErr 0x02 ! 60: #define ISRh_RxErr 0x11 /* ISR, high nibble */ ! 61: ! 62: #define CMR1h_RESET 0x04 /* Reset. */ ! 63: #define CMR1h_RxENABLE 0x02 /* Rx unit enable. */ ! 64: #define CMR1h_TxENABLE 0x01 /* Tx unit enable. */ ! 65: #define CMR1h_TxRxOFF 0x00 ! 66: #define CMR1_ReXmit 0x08 /* Trigger a retransmit. */ ! 67: #define CMR1_Xmit 0x04 /* Trigger a transmit. */ ! 68: #define CMR1_IRQ 0x02 /* Interrupt active. */ ! 69: #define CMR1_BufEnb 0x01 /* Enable the buffer(?). */ ! 70: #define CMR1_NextPkt 0x01 /* Enable the buffer(?). */ ! 71: ! 72: #define CMR2_NULL 8 ! 73: #define CMR2_IRQOUT 9 ! 74: #define CMR2_RAMTEST 10 ! 75: #define CMR2_EEPROM 12 /* Set to page 1, for reading the EEPROM. */ ! 76: ! 77: #define CMR2h_OFF 0 /* No accept mode. */ ! 78: #define CMR2h_Physical 1 /* Accept a physical address match only. */ ! 79: #define CMR2h_Normal 2 /* Accept physical and broadcast address. */ ! 80: #define CMR2h_PROMISC 3 /* Promiscuous mode. */ ! 81: ! 82: /* An inline function used below: it differs from inb() by explicitly return an unsigned ! 83: char, saving a truncation. */ ! 84: extern inline unsigned char inbyte(unsigned short port) ! 85: { ! 86: unsigned char _v; ! 87: __asm__ __volatile__ ("inb %w1,%b0" :"=a" (_v):"d" (port)); ! 88: return _v; ! 89: } ! 90: ! 91: /* Read register OFFSET. ! 92: This command should always be terminated with read_end(). */ ! 93: extern inline unsigned char read_nibble(short port, unsigned char offset) ! 94: { ! 95: unsigned char retval; ! 96: outb(EOC+offset, port + PAR_DATA); ! 97: outb(RdAddr+offset, port + PAR_DATA); ! 98: inbyte(port + PAR_STATUS); /* Settling time delay */ ! 99: retval = inbyte(port + PAR_STATUS); ! 100: outb(EOC+offset, port + PAR_DATA); ! 101: ! 102: return retval; ! 103: } ! 104: ! 105: /* Functions for bulk data read. The interrupt line is always disabled. */ ! 106: /* Get a byte using read mode 0, reading data from the control lines. */ ! 107: extern inline unsigned char read_byte_mode0(short ioaddr) ! 108: { ! 109: unsigned char low_nib; ! 110: ! 111: outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL); ! 112: inbyte(ioaddr + PAR_STATUS); ! 113: low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; ! 114: outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL); ! 115: inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ ! 116: inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ ! 117: return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); ! 118: } ! 119: ! 120: /* The same as read_byte_mode0(), but does multiple inb()s for stability. */ ! 121: extern inline unsigned char read_byte_mode2(short ioaddr) ! 122: { ! 123: unsigned char low_nib; ! 124: ! 125: outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL); ! 126: inbyte(ioaddr + PAR_STATUS); ! 127: low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; ! 128: outb(Ctrl_HNibRead, ioaddr + PAR_CONTROL); ! 129: inbyte(ioaddr + PAR_STATUS); /* Settling time delay -- needed! */ ! 130: return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); ! 131: } ! 132: ! 133: /* Read a byte through the data register. */ ! 134: extern inline unsigned char read_byte_mode4(short ioaddr) ! 135: { ! 136: unsigned char low_nib; ! 137: ! 138: outb(RdAddr | MAR, ioaddr + PAR_DATA); ! 139: low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; ! 140: outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA); ! 141: return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); ! 142: } ! 143: ! 144: /* Read a byte through the data register, double reading to allow settling. */ ! 145: extern inline unsigned char read_byte_mode6(short ioaddr) ! 146: { ! 147: unsigned char low_nib; ! 148: ! 149: outb(RdAddr | MAR, ioaddr + PAR_DATA); ! 150: inbyte(ioaddr + PAR_STATUS); ! 151: low_nib = (inbyte(ioaddr + PAR_STATUS) >> 3) & 0x0f; ! 152: outb(RdAddr | HNib | MAR, ioaddr + PAR_DATA); ! 153: inbyte(ioaddr + PAR_STATUS); ! 154: return low_nib | ((inbyte(ioaddr + PAR_STATUS) << 1) & 0xf0); ! 155: } ! 156: ! 157: extern inline void ! 158: write_reg(short port, unsigned char reg, unsigned char value) ! 159: { ! 160: unsigned char outval; ! 161: outb(EOC | reg, port + PAR_DATA); ! 162: outval = WrAddr | reg; ! 163: outb(outval, port + PAR_DATA); ! 164: outb(outval, port + PAR_DATA); /* Double write for PS/2. */ ! 165: ! 166: outval &= 0xf0; ! 167: outval |= value; ! 168: outb(outval, port + PAR_DATA); ! 169: outval &= 0x1f; ! 170: outb(outval, port + PAR_DATA); ! 171: outb(outval, port + PAR_DATA); ! 172: ! 173: outb(EOC | outval, port + PAR_DATA); ! 174: } ! 175: ! 176: extern inline void ! 177: write_reg_high(short port, unsigned char reg, unsigned char value) ! 178: { ! 179: unsigned char outval = EOC | HNib | reg; ! 180: ! 181: outb(outval, port + PAR_DATA); ! 182: outval &= WrAddr | HNib | 0x0f; ! 183: outb(outval, port + PAR_DATA); ! 184: outb(outval, port + PAR_DATA); /* Double write for PS/2. */ ! 185: ! 186: outval = WrAddr | HNib | value; ! 187: outb(outval, port + PAR_DATA); ! 188: outval &= HNib | 0x0f; /* HNib | value */ ! 189: outb(outval, port + PAR_DATA); ! 190: outb(outval, port + PAR_DATA); ! 191: ! 192: outb(EOC | HNib | outval, port + PAR_DATA); ! 193: } ! 194: ! 195: /* Write a byte out using nibble mode. The low nibble is written first. */ ! 196: extern inline void ! 197: write_reg_byte(short port, unsigned char reg, unsigned char value) ! 198: { ! 199: unsigned char outval; ! 200: outb(EOC | reg, port + PAR_DATA); /* Reset the address register. */ ! 201: outval = WrAddr | reg; ! 202: outb(outval, port + PAR_DATA); ! 203: outb(outval, port + PAR_DATA); /* Double write for PS/2. */ ! 204: ! 205: outb((outval & 0xf0) | (value & 0x0f), port + PAR_DATA); ! 206: outb(value & 0x0f, port + PAR_DATA); ! 207: value >>= 4; ! 208: outb(value, port + PAR_DATA); ! 209: outb(0x10 | value, port + PAR_DATA); ! 210: outb(0x10 | value, port + PAR_DATA); ! 211: ! 212: outb(EOC | value, port + PAR_DATA); /* Reset the address register. */ ! 213: } ! 214: ! 215: /* ! 216: * Bulk data writes to the packet buffer. The interrupt line remains enabled. ! 217: * The first, faster method uses only the dataport (data modes 0, 2 & 4). ! 218: * The second (backup) method uses data and control regs (modes 1, 3 & 5). ! 219: * It should only be needed when there is skew between the individual data ! 220: * lines. ! 221: */ ! 222: extern inline void write_byte_mode0(short ioaddr, unsigned char value) ! 223: { ! 224: outb(value & 0x0f, ioaddr + PAR_DATA); ! 225: outb((value>>4) | 0x10, ioaddr + PAR_DATA); ! 226: } ! 227: ! 228: extern inline void write_byte_mode1(short ioaddr, unsigned char value) ! 229: { ! 230: outb(value & 0x0f, ioaddr + PAR_DATA); ! 231: outb(Ctrl_IRQEN | Ctrl_LNibWrite, ioaddr + PAR_CONTROL); ! 232: outb((value>>4) | 0x10, ioaddr + PAR_DATA); ! 233: outb(Ctrl_IRQEN | Ctrl_HNibWrite, ioaddr + PAR_CONTROL); ! 234: } ! 235: ! 236: /* Write 16bit VALUE to the packet buffer: the same as above just doubled. */ ! 237: extern inline void write_word_mode0(short ioaddr, unsigned short value) ! 238: { ! 239: outb(value & 0x0f, ioaddr + PAR_DATA); ! 240: value >>= 4; ! 241: outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA); ! 242: value >>= 4; ! 243: outb(value & 0x0f, ioaddr + PAR_DATA); ! 244: value >>= 4; ! 245: outb((value & 0x0f) | 0x10, ioaddr + PAR_DATA); ! 246: } ! 247: ! 248: /* EEPROM_Ctrl bits. */ ! 249: #define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ ! 250: #define EE_CS 0x02 /* EEPROM chip select. */ ! 251: #define EE_CLK_HIGH 0x12 ! 252: #define EE_CLK_LOW 0x16 ! 253: #define EE_DATA_WRITE 0x01 /* EEPROM chip data in. */ ! 254: #define EE_DATA_READ 0x08 /* EEPROM chip data out. */ ! 255: ! 256: /* Delay between EEPROM clock transitions. */ ! 257: #define eeprom_delay(ticks) \ ! 258: do { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) ! 259: ! 260: /* The EEPROM commands include the alway-set leading bit. */ ! 261: #define EE_WRITE_CMD(offset) (((5 << 6) + (offset)) << 17) ! 262: #define EE_READ(offset) (((6 << 6) + (offset)) << 17) ! 263: #define EE_ERASE(offset) (((7 << 6) + (offset)) << 17) ! 264: #define EE_CMD_SIZE 27 /* The command+address+data size. */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.