xref: /minix/minix/drivers/net/dpeth/8390.c (revision fb9c64b2)
1 /*
2 **  File:	8390.c		May  02, 2000
3 **
4 **  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
5 **
6 **  This file contains an ethernet device driver for NICs
7 **  equipped with the National Semiconductor NS 8390 chip.
8 **  It has to be associated with the board specific driver.
9 **  Rewritten from Minix 2.0.0 ethernet driver dp8390.c
10 **  to extract the NS 8390 common functions.
11 */
12 
13 #include <minix/drivers.h>
14 #include <minix/netdriver.h>
15 #include <assert.h>
16 #include "dp.h"
17 
18 #if (ENABLE_DP8390 == 1)
19 
20 #include "8390.h"
21 
22 /*
23 **  Name:	ns_rw_setup
24 **  Function:	Sets the board for reading/writing.
25 */
26 static void ns_rw_setup(const dpeth_t *dep, int mode, int size, u16_t offset)
27 {
28 
29   if (mode == CR_DM_RW) outb_reg0(dep, DP_ISR, ISR_RDC);
30   outb_reg0(dep, DP_RBCR0, size & 0xFF);
31   outb_reg0(dep, DP_RBCR1, (size >> 8) & 0xFF);
32   outb_reg0(dep, DP_RSAR0, offset & 0xFF);
33   outb_reg0(dep, DP_RSAR1, (offset >> 8) & 0xFF);
34   mode |= (CR_PS_P0 | CR_STA);
35   outb_reg0(dep, DP_CR, mode);
36 }
37 
38 /*
39 **  Name:	ns_start_xmit
40 **  Function:	Sets the board for for transmitting and fires it.
41 */
42 static void ns_start_xmit(const dpeth_t * dep, int size, int pageno)
43 {
44 
45   outb_reg0(dep, DP_TPSR, pageno);
46   outb_reg0(dep, DP_TBCR1, size >> 8);
47   outb_reg0(dep, DP_TBCR0, size & 0xFF);
48   outb_reg0(dep, DP_CR, CR_NO_DMA | CR_STA | CR_TXP);	/* Fires transmission */
49 }
50 
51 /*
52 **  Name:	mem_getblock
53 **  Function:	Reads a block of packet from board (shared memory).
54 */
55 static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
56 {
57 
58   assert(size >= 0);
59   assert(offset + (unsigned int)size <= dep->de_ramsize);
60 
61   memcpy(dst, dep->de_locmem + offset, size);
62 }
63 
64 /*
65 **  Name:	mem_nic2user
66 **  Function:	Copies a packet from board to user area (shared memory).
67 */
68 static void mem_nic2user(dpeth_t *dep, int pageno, struct netdriver_data *data,
69 	size_t size)
70 {
71   size_t offset, left;
72 
73   /* Computes shared memory address (skipping receive header) */
74   offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
75 
76   if (offset + size > dep->de_stoppage * DP_PAGESIZE) {
77 	left = dep->de_stoppage * DP_PAGESIZE - offset;
78 	netdriver_copyout(data, 0, dep->de_locmem + offset, left);
79 	offset = dep->de_startpage * DP_PAGESIZE;
80 	netdriver_copyout(data, left, dep->de_locmem + offset, size - left);
81   } else
82 	netdriver_copyout(data, 0, dep->de_locmem + offset, size);
83 }
84 
85 /*
86 **  Name:	mem_user2nic
87 **  Function:	Copies a packet from user area to board (shared memory).
88 */
89 static void mem_user2nic(dpeth_t *dep, int pageno, struct netdriver_data *data,
90 	size_t size)
91 {
92   size_t offset;
93 
94   /* Computes shared memory address */
95   offset = pageno * DP_PAGESIZE;
96 
97   netdriver_copyin(data, 0, dep->de_locmem + offset, size);
98 }
99 
100 /*
101 **  Name:	pio_getblock
102 **  Function:	Reads a block of packet from board (Prog. I/O).
103 */
104 static void pio_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
105 {
106 
107   /* Sets up board for reading */
108   ns_rw_setup(dep, CR_DM_RR, size, offset);
109 
110   if (dep->de_16bit == TRUE)
111 	insw(dep->de_data_port, dst, size);
112   else
113 	insb(dep->de_data_port, dst, size);
114 }
115 
116 /*
117 **  Name:	pio_nic2user
118 **  Function:	Copies a packet from board to user area (Prog. I/O).
119 */
120 static void pio_nic2user(dpeth_t *dep, int pageno, struct netdriver_data *data,
121 	size_t size)
122 {
123   size_t offset, left;
124 
125   /* Computes memory address (skipping receive header) */
126   offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
127 
128   if (offset + size > dep->de_stoppage * DP_PAGESIZE) {
129 	left = dep->de_stoppage * DP_PAGESIZE - offset;
130 
131 	ns_rw_setup(dep, CR_DM_RR, left, offset);
132 
133 	if (dep->de_16bit)
134 		netdriver_portinw(data, 0, dep->de_data_port, left);
135 	else
136 		netdriver_portinb(data, 0, dep->de_data_port, left);
137 
138 	offset = dep->de_startpage * DP_PAGESIZE;
139   } else
140 	left = 0;
141 
142   ns_rw_setup(dep, CR_DM_RR, size - left, offset);
143 
144   if (dep->de_16bit)
145 	netdriver_portinw(data, left, dep->de_data_port, size - left);
146   else
147 	netdriver_portinb(data, left, dep->de_data_port, size - left);
148 }
149 
150 /*
151 **  Name:	pio_user2nic
152 **  Function:	Copies a packet from user area to board (Prog. I/O).
153 */
154 static void pio_user2nic(dpeth_t *dep, int pageno, struct netdriver_data *data,
155 	size_t size)
156 {
157   int ix;
158 
159   /* Sets up board for writing */
160   ns_rw_setup(dep, CR_DM_RW, size, pageno * DP_PAGESIZE);
161 
162   if (dep->de_16bit)
163 	netdriver_portoutw(data, 0, dep->de_data_port, size);
164   else
165 	netdriver_portoutb(data, 0, dep->de_data_port, size);
166 
167   for (ix = 0; ix < 100; ix += 1) {
168 	if (inb_reg0(dep, DP_ISR) & ISR_RDC) break;
169   }
170   if (ix == 100)
171 	panic("remote dma failed to complete");
172 }
173 
174 /*
175 **  Name:	ns_stats
176 **  Function:	Updates counters reading from device
177 */
178 static void ns_stats(dpeth_t * dep)
179 {
180 
181   netdriver_stat_ierror(inb_reg0(dep, DP_CNTR0));
182   netdriver_stat_ierror(inb_reg0(dep, DP_CNTR1));
183   netdriver_stat_ierror(inb_reg0(dep, DP_CNTR2));
184 }
185 
186 /*
187 **  Name:	ns_dodump
188 **  Function:	Displays statistics (a request from a function key).
189 */
190 static void ns_dodump(dpeth_t * dep)
191 {
192 
193   ns_stats(dep);		/* Forces reading of counters from board */
194 }
195 
196 /*
197 **  Name:	ns_reinit
198 **  Function:	Updates receiver configuration.
199 */
200 static void ns_reinit(dpeth_t * dep)
201 {
202   int dp_reg = 0;
203 
204   if (dep->de_flags & DEF_PROMISC) dp_reg |= RCR_AB | RCR_PRO | RCR_AM;
205   if (dep->de_flags & DEF_BROAD) dp_reg |= RCR_AB;
206   if (dep->de_flags & DEF_MULTI) dp_reg |= RCR_AM;
207   outb_reg0(dep, DP_CR, CR_PS_P0);
208   outb_reg0(dep, DP_RCR, dp_reg);
209 }
210 
211 /*
212 **  Name:	ns_send
213 **  Function:	Transfers packet to device and starts sending.
214 */
215 static int ns_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
216 {
217   unsigned int queue;
218 
219   queue = dep->de_sendq_head;
220   if (dep->de_sendq[queue].sq_filled)
221 	return SUSPEND;
222 
223   (dep->de_user2nicf)(dep, dep->de_sendq[queue].sq_sendpage, data, size);
224   dep->bytes_Tx += (long) size;
225   dep->de_sendq[queue].sq_filled = TRUE;
226   dep->de_flags |= DEF_XMIT_BUSY;
227   if (dep->de_sendq_tail == queue) {	/* there it goes.. */
228 	ns_start_xmit(dep, size, dep->de_sendq[queue].sq_sendpage);
229   } else
230 	dep->de_sendq[queue].sq_size = size;
231 
232   if (++queue == dep->de_sendq_nr) queue = 0;
233   dep->de_sendq_head = queue;
234 
235   return OK;
236 }
237 
238 /*
239 **  Name:	ns_reset
240 **  Function:	Resets device.
241 */
242 static void ns_reset(dpeth_t * dep)
243 {
244   unsigned int ix;
245 
246   /* Stop chip */
247   outb_reg0(dep, DP_CR, CR_STP | CR_NO_DMA);
248   outb_reg0(dep, DP_RBCR0, 0);
249   outb_reg0(dep, DP_RBCR1, 0);
250   for (ix = 0; ix < 0x1000 && (inb_reg0(dep, DP_ISR) & ISR_RST) == 0; ix += 1)
251 	 /* Do nothing */ ;
252   outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST);
253   outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA);
254   outb_reg0(dep, DP_TCR, TCR_NORMAL | TCR_OFST);
255 
256   /* Acknowledge the ISR_RDC (remote dma) interrupt. */
257   for (ix = 0; ix < 0x1000 && (inb_reg0(dep, DP_ISR) & ISR_RDC) == 0; ix += 1)
258 	 /* Do nothing */ ;
259   outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & NOT(ISR_RDC));
260 
261   /* Reset the transmit ring. If we were transmitting a packet, we
262    * pretend that the packet is processed. Higher layers will
263    * retransmit if the packet wasn't actually sent. */
264   dep->de_sendq_head = dep->de_sendq_tail = 0;
265   for (ix = 0; ix < dep->de_sendq_nr; ix++)
266 	dep->de_sendq[ix].sq_filled = FALSE;
267   netdriver_send();
268 }
269 
270 /*
271 **  Name:	ns_recv
272 **  Function:	Gets a packet from device
273 */
274 static ssize_t ns_recv(dpeth_t *dep, struct netdriver_data *data, size_t max)
275 {
276   dp_rcvhdr_t header;
277   unsigned pageno, curr, next;
278   size_t length;
279   int packet_processed = FALSE;
280 #ifdef ETH_IGN_PROTO
281   u16_t eth_type;
282 #endif
283 
284   pageno = inb_reg0(dep, DP_BNRY) + 1;
285   if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
286 
287   do {
288 	/* */
289 	outb_reg0(dep, DP_CR, CR_PS_P1);
290 	curr = inb_reg1(dep, DP_CURR);
291 	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_NO_DMA | CR_STA);
292 
293 	if (curr == pageno)
294 		return SUSPEND;
295 
296 	(dep->de_getblockf)(dep, pageno * DP_PAGESIZE, sizeof(header),
297 	    &header);
298 #ifdef ETH_IGN_PROTO
299 	(dep->de_getblockf)(dep, pageno * DP_PAGESIZE + sizeof(header) +
300 	    2 * sizeof(netdriver_addr_t), sizeof(eth_type), &eth_type);
301 #endif
302 	length = (header.dr_rbcl | (header.dr_rbch << 8)) -
303 	    sizeof(dp_rcvhdr_t);
304 	next = header.dr_next;
305 
306 	if (length < NDEV_ETH_PACKET_MIN || length > max) {
307 		printf("%s: packet with strange length arrived: %zu\n",
308 			netdriver_name(), length);
309 		netdriver_stat_ierror(1);
310 		next = curr;
311 
312 	} else if (next < dep->de_startpage || next >= dep->de_stoppage) {
313 		printf("%s: strange next page\n", netdriver_name());
314 		netdriver_stat_ierror(1);
315 		next = curr;
316 #ifdef ETH_IGN_PROTO
317 	} else if (eth_type == eth_ign_proto) {
318 		/* Hack: ignore packets of a given protocol */
319 		static int first = TRUE;
320 		if (first) {
321 			first = FALSE;
322 			printf("%s: dropping proto %04x packet\n",
323 			    netdriver_name(), ntohs(eth_ign_proto));
324 		}
325 		next = curr;
326 #endif
327 	} else if (header.dr_status & RSR_FO) {
328 		/* This is very serious, issue a warning and reset buffers */
329 		printf("%s: fifo overrun, resetting receive buffer\n",
330 		    netdriver_name());
331 		netdriver_stat_ierror(1);
332 		next = curr;
333 
334 	} else if (header.dr_status & RSR_PRX) {
335 		(dep->de_nic2userf)(dep, pageno, data, length);
336 		packet_processed = TRUE;
337 	}
338 	dep->bytes_Rx += (long) length;
339 	outb_reg0(dep, DP_BNRY,
340 	    (next == dep->de_startpage ? dep->de_stoppage : next) - 1);
341 	pageno = next;
342   } while (!packet_processed);
343 
344   return length;
345 }
346 
347 /*
348 **  Name:	ns_interrupt
349 **  Function:	Handles interrupt.
350 */
351 static void ns_interrupt(dpeth_t * dep)
352 {
353   int isr, tsr;
354   unsigned int queue;
355 
356   while ((isr = inb_reg0(dep, DP_ISR)) != 0) {
357 
358 	outb_reg0(dep, DP_ISR, isr);
359 	if (isr & (ISR_PTX | ISR_TXE)) {
360 
361 		tsr = inb_reg0(dep, DP_TSR);
362 		if (tsr & TSR_PTX) {
363 			/* Packet transmission was successful. */
364 		}
365 		if (tsr & TSR_COL)
366 			netdriver_stat_coll(1);
367 		if (tsr & (TSR_ABT | TSR_FU)) {
368 			netdriver_stat_oerror(1);
369 		}
370 		if ((isr & ISR_TXE) || (tsr & (TSR_CRS | TSR_CDH | TSR_OWC))) {
371 			printf("%s: got send Error (0x%02X)\n",
372 			    netdriver_name(), tsr);
373 			netdriver_stat_oerror(1);
374 		}
375 		queue = dep->de_sendq_tail;
376 
377 		if (!(dep->de_sendq[queue].sq_filled)) { /* Hardware bug? */
378 			printf("%s: transmit interrupt, but not sending\n",
379 			    netdriver_name());
380 			continue;
381 		}
382 		dep->de_sendq[queue].sq_filled = FALSE;
383 		if (++queue == dep->de_sendq_nr) queue = 0;
384 		dep->de_sendq_tail = queue;
385 		if (dep->de_sendq[queue].sq_filled) {
386 			ns_start_xmit(dep, dep->de_sendq[queue].sq_size,
387 				dep->de_sendq[queue].sq_sendpage);
388 		}
389 		netdriver_send();
390 	}
391 	if (isr & ISR_PRX) {
392 		netdriver_recv();
393 	}
394 	if (isr & ISR_RXE) {
395 		printf("%s: got recv Error (0x%04X)\n",
396 		    netdriver_name(), inb_reg0(dep, DP_RSR));
397 		netdriver_stat_ierror(1);
398 	}
399 	if (isr & ISR_CNT) {
400 		ns_stats(dep);
401 	}
402 	if (isr & ISR_OVW) {
403 		printf("%s: got overwrite warning\n", netdriver_name());
404 	}
405 	if (isr & ISR_RDC) {
406 		/* Nothing to do */
407 	}
408 	if (isr & ISR_RST) {
409 		/* This means we got an interrupt but the ethernet chip is shut
410 		 * down. We reset the chip right away, possibly losing received
411 		 * packets in the process. There used to be a more elaborate
412 		 * approach of resetting only after all pending packets had
413 		 * been accepted, but it was broken and this is simpler anyway.
414 		 */
415 		printf("%s: network interface stopped\n",
416 		    netdriver_name());
417 		ns_reset(dep);
418 		break;
419 	}
420   }
421 }
422 
423 /*
424 **  Name:	ns_init
425 **  Function:	Initializes the NS 8390
426 */
427 void ns_init(dpeth_t * dep)
428 {
429   unsigned int dp_reg;
430   unsigned int ix;
431 
432   /* NS8390 initialization (as recommended in National Semiconductor specs) */
433   outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_NO_DMA);	/* 0x21 */
434   outb_reg0(dep, DP_DCR, (((dep->de_16bit) ? DCR_WORDWIDE : DCR_BYTEWIDE) |
435 			DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS));
436   outb_reg0(dep, DP_RBCR0, 0);
437   outb_reg0(dep, DP_RBCR1, 0);
438   outb_reg0(dep, DP_RCR, RCR_MON);	/* Sets Monitor mode */
439   outb_reg0(dep, DP_TCR, TCR_INTERNAL);	/* Sets Loopback mode 1 */
440   outb_reg0(dep, DP_PSTART, dep->de_startpage);
441   outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
442   outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
443   outb_reg0(dep, DP_ISR, 0xFF);	/* Clears Interrupt Status Register */
444   outb_reg0(dep, DP_IMR, 0);	/* Clears Interrupt Mask Register */
445 
446   /* Copies station address in page 1 registers */
447   outb_reg0(dep, DP_CR, CR_PS_P1 | CR_NO_DMA);	/* Selects Page 1 */
448   for (ix = 0; ix < SA_ADDR_LEN; ix += 1)	/* Initializes address */
449 	outb_reg1(dep, DP_PAR0 + ix, dep->de_address.na_addr[ix]);
450   for (ix = DP_MAR0; ix <= DP_MAR7; ix += 1)	/* Initializes address */
451 	outb_reg1(dep, ix, 0xFF);
452 
453   outb_reg1(dep, DP_CURR, dep->de_startpage);
454   outb_reg1(dep, DP_CR, CR_PS_P0 | CR_NO_DMA);	/* Selects Page 0 */
455 
456   inb_reg0(dep, DP_CNTR0);	/* Resets counters by reading them */
457   inb_reg0(dep, DP_CNTR1);
458   inb_reg0(dep, DP_CNTR2);
459 
460   dp_reg = IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE;
461   outb_reg0(dep, DP_ISR, 0xFF);	/* Clears Interrupt Status Register */
462   outb_reg0(dep, DP_IMR, dp_reg);	/* Sets Interrupt Mask register */
463 
464   dp_reg = 0;
465   if (dep->de_flags & DEF_PROMISC) dp_reg |= RCR_AB | RCR_PRO | RCR_AM;
466   if (dep->de_flags & DEF_BROAD) dp_reg |= RCR_AB;
467   if (dep->de_flags & DEF_MULTI) dp_reg |= RCR_AM;
468   outb_reg0(dep, DP_RCR, dp_reg);	/* Sets receive as requested */
469   outb_reg0(dep, DP_TCR, TCR_NORMAL);	/* Sets transmitter */
470 
471   outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA);	/* Starts board */
472 
473   /* Initializes the send queue. */
474   for (ix = 0; ix < dep->de_sendq_nr; ix += 1)
475 	dep->de_sendq[ix].sq_filled = 0;
476   dep->de_sendq_head = dep->de_sendq_tail = 0;
477 
478   /* Device specific functions */
479   if (!dep->de_prog_IO) {
480 	dep->de_user2nicf = mem_user2nic;
481 	dep->de_nic2userf = mem_nic2user;
482 	dep->de_getblockf = mem_getblock;
483   } else {
484 	dep->de_user2nicf = pio_user2nic;
485 	dep->de_nic2userf = pio_nic2user;
486 	dep->de_getblockf = pio_getblock;
487   }
488   dep->de_recvf = ns_recv;
489   dep->de_sendf = ns_send;
490   dep->de_flagsf = ns_reinit;
491   dep->de_resetf = ns_reset;
492   dep->de_getstatsf = ns_stats;
493   dep->de_dumpstatsf = ns_dodump;
494   dep->de_interruptf = ns_interrupt;
495 }
496 
497 #endif				/* ENABLE_DP8390 */
498 
499 /** end 8390.c **/
500