xref: /minix3/minix/drivers/net/dpeth/dp.c (revision 03ac74ede908465cc64c671bbd209e761dc765dc)
1 /*
2 **  File:	dp.c	Version 1.01,	Oct. 17, 2007
3 **  Original:	eth.c	Version 1.00,	Jan. 14, 1997
4 **
5 **  Author:	Giovanni Falzoni <gfalzoni@inwind.it>
6 **
7 **  This file contains the ethernet device driver main task.
8 **  It has to be integrated with the board specific drivers.
9 **  It is a rewriting of Minix 2.0.0 ethernet driver (dp8390.c)
10 **  to remove bord specific code. It should operate (I hope)
11 **  with any board driver.
12 */
13 
14 #include <minix/drivers.h>
15 #include <minix/netdriver.h>
16 #include <minix/endpoint.h>
17 #include <sys/mman.h>
18 #include <assert.h>
19 
20 #include "dp.h"
21 
22 /*
23 **  Local data
24 */
25 static dpeth_t de_state;
26 
27 typedef struct dp_conf {	/* Configuration description structure */
28   port_t dpc_port;
29   int dpc_irq;
30   phys_bytes dpc_mem;
31 } dp_conf_t;
32 
33 /* Device default configuration */
34 #define DP_CONF_NR 3
35 static dp_conf_t dp_conf[DP_CONF_NR] = {
36   /* I/O port, IRQ, Buff addr, Env. var */
37   {     0x300,   5,   0xC8000,  },
38   {     0x280,  10,   0xCC000,  },
39   {     0x000,   0,   0x00000,  },
40 };
41 
42 static int do_init(unsigned int instance, netdriver_addr_t *addr,
43 	uint32_t *caps, unsigned int *ticks);
44 static void do_stop(void);
45 static void do_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list,
46 	unsigned int mcast_count);
47 static int do_send(struct netdriver_data *data, size_t size);
48 static ssize_t do_recv(struct netdriver_data *data, size_t max);
49 static void do_intr(unsigned int mask);
50 static void do_tick(void);
51 static void do_other(const message *m_ptr, int ipc_status);
52 
53 static const struct netdriver dp_table = {
54 	.ndr_name	= "dpe",
55 	.ndr_init	= do_init,
56 	.ndr_stop	= do_stop,
57 	.ndr_set_mode	= do_set_mode,
58 	.ndr_recv	= do_recv,
59 	.ndr_send	= do_send,
60 	.ndr_intr	= do_intr,
61 	.ndr_tick	= do_tick,
62 	.ndr_other	= do_other
63 };
64 
65 /*
66 **  Name:	update_conf
67 **  Function:	Gets the default settings from 'dp_conf' table and
68 **  		modifies them from the environment.
69 */
70 static void update_conf(dpeth_t * dep, const dp_conf_t * dcp,
71 	unsigned int instance)
72 {
73   static char dpc_fmt[] = "x:d:x";
74   char ec_key[16];
75   long val;
76 
77   strlcpy(ec_key, "DPETH0", sizeof(ec_key));
78   ec_key[5] += instance;
79 
80   val = dcp->dpc_port;		/* Get I/O port address */
81   env_parse(ec_key, dpc_fmt, 0, &val, 0x000L, 0x3FFL);
82   dep->de_base_port = val;
83 
84   val = dcp->dpc_irq | DEI_DEFAULT;	/* Get Interrupt line (IRQ) */
85   env_parse(ec_key, dpc_fmt, 1, &val, 0L, (long) NR_IRQ_VECTORS - 1);
86   dep->de_irq = val;
87 
88   val = dcp->dpc_mem;		/* Get shared memory address */
89   env_parse(ec_key, dpc_fmt, 2, &val, 0L, LONG_MAX);
90   dep->de_linmem = val;
91 }
92 
93 /*
94 **  Name:	do_dump
95 **  Function:	Displays statistics on screen (SFx key from console)
96 */
97 static void do_dump(void)
98 {
99   dpeth_t *dep;
100 
101   dep = &de_state;
102 
103   printf("\n\n");
104 
105   printf("%s statistics:\t\t", netdriver_name());
106 
107   /* Network interface status  */
108   printf("Status: 0x%04x\n\n", dep->de_flags);
109 
110   (*dep->de_dumpstatsf)(dep);
111 
112   /* Transmitted/received bytes */
113   printf("Tx bytes:%10ld\t", dep->bytes_Tx);
114   printf("Rx bytes:%10ld\n", dep->bytes_Rx);
115 }
116 
117 /*
118 **  Name:	do_first_init
119 **  Function:	Init action to setup task
120 */
121 static void do_first_init(dpeth_t *dep, const dp_conf_t *dcp)
122 {
123 
124   dep->de_linmem = 0xFFFF0000; /* FIXME: this overrides update_conf, why? */
125 
126   /* Device specific initialization */
127   (*dep->de_initf)(dep);
128 
129   /* Map memory if requested */
130   if (dep->de_linmem != 0) {
131 	assert(dep->de_ramsize > 0);
132 	dep->de_locmem =
133 	    vm_map_phys(SELF, (void *)dep->de_linmem, dep->de_ramsize);
134 	if (dep->de_locmem == MAP_FAILED)
135 		panic("unable to map memory");
136   }
137 
138   /* Set the interrupt handler policy. Request interrupts not to be reenabled
139    * automatically. Return the IRQ line number when an interrupt occurs.
140    */
141   dep->de_hook = dep->de_irq;
142   if (sys_irqsetpolicy(dep->de_irq, 0 /*IRQ_REENABLE*/, &dep->de_hook) != OK)
143 	panic("unable to set IRQ policy");
144   sys_irqenable(&dep->de_hook);
145 }
146 
147 /*
148 **  Name:	do_init
149 **  Function:	Checks for hardware presence.
150 **  		Initialize hardware and data structures.
151 **		Return status and ethernet address.
152 */
153 static int do_init(unsigned int instance, netdriver_addr_t *addr,
154 	uint32_t *caps, unsigned int *ticks)
155 {
156   dpeth_t *dep;
157   dp_conf_t *dcp;
158   int confnr, fkeys, sfkeys;
159 
160   dep = &de_state;
161 
162   /* Pick a default configuration for this instance. */
163   confnr = MIN(instance, DP_CONF_NR-1);
164 
165   dcp = &dp_conf[confnr];
166 
167   update_conf(dep, dcp, instance);
168 
169   if (!el1_probe(dep) &&	/* Probe for 3c501  */
170     !wdeth_probe(dep) &&	/* Probe for WD80x3 */
171     !ne_probe(dep) &&		/* Probe for NEx000 */
172     !el2_probe(dep) &&		/* Probe for 3c503  */
173     !el3_probe(dep)) {		/* Probe for 3c509  */
174 	printf("%s: warning no ethernet card found at 0x%04X\n",
175 	       netdriver_name(), dep->de_base_port);
176 	return ENXIO;
177   }
178 
179   do_first_init(dep, dcp);
180 
181   /* Request function key for debug dumps */
182   fkeys = sfkeys = 0; bit_set(sfkeys, 7);
183   if (fkey_map(&fkeys, &sfkeys) != OK)
184 	printf("%s: couldn't bind Shift+F7 key (%d)\n",
185 	    netdriver_name(), errno);
186 
187   memcpy(addr, dep->de_address.na_addr, sizeof(*addr));
188   *caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST; /* ..is this even accurate? */
189   *ticks = sys_hz(); /* update statistics once a second */
190   return OK;
191 }
192 
193 /*
194 **  Name:	de_set_mode
195 **  Function:	Sets packet receipt mode.
196 */
197 static void do_set_mode(unsigned int mode,
198 	const netdriver_addr_t * mcast_list __unused,
199 	unsigned int mcast_count __unused)
200 {
201   dpeth_t *dep;
202 
203   dep = &de_state;
204 
205   dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
206   if (mode & NDEV_MODE_PROMISC)
207 	dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
208   if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
209 	dep->de_flags |= DEF_MULTI;
210   if (mode & NDEV_MODE_BCAST)
211 	dep->de_flags |= DEF_BROAD;
212   (*dep->de_flagsf)(dep);
213 }
214 
215 /*
216 **  Name:	do_send
217 **  Function:	Send a packet, if possible.
218 */
219 static int do_send(struct netdriver_data *data, size_t size)
220 {
221   dpeth_t *dep;
222 
223   dep = &de_state;
224 
225   return (*dep->de_sendf)(dep, data, size);
226 }
227 
228 /*
229 **  Name:	do_recv
230 **  Function:	Receive a packet, if possible.
231 */
232 static ssize_t do_recv(struct netdriver_data *data, size_t max)
233 {
234   dpeth_t *dep;
235 
236   dep = &de_state;
237 
238   return (*dep->de_recvf)(dep, data, max);
239 }
240 
241 /*
242 **  Name:	do_stop
243 **  Function:	Stops network interface.
244 */
245 static void do_stop(void)
246 {
247   dpeth_t *dep;
248 
249   dep = &de_state;
250 
251   /* Stop device */
252   (dep->de_stopf)(dep);
253 }
254 
255 /*
256 **  Name:	do_intr
257 **  Function;	Handles interrupts.
258 */
259 static void do_intr(unsigned int __unused mask)
260 {
261 	dpeth_t *dep;
262 
263 	dep = &de_state;
264 
265 	/* If device is enabled and interrupt pending */
266 	(*dep->de_interruptf)(dep);
267 	sys_irqenable(&dep->de_hook);
268 }
269 
270 /*
271 **  Name:	do_tick
272 **  Function:	perform regular processing.
273 */
274 static void do_tick(void)
275 {
276 	dpeth_t *dep;
277 
278 	dep = &de_state;
279 
280 	if (dep->de_getstatsf != NULL)
281 		(*dep->de_getstatsf)(dep);
282 }
283 
284 /*
285 **  Name:	do_other
286 **  Function:	Processes miscellaneous messages.
287 */
288 static void do_other(const message *m_ptr, int ipc_status)
289 {
290 
291   if (is_ipc_notify(ipc_status) && m_ptr->m_source == TTY_PROC_NR)
292 	do_dump();
293 }
294 
295 /*
296 **  Name:	main
297 **  Function:	Main entry for dp task
298 */
299 int main(int argc, char **argv)
300 {
301 
302   env_setargs(argc, argv);
303 
304   netdriver_task(&dp_table);
305 
306   return 0;
307 }
308