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