Преглед на файлове

[ne2k_isa] Restore support for ne2k isa cards

Add the simplified ne2k_isa driver.  It is just a selective copy+paste
of the relevant parts from ns8390.c plus a little trivial hacking to
make it actually work.

It is true that the code is pretty ugly, but:
  a) ns8390.c is worse
  b) It is only 372 lines and no #ifdefs
  c) It works both in qemu/bochs and in real hardware
     and we all know it is easier to cleanup working code

Hope someone will find the time to rewrite this driver properly,
but until then at least for me this is an ok solution.

Signed-off-by: Pantelis Koukousoulas <pktoss@gmail.com>
tags/v0.9.6
Pantelis Koukousoulas преди 15 години
родител
ревизия
dd34500188
променени са 2 файла, в които са добавени 374 реда и са изтрити 0 реда
  1. 373
    0
      src/drivers/net/ne2k_isa.c
  2. 1
    0
      src/include/gpxe/errfile.h

+ 373
- 0
src/drivers/net/ne2k_isa.c Целия файл

@@ -0,0 +1,373 @@
1
+/**************************************************************************
2
+ ETHERBOOT -  BOOTP/TFTP Bootstrap Program
3
+
4
+ Author: Martin Renters
5
+ Date: May/94
6
+
7
+ This code is based heavily on David Greenman's if_ed.c driver
8
+
9
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
10
+ This software may be used, modified, copied, distributed, and sold, in
11
+ both source and binary form provided that the above copyright and these
12
+ terms are retained. Under no circumstances are the authors responsible for
13
+ the proper functioning of this software, nor do the authors assume any
14
+ responsibility for damages incurred with its use.
15
+
16
+ Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
17
+ Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
18
+ Card Detect support adapted from the eCos driver (Christian Plessl <cplessl@ee.ethz.ch>)
19
+ Extracted from ns8390.c and adapted by Pantelis Koukousoulas <pktoss@gmail.com>
20
+ **************************************************************************/
21
+
22
+#include "ns8390.h"
23
+#include "etherboot.h"
24
+#include "nic.h"
25
+#include <gpxe/ethernet.h>
26
+#include <gpxe/isa.h>
27
+#include <errno.h>
28
+
29
+#define ASIC_PIO NE_DATA
30
+
31
+static unsigned char eth_vendor, eth_flags;
32
+static unsigned short eth_nic_base, eth_asic_base;
33
+static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
34
+static Address eth_bmem, eth_rmem;
35
+static unsigned char eth_drain_receiver;
36
+
37
+static struct nic_operations ne_operations;
38
+static void ne_reset(struct nic *nic, struct isa_device *isa);
39
+
40
+static isa_probe_addr_t ne_probe_addrs[] = { 0x300, 0x280, 0x320, 0x340, 0x380, 0x220, };
41
+
42
+/**************************************************************************
43
+ ETH_PIO_READ - Read a frame via Programmed I/O
44
+ **************************************************************************/
45
+static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) {
46
+	outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
47
+	outb(cnt, eth_nic_base + D8390_P0_RBCR0);
48
+	outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
49
+	outb(src, eth_nic_base + D8390_P0_RSAR0);
50
+	outb(src >> 8, eth_nic_base + D8390_P0_RSAR1);
51
+	outb(D8390_COMMAND_RD0 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
52
+	if (eth_flags & FLAG_16BIT)
53
+		cnt = (cnt + 1) >> 1;
54
+
55
+	while (cnt--) {
56
+		if (eth_flags & FLAG_16BIT) {
57
+			*((unsigned short *) dst) = inw(eth_asic_base + ASIC_PIO);
58
+			dst += 2;
59
+		} else
60
+			*(dst++) = inb(eth_asic_base + ASIC_PIO);
61
+	}
62
+}
63
+
64
+/**************************************************************************
65
+ ETH_PIO_WRITE - Write a frame via Programmed I/O
66
+ **************************************************************************/
67
+static void eth_pio_write(const unsigned char *src, unsigned int dst,
68
+		unsigned int cnt) {
69
+	outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
70
+	outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
71
+	outb(cnt, eth_nic_base + D8390_P0_RBCR0);
72
+	outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
73
+	outb(dst, eth_nic_base + D8390_P0_RSAR0);
74
+	outb(dst >> 8, eth_nic_base + D8390_P0_RSAR1);
75
+	outb(D8390_COMMAND_RD1 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
76
+	if (eth_flags & FLAG_16BIT)
77
+		cnt = (cnt + 1) >> 1;
78
+
79
+	while (cnt--) {
80
+
81
+		if (eth_flags & FLAG_16BIT) {
82
+			outw(*((unsigned short *) src), eth_asic_base + ASIC_PIO);
83
+			src += 2;
84
+		} else
85
+			outb(*(src++), eth_asic_base + ASIC_PIO);
86
+	}
87
+}
88
+
89
+/**************************************************************************
90
+ enable_multicast - Enable Multicast
91
+ **************************************************************************/
92
+static void enable_multicast(unsigned short eth_nic_base) {
93
+	unsigned char mcfilter[8];
94
+	int i;
95
+
96
+	memset(mcfilter, 0xFF, 8);
97
+	outb(4, eth_nic_base + D8390_P0_RCR);
98
+	outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
99
+	for (i = 0; i < 8; i++) {
100
+		outb(mcfilter[i], eth_nic_base + 8 + i);
101
+		if (inb(eth_nic_base + 8 + i) != mcfilter[i])
102
+			DBG("Error SMC 83C690 Multicast filter read/write mishap %d\n",
103
+					i);
104
+	}
105
+	outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
106
+	outb(4 | 0x08, eth_nic_base + D8390_P0_RCR);
107
+}
108
+
109
+/**************************************************************************
110
+ NE_PROBE1 - Look for an adapter on the ISA bus
111
+ **************************************************************************/
112
+static int ne_probe1(isa_probe_addr_t ioaddr) {
113
+	//From the eCos driver
114
+	unsigned int regd;
115
+	unsigned int state;
116
+
117
+	state = inb(ioaddr);
118
+	outb(ioaddr, D8390_COMMAND_RD2 | D8390_COMMAND_PS1 | D8390_COMMAND_STP);
119
+	regd = inb(ioaddr + D8390_P0_TCR);
120
+
121
+	if (inb(ioaddr + D8390_P0_TCR)) {
122
+		outb(ioaddr, state);
123
+		outb(ioaddr + 0x0d, regd);
124
+		return 0;
125
+	}
126
+
127
+	return 1;
128
+}
129
+
130
+/**************************************************************************
131
+ NE_PROBE - Initialize an adapter ???
132
+ **************************************************************************/
133
+static int ne_probe(struct nic *nic, struct isa_device *isa) {
134
+	int i;
135
+	unsigned char c;
136
+	unsigned char romdata[16];
137
+	unsigned char testbuf[32];
138
+
139
+	eth_vendor = VENDOR_NONE;
140
+	eth_drain_receiver = 0;
141
+
142
+	nic->irqno = 0;
143
+	nic->ioaddr = isa->ioaddr;
144
+	eth_nic_base = isa->ioaddr;
145
+
146
+	/******************************************************************
147
+	 Search for NE1000/2000 if no WD/SMC or 3com cards
148
+	 ******************************************************************/
149
+	if (eth_vendor == VENDOR_NONE) {
150
+
151
+		static unsigned char test[] = "NE*000 memory";
152
+
153
+		eth_bmem = 0; /* No shared memory */
154
+
155
+		eth_flags = FLAG_PIO;
156
+		eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
157
+		eth_memsize = MEM_16384;
158
+		eth_tx_start = 32;
159
+		eth_rx_start = 32 + D8390_TXBUF_SIZE;
160
+		c = inb(eth_asic_base + NE_RESET);
161
+		outb(c, eth_asic_base + NE_RESET);
162
+		(void) inb(0x84);
163
+		outb(D8390_COMMAND_STP | D8390_COMMAND_RD2, eth_nic_base
164
+				+ D8390_P0_COMMAND);
165
+		outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
166
+		outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
167
+		outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
168
+		outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
169
+		eth_pio_write((unsigned char *) test, 8192, sizeof(test));
170
+		eth_pio_read(8192, testbuf, sizeof(test));
171
+		if (!memcmp(test, testbuf, sizeof(test)))
172
+			goto out;
173
+		eth_flags |= FLAG_16BIT;
174
+		eth_memsize = MEM_32768;
175
+		eth_tx_start = 64;
176
+		eth_rx_start = 64 + D8390_TXBUF_SIZE;
177
+		outb(D8390_DCR_WTS | D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base
178
+				+ D8390_P0_DCR);
179
+		outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
180
+		outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
181
+		eth_pio_write((unsigned char *) test, 16384, sizeof(test));
182
+		eth_pio_read(16384, testbuf, sizeof(test));
183
+		if (!memcmp(testbuf, test, sizeof(test)))
184
+			goto out;
185
+
186
+
187
+out:
188
+		if (eth_nic_base == 0)
189
+			return (0);
190
+		if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
191
+			eth_flags |= FLAG_16BIT;
192
+		eth_vendor = VENDOR_NOVELL;
193
+		eth_pio_read(0, romdata, sizeof(romdata));
194
+		for (i = 0; i < ETH_ALEN; i++) {
195
+			nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
196
+		}
197
+		nic->ioaddr = eth_nic_base;
198
+		DBG("\nNE%c000 base %4.4x, MAC Addr %s\n",
199
+				(eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base, eth_ntoa(
200
+						nic->node_addr));
201
+	}
202
+
203
+	if (eth_vendor == VENDOR_NONE)
204
+		return (0);
205
+
206
+	if (eth_vendor != VENDOR_3COM)
207
+		eth_rmem = eth_bmem;
208
+
209
+	ne_reset(nic, isa);
210
+	nic->nic_op = &ne_operations;
211
+	return 1;
212
+}
213
+
214
+
215
+/**************************************************************************
216
+ NE_DISABLE - Turn off adapter
217
+ **************************************************************************/
218
+static void ne_disable(struct nic *nic, struct isa_device *isa) {
219
+	ne_reset(nic, isa);
220
+}
221
+
222
+
223
+/**************************************************************************
224
+ NE_RESET - Reset adapter
225
+ **************************************************************************/
226
+static void ne_reset(struct nic *nic, struct isa_device *isa __unused)
227
+{
228
+	int i;
229
+
230
+	eth_drain_receiver = 0;
231
+	outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
232
+			D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
233
+	if (eth_flags & FLAG_16BIT)
234
+	outb(0x49, eth_nic_base+D8390_P0_DCR);
235
+	else
236
+	outb(0x48, eth_nic_base+D8390_P0_DCR);
237
+	outb(0, eth_nic_base+D8390_P0_RBCR0);
238
+	outb(0, eth_nic_base+D8390_P0_RBCR1);
239
+	outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
240
+	outb(2, eth_nic_base+D8390_P0_TCR);
241
+	outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
242
+	outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
243
+
244
+	outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
245
+	outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
246
+	outb(0xFF, eth_nic_base+D8390_P0_ISR);
247
+	outb(0, eth_nic_base+D8390_P0_IMR);
248
+	outb(D8390_COMMAND_PS1 |
249
+			D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
250
+
251
+	for (i=0; i<ETH_ALEN; i++)
252
+	outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
253
+	for (i=0; i<ETH_ALEN; i++)
254
+	outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
255
+	outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
256
+	outb(D8390_COMMAND_PS0 |
257
+			D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
258
+	outb(0xFF, eth_nic_base+D8390_P0_ISR);
259
+	outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
260
+	outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
261
+
262
+	enable_multicast(eth_nic_base);
263
+}
264
+
265
+
266
+/**************************************************************************
267
+ NE_POLL - Wait for a frame
268
+ **************************************************************************/
269
+static int ne_poll(struct nic *nic __unused, int retrieve __unused)
270
+{
271
+	int ret = 0;
272
+	unsigned char rstat, curr, next;
273
+	unsigned short len, frag;
274
+	unsigned short pktoff;
275
+	unsigned char *p;
276
+	struct ringbuffer pkthdr;
277
+
278
+	rstat = inb(eth_nic_base+D8390_P0_RSR);
279
+	if (!(rstat & D8390_RSTAT_PRX)) return(0);
280
+	next = inb(eth_nic_base+D8390_P0_BOUND)+1;
281
+	if (next >= eth_memsize) next = eth_rx_start;
282
+	outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
283
+	curr = inb(eth_nic_base+D8390_P1_CURR);
284
+	outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
285
+	if (curr >= eth_memsize) curr=eth_rx_start;
286
+	if (curr == next) return(0);
287
+
288
+	if ( ! retrieve ) return 1;
289
+
290
+	pktoff = next << 8;
291
+	if (eth_flags & FLAG_PIO)
292
+	eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
293
+	else
294
+	memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
295
+	pktoff += sizeof(pkthdr);
296
+	/* incoming length includes FCS so must sub 4 */
297
+	len = pkthdr.len - 4;
298
+	if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
299
+			|| len> ETH_FRAME_LEN) {
300
+		DBG("Bogus packet, ignoring\n");
301
+		return (0);
302
+	}
303
+	else {
304
+		p = nic->packet;
305
+		nic->packetlen = len; /* available to caller */
306
+		frag = (eth_memsize << 8) - pktoff;
307
+		if (len> frag) { /* We have a wrap-around */
308
+			/* read first part */
309
+			if (eth_flags & FLAG_PIO)
310
+			eth_pio_read(pktoff, p, frag);
311
+			else
312
+			memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
313
+			pktoff = eth_rx_start << 8;
314
+			p += frag;
315
+			len -= frag;
316
+		}
317
+		/* read second part */
318
+		if (eth_flags & FLAG_PIO)
319
+		eth_pio_read(pktoff, p, len);
320
+		else
321
+		memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
322
+		ret = 1;
323
+	}
324
+	next = pkthdr.next; /* frame number of next packet */
325
+	if (next == eth_rx_start)
326
+	next = eth_memsize;
327
+	outb(next-1, eth_nic_base+D8390_P0_BOUND);
328
+	return(ret);
329
+}
330
+
331
+
332
+/**************************************************************************
333
+ NE_TRANSMIT - Transmit a frame
334
+ **************************************************************************/
335
+static void ne_transmit(struct nic *nic, const char *d, /* Destination */
336
+unsigned int t, /* Type */
337
+unsigned int s, /* size */
338
+const char *p) { /* Packet */
339
+
340
+	/* Programmed I/O */
341
+	unsigned short type;
342
+	type = (t >> 8) | (t << 8);
343
+	eth_pio_write((unsigned char *) d, eth_tx_start << 8, ETH_ALEN);
344
+	eth_pio_write(nic->node_addr, (eth_tx_start << 8) + ETH_ALEN, ETH_ALEN);
345
+	/* bcc generates worse code without (const+const) below */
346
+	eth_pio_write((unsigned char *) &type, (eth_tx_start << 8) + (ETH_ALEN
347
+			+ ETH_ALEN), 2);
348
+	eth_pio_write((unsigned char *) p, (eth_tx_start << 8) + ETH_HLEN, s);
349
+	s += ETH_HLEN;
350
+	if (s < ETH_ZLEN)
351
+		s = ETH_ZLEN;
352
+
353
+	outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STA,
354
+			eth_nic_base + D8390_P0_COMMAND);
355
+	outb(eth_tx_start, eth_nic_base + D8390_P0_TPSR);
356
+	outb(s, eth_nic_base + D8390_P0_TBCR0);
357
+	outb(s >> 8, eth_nic_base + D8390_P0_TBCR1);
358
+
359
+	outb(D8390_COMMAND_PS0 | D8390_COMMAND_TXP | D8390_COMMAND_RD2
360
+			| D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
361
+}
362
+
363
+static struct nic_operations ne_operations = { .connect = dummy_connect,
364
+		.poll = ne_poll, .transmit = ne_transmit, .irq = dummy_irq,
365
+};
366
+
367
+ISA_DRIVER ( ne_driver, ne_probe_addrs, ne_probe1,
368
+		GENERIC_ISAPNP_VENDOR, 0x0600 );
369
+
370
+DRIVER ( "ne", nic_driver, isapnp_driver, ne_driver,
371
+		ne_probe, ne_disable );
372
+
373
+ISA_ROM("ne","NE1000/2000 and clones");

+ 1
- 0
src/include/gpxe/errfile.h Целия файл

@@ -106,6 +106,7 @@
106 106
 #define ERRFILE_e1000_hw	     ( ERRFILE_DRIVER | 0x00490000 )
107 107
 #define ERRFILE_mtnic		     ( ERRFILE_DRIVER | 0x004a0000 )
108 108
 #define ERRFILE_phantom		     ( ERRFILE_DRIVER | 0x004b0000 )
109
+#define ERRFILE_ne2k_isa	     ( ERRFILE_DRIVER | 0x004c0000 )
109 110
 
110 111
 #define ERRFILE_scsi		     ( ERRFILE_DRIVER | 0x00700000 )
111 112
 #define ERRFILE_arbel		     ( ERRFILE_DRIVER | 0x00710000 )

Loading…
Отказ
Запис