1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: lance_mapped.c,v $
29 * Revision 2.21 93/05/15 19:36:50 mrt
30 * machparam.h -> machspl.h
31 *
32 * Revision 2.20 93/05/10 20:08:11 rvb
33 * No more sys/types.h.
34 * [93/05/06 09:52:53 af]
35 *
36 * Revision 2.19 93/03/26 17:58:07 mrt
37 * Removed dev_t, minor();
38 * [93/03/17 af]
39 *
40 * Revision 2.18 93/03/11 14:06:09 danner
41 * eliminate u_long.
42 * [93/03/09 danner]
43 *
44 * Revision 2.17 93/02/05 08:18:50 danner
45 * Include fixes.
46 * [93/02/04 danner]
47 *
48 * Revision 2.16 93/02/01 09:55:15 danner
49 * Put return types on some functions to quiet warnings.
50 * [93/01/25 jfriedl]
51 *
52 * Revision 2.15 93/01/14 17:16:46 danner
53 * corrected typo.
54 * [93/01/12 danner]
55 * Added LUNA88K and portability support.
56 * [92/12/02 jfriedl]
57 * Proper spl typing.
58 * [92/11/30 af]
59 *
60 * Revision 2.14 92/01/03 20:39:03 dbg
61 * No need to destroy/init the eventcounter all the time.
62 * [91/12/27 af]
63 *
64 * Since we are actually using this, made user-safe.
65 * [91/12/27 af]
66 *
67 * Revision 2.13 91/12/13 14:54:23 jsb
68 * Use eventcounters.
69 * [91/12/12 17:43:08 af]
70 *
71 * Revision 2.12 91/08/24 11:52:17 af
72 * Bugfix: typos, spl for 3min.
73 * [91/08/02 01:52:26 af]
74 *
75 * Revision 2.11 91/06/25 20:54:03 rpd
76 * Tweaks to make gcc happy.
77 *
78 * Revision 2.10 91/06/19 15:19:40 rvb
79 * mips->DECSTATION; vax->VAXSTATION
80 * [91/06/12 14:01:45 rvb]
81 *
82 * File moved here from mips/PMAX since it tries to be generic;
83 * it is used on the PMAX and could be used on the Vax3100.
84 * [91/06/04 rvb]
85 *
86 * Revision 2.9 91/05/14 17:22:24 mrt
87 * Correcting copyright
88 *
89 * Revision 2.8 91/03/16 14:54:00 rpd
90 * Picked up a further spl fix from Sandro.
91 * [91/03/09 rpd]
92 * Updated for new kmem_alloc interface.
93 * [91/03/03 rpd]
94 * Removed thread_swappable.
95 * [91/01/18 rpd]
96 *
97 * Revision 2.7 91/02/14 14:34:16 mrt
98 * In interrupt routine, drop priority as now required.
99 * Also sanity check for spurious interrupts anyways.
100 * [91/02/12 12:41:46 af]
101 *
102 * Revision 2.6 91/02/05 17:41:22 mrt
103 * Added author notices
104 * [91/02/04 11:13:58 mrt]
105 *
106 * Changed to use new Mach copyright
107 * [91/02/02 12:12:01 mrt]
108 *
109 * Revision 2.5 90/12/05 23:31:33 af
110 * Cleanups.
111 * [90/12/03 23:20:13 af]
112 *
113 * Revision 2.3.1.1 90/10/03 12:06:02 af
114 * Made it work with multiple ether boards (e.g. thick ether
115 * on 3maxen). This is the first time a mapped device does
116 * something before the un-mapped one..
117 *
118 * Revision 2.3 90/09/09 23:52:11 rpd
119 * Changed thread_resume_from_kernel to thread_resume.
120 *
121 * Revision 2.2 90/09/09 23:20:35 rpd
122 * Correctly return the ram size for the givem machine: 3maxen
123 * have twice as much ram as pmaxen.
124 * [90/09/09 18:59:41 af]
125 *
126 * Created.
127 * [90/08/22 af]
128 */
129 /*
130 * File: if_se_mapped.c
131 * Author: Alessandro Forin, Carnegie Mellon University
132 * Date: 8/90
133 *
134 * In-kernel side of the user-mapped ethernet driver.
135 */
136
137 #include <ln.h>
138 #if NLN > 0
139 #include <platforms.h>
140
141 #include <mach/machine/vm_types.h>
142 #include <machine/machspl.h> /* spl definitions */
143 #include <chips/lance.h>
144 #include <chips/busses.h>
145
146 #include <device/device_types.h>
147 #include <device/errno.h>
148 #include <device/io_req.h>
149 #include <device/net_status.h>
150 #include <device/net_io.h>
151 #include <device/if_hdr.h>
152 #include <device/if_ether.h>
153
154 #include <vm/vm_kern.h>
155 #include <kern/eventcount.h>
156
157 #include <machine/machspl.h>
158
159 #ifdef DECSTATION
160
161 #define machine_btop mips_btop
162
163 #define kvctophys(v) K0SEG_TO_PHYS((v)) /* kernel virtual cached */
164 #define phystokvc(p) PHYS_TO_K0SEG((p)) /* and back */
165 #define kvutophys(v) K1SEG_TO_PHYS((v)) /* kernel virtual uncached */
166 #define phystokvu(p) PHYS_TO_K1SEG((p)) /* and back */
167 /* remap from k2 to k0 */
168 #define kvirt(v) ((phystokvc(pmap_extract(pmap_kernel(),v))))
169
170 #include <mips/mips_cpu.h>
171 /*
172 * Wired addresses and sizes
173 */
174 #define SE0_REG_EMRG (se_reg_t)(0xb8000000)
175
176 #define REGBASE(unit) (((u_int)SE_statii[unit].registers) - se_sw->regspace)
177
178 #define SE_REG_PHYS(unit) kvutophys(REGBASE(unit)+se_sw->regspace)
179 #define SE_REG_SIZE PAGE_SIZE
180
181 #define SE_BUF_PHYS(unit) kvutophys(REGBASE(unit)+se_sw->bufspace)
182 #define SE_BUF_SIZE (128*1024)
183
184 #define SE_ADR_PHYS(unit) kvutophys(REGBASE(unit)+se_sw->romspace)
185 #define SE_ADR_SIZE PAGE_SIZE
186 #endif /*DECSTATION*/
187
188 #ifdef VAXSTATION
189 #define machine_btop vax_btop
190 #endif /*VAXSTATION*/
191
192 #ifdef LUNA88K
193 # define machine_btop m88k_btop
194 # define kvirt(v) (v)
195 # define kvctophys(v) pmap_extract(pmap_kernel(),(v))
196 # define SE0_REG_EMRG ((se_reg_t)0xF1000000U)
197 # define REGBASE(unit) (((u_int)SE_statii[unit].registers) - se_sw->regspace)
198 # define SE_REG_PHYS(unit) (REGBASE(unit) + se_sw->regspace)
199 # define SE_REG_SIZE PAGE_SIZE
200 # define SE_BUF_PHYS(unit) (REGBASE(unit) + se_sw->bufspace)
201 # define SE_BUF_SIZE (64*1024)
202 # define SE_ADR_PHYS(unit) kvctophys(REGBASE(unit) + se_sw->romspace)
203 # define SE_ADR_SIZE PAGE_SIZE
204 # define wbflush() /*empty*/
205 #endif /*LUNA88K*/
206
207 /*
208 * Autoconf info
209 */
210
211 static vm_offset_t SEstd[NLN] = { 0 };
212 static struct bus_device *SEinfo[NLN];
213 void SE_attach();
214 int SE_probe();
215
216 struct bus_driver SEdriver =
217 { SE_probe, 0, SE_attach, 0, SEstd, "SE", SEinfo, };
218
219 /*
220 * Externally visible functions
221 */
222 int SE_probe(); /* Kernel */
223 void SE_intr(), SE_portdeath();
224 /* User */
225 int SE_open(), SE_close();
226 vm_offset_t SE_mmap();
227
228
229 /* forward declarations */
230
231 static void SE_stop(unsigned int unit);
232
233 /*
234 * Status information for all interfaces
235 */
236 /*static*/ struct SE_status {
237 se_reg_t registers;
238 mapped_ether_info_t info;
239 struct evc eventcounter;
240 } SE_statii[NLN];
241
242
243 /*
244 * Probe the Lance to see (if) that it's there
245 */
246 int
247 SE_probe(regbase, ui)
248 vm_offset_t regbase;
249 register struct bus_device *ui;
250 {
251 int unit = ui->unit;
252 se_reg_t regs;
253 vm_offset_t addr;
254 mapped_ether_info_t info;
255 struct SE_status *self;
256
257
258 if (unit >= NLN)
259 return 0;
260
261 self = &SE_statii[unit];
262
263 printf("[mappable] ");
264
265 regs = (se_reg_t) (regbase + se_sw->regspace);
266 self->registers = regs;
267
268 /*
269 * Reset the interface
270 */
271 SE_stop(unit);
272
273 /*
274 * Grab a page to be mapped later to users
275 */
276 (void) kmem_alloc_wired(kernel_map, &addr, PAGE_SIZE);
277 /*
278 on the decstation, kmem_alloc_wired returns virtual addresses
279 in the k2 seg. Since this page is going to get mapped in
280 user space, we need to transform it to a better understood
281 virtual address. The kvirt function does this.
282 */
283 bzero(addr, PAGE_SIZE);
284 info = (mapped_ether_info_t) kvirt(addr);
285 self->info = info;
286
287 /*
288 * Set permanent info
289 */
290 info->rom_stride = se_sw->romstride;
291 info->ram_stride = se_sw->ramstride;
292 info->buffer_size = se_sw->ramsize;
293 info->buffer_physaddr = se_sw->ln_bufspace;
294
295 /*
296 * Synch setup
297 */
298 evc_init(&self->eventcounter);
299 info->wait_event = self->eventcounter.ev_id;
300
301 return 1;
302 }
303
304 void
305 SE_attach(ui)
306 register struct bus_device *ui;
307 {
308 }
309
310
311 /*
312 * Shut off the lance
313 */
314 static void SE_stop(unsigned int unit)
315 {
316 register se_reg_t regs = SE_statii[unit].registers;
317
318 if (regs == 0)
319 /* Stray interrupt */
320 regs = SE0_REG_EMRG;
321
322 regs[2] = CSR0_SELECT; /* XXXX rap XXXX */
323 wbflush();
324 regs[0] = LN_CSR0_STOP;
325 wbflush();
326 }
327
328
329 /*
330 * Ethernet interface interrupt routine
331 */
332 void SE_intr(unit,spllevel)
333 int unit;
334 spl_t spllevel;
335 {
336 register struct SE_status *self = &SE_statii[unit];
337 register se_reg_t regs = self->registers;
338 register csr;
339
340 if (regs == 0) { /* stray */
341 SE_stop(unit);
342 return;
343 }
344
345 /* Acknowledge interrupt request, drop spurious intr */
346 csr = regs[0];
347 if ((csr & LN_CSR0_INTR) == 0)
348 return;
349 regs[0] = csr & LN_CSR0_WTC; /* silence it */
350
351 splx(spllevel); /* drop priority now */
352
353 /* Pass csr state up to user thread */
354 if (self->info) {
355 self->info->interrupt_count++; /* total interrupts */
356 self->info->saved_csr0 = csr;
357 }
358
359 /* Awake user thread */
360 evc_signal(&self->eventcounter);
361 }
362
363
364 extern boolean_t se_use_mapped_interface[NLN];
365
366 /*
367 * Device open procedure
368 */
369 int SE_open(dev, flag, ior)
370 io_req_t ior;
371 {
372 int unit = dev;
373 register struct SE_status *self = &SE_statii[unit];
374
375 if (unit >= NLN)
376 return EINVAL;
377
378 /*
379 * Silence interface, just in case
380 */
381 SE_stop(unit);
382
383 /*
384 * Reset eventcounter
385 */
386 evc_signal(&self->eventcounter);
387
388 se_use_mapped_interface[unit] = 1;
389
390 /*
391 * Do not turn Ether interrupts on. The user can do it when ready
392 * to take them.
393 */
394
395 return 0;
396 }
397
398 /*
399 * Device close procedure
400 */
401 int SE_close(dev, flag)
402 {
403 int unit = dev;
404 register struct SE_status *self = &SE_statii[unit];
405
406 if (unit >= NLN)
407 return EINVAL;
408
409 /*
410 * Silence interface, in case user forgot
411 */
412 SE_stop(unit);
413 evc_signal(&self->eventcounter);
414
415 se_normal(unit);
416
417 return 0;
418 }
419
420
421 /*
422 * Get status procedure.
423 * We need to tell that we are mappable.
424 */
425 io_return_t
426 SE_get_status(ifp, flavor, status, status_count)
427 /* struct ifnet *ifp; not really..*/
428 int flavor;
429 dev_status_t status; /* pointer to OUT array */
430 unsigned int *status_count; /* OUT */
431 {
432 switch (flavor) {
433 case NET_STATUS:
434 {
435 register struct net_status *ns = (struct net_status *)status;
436
437 ns->min_packet_size = sizeof(struct ether_header);
438 ns->max_packet_size = sizeof(struct ether_header) + ETHERMTU;
439 ns->header_format = HDR_ETHERNET;
440 ns->header_size = sizeof(struct ether_header);
441 ns->address_size = 6;
442 ns->flags = IFF_BROADCAST;
443 ns->mapped_size = SE_BUF_SIZE + (3 * PAGE_SIZE);
444
445 *status_count = NET_STATUS_COUNT;
446 break;
447 }
448 /* case NET_ADDRESS: find it yourself */
449 default:
450 return (D_INVALID_OPERATION);
451 }
452 return (D_SUCCESS);
453 }
454
455 /*
456 * Should not refuse this either
457 */
458 int SE_set_status(dev, flavor, status, status_count)
459 int dev;
460 int flavor;
461 dev_status_t status;
462 unsigned int status_count;
463 {
464 return (D_SUCCESS);
465 }
466
467 /*
468 * Port death notification routine
469 */
470 void SE_portdeath(dev, dead_port)
471 {
472 }
473
474
475 /*
476 * Virtual->physical mapping routine.
477 */
478 vm_offset_t
479 SE_mmap(dev, off, prot)
480 int dev;
481 vm_offset_t off;
482 vm_prot_t prot;
483 {
484 vm_offset_t page;
485 vm_offset_t addr;
486 int unit = dev;
487
488 /*
489 * The offset (into the VM object) defines the following layout
490 *
491 * off size what
492 * 0 1pg mapping information (csr & #interrupts)
493 * 1pg 1pg lance registers
494 * 2pg 1pg lance station address (ROM)
495 * 3pg 128k lance buffers
496 */
497 #define S0 PAGE_SIZE
498 #define S1 (S0+SE_REG_SIZE)
499 #define S2 (S1+SE_ADR_SIZE)
500 #define S3 (S2+SE_BUF_SIZE)
501
502 if (off < S0) {
503 addr = kvctophys (SE_statii[unit].info);
504 } else if (off < S1) {
505 addr = (vm_offset_t) SE_REG_PHYS(unit);
506 off -= S0;
507 } else if (off < S2) {
508 addr = (vm_offset_t) SE_ADR_PHYS(unit);
509 off -= S1;
510 } else if (off < S3) {
511 addr = (vm_offset_t) SE_BUF_PHYS(unit);
512 off -= S2;
513 } else
514 return (EINVAL);
515
516 page = machine_btop(addr + off);
517 return (page);
518 }
519
520 #endif NLN > 0
Cache object: 181ff8ddd4506f81c2ad9602b930b98e
|