|
|
1.1 root 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 [email protected]
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: * File: if_se_mapped.c
28: * Author: Alessandro Forin, Carnegie Mellon University
29: * Date: 8/90
30: *
31: * In-kernel side of the user-mapped ethernet driver.
32: */
33:
34: #include <ln.h>
35: #if NLN > 0
36: #include <platforms.h>
37:
38: #include <mach/machine/vm_types.h>
39: #include <machine/machspl.h> /* spl definitions */
40: #include <chips/lance.h>
41: #include <chips/busses.h>
42:
43: #include <device/device_types.h>
44: #include <device/errno.h>
45: #include <device/io_req.h>
46: #include <device/net_status.h>
47: #include <device/net_io.h>
48: #include <device/if_hdr.h>
49: #include <device/if_ether.h>
50:
51: #include <vm/vm_kern.h>
52: #include <kern/eventcount.h>
53:
54: #include <machine/machspl.h>
55:
56: #ifdef DECSTATION
57:
58: #define machine_btop mips_btop
59:
60: #define kvctophys(v) K0SEG_TO_PHYS((v)) /* kernel virtual cached */
61: #define phystokvc(p) PHYS_TO_K0SEG((p)) /* and back */
62: #define kvutophys(v) K1SEG_TO_PHYS((v)) /* kernel virtual uncached */
63: #define phystokvu(p) PHYS_TO_K1SEG((p)) /* and back */
64: /* remap from k2 to k0 */
65: #define kvirt(v) ((phystokvc(pmap_extract(pmap_kernel(),v))))
66:
67: #include <mips/mips_cpu.h>
68: /*
69: * Wired addresses and sizes
70: */
71: #define SE0_REG_EMRG (se_reg_t)(0xb8000000)
72:
73: #define REGBASE(unit) (((u_int)SE_statii[unit].registers) - se_sw->regspace)
74:
75: #define SE_REG_PHYS(unit) kvutophys(REGBASE(unit)+se_sw->regspace)
76: #define SE_REG_SIZE PAGE_SIZE
77:
78: #define SE_BUF_PHYS(unit) kvutophys(REGBASE(unit)+se_sw->bufspace)
79: #define SE_BUF_SIZE (128*1024)
80:
81: #define SE_ADR_PHYS(unit) kvutophys(REGBASE(unit)+se_sw->romspace)
82: #define SE_ADR_SIZE PAGE_SIZE
83: #endif /*DECSTATION*/
84:
85: #ifdef VAXSTATION
86: #define machine_btop vax_btop
87: #endif /*VAXSTATION*/
88:
89: #ifdef LUNA88K
90: # define machine_btop m88k_btop
91: # define kvirt(v) (v)
92: # define kvctophys(v) pmap_extract(pmap_kernel(),(v))
93: # define SE0_REG_EMRG ((se_reg_t)0xF1000000U)
94: # define REGBASE(unit) (((u_int)SE_statii[unit].registers) - se_sw->regspace)
95: # define SE_REG_PHYS(unit) (REGBASE(unit) + se_sw->regspace)
96: # define SE_REG_SIZE PAGE_SIZE
97: # define SE_BUF_PHYS(unit) (REGBASE(unit) + se_sw->bufspace)
98: # define SE_BUF_SIZE (64*1024)
99: # define SE_ADR_PHYS(unit) kvctophys(REGBASE(unit) + se_sw->romspace)
100: # define SE_ADR_SIZE PAGE_SIZE
101: # define wbflush() /*empty*/
102: #endif /*LUNA88K*/
103:
104: /*
105: * Autoconf info
106: */
107:
108: static vm_offset_t SEstd[NLN] = { 0 };
109: static struct bus_device *SEinfo[NLN];
110: void SE_attach();
111: int SE_probe();
112:
113: struct bus_driver SEdriver =
114: { SE_probe, 0, SE_attach, 0, SEstd, "SE", SEinfo, };
115:
116: /*
117: * Externally visible functions
118: */
119: int SE_probe(); /* Kernel */
120: void SE_intr(), SE_portdeath();
121: /* User */
122: int SE_open(), SE_close();
123: vm_offset_t SE_mmap();
124:
125:
126: /* forward declarations */
127:
128: static void SE_stop(unsigned int unit);
129:
130: /*
131: * Status information for all interfaces
132: */
133: /*static*/ struct SE_status {
134: se_reg_t registers;
135: mapped_ether_info_t info;
136: struct evc eventcounter;
137: } SE_statii[NLN];
138:
139:
140: /*
141: * Probe the Lance to see (if) that it's there
142: */
143: int
144: SE_probe(regbase, ui)
145: vm_offset_t regbase;
146: register struct bus_device *ui;
147: {
148: int unit = ui->unit;
149: se_reg_t regs;
150: vm_offset_t addr;
151: mapped_ether_info_t info;
152: struct SE_status *self;
153:
154:
155: if (unit >= NLN)
156: return 0;
157:
158: self = &SE_statii[unit];
159:
160: printf("[mappable] ");
161:
162: regs = (se_reg_t) (regbase + se_sw->regspace);
163: self->registers = regs;
164:
165: /*
166: * Reset the interface
167: */
168: SE_stop(unit);
169:
170: /*
171: * Grab a page to be mapped later to users
172: */
173: (void) kmem_alloc_wired(kernel_map, &addr, PAGE_SIZE);
174: /*
175: on the decstation, kmem_alloc_wired returns virtual addresses
176: in the k2 seg. Since this page is going to get mapped in
177: user space, we need to transform it to a better understood
178: virtual address. The kvirt function does this.
179: */
180: bzero(addr, PAGE_SIZE);
181: info = (mapped_ether_info_t) kvirt(addr);
182: self->info = info;
183:
184: /*
185: * Set permanent info
186: */
187: info->rom_stride = se_sw->romstride;
188: info->ram_stride = se_sw->ramstride;
189: info->buffer_size = se_sw->ramsize;
190: info->buffer_physaddr = se_sw->ln_bufspace;
191:
192: /*
193: * Synch setup
194: */
195: evc_init(&self->eventcounter);
196: info->wait_event = self->eventcounter.ev_id;
197:
198: return 1;
199: }
200:
201: void
202: SE_attach(ui)
203: register struct bus_device *ui;
204: {
205: }
206:
207:
208: /*
209: * Shut off the lance
210: */
211: static void SE_stop(unsigned int unit)
212: {
213: register se_reg_t regs = SE_statii[unit].registers;
214:
215: if (regs == 0)
216: /* Stray interrupt */
217: regs = SE0_REG_EMRG;
218:
219: regs[2] = CSR0_SELECT; /* XXXX rap XXXX */
220: wbflush();
221: regs[0] = LN_CSR0_STOP;
222: wbflush();
223: }
224:
225:
226: /*
227: * Ethernet interface interrupt routine
228: */
229: void SE_intr(unit,spllevel)
230: int unit;
231: spl_t spllevel;
232: {
233: register struct SE_status *self = &SE_statii[unit];
234: register se_reg_t regs = self->registers;
235: register csr;
236:
237: if (regs == 0) { /* stray */
238: SE_stop(unit);
239: return;
240: }
241:
242: /* Acknowledge interrupt request, drop spurious intr */
243: csr = regs[0];
244: if ((csr & LN_CSR0_INTR) == 0)
245: return;
246: regs[0] = csr & LN_CSR0_WTC; /* silence it */
247:
248: splx(spllevel); /* drop priority now */
249:
250: /* Pass csr state up to user thread */
251: if (self->info) {
252: self->info->interrupt_count++; /* total interrupts */
253: self->info->saved_csr0 = csr;
254: }
255:
256: /* Awake user thread */
257: evc_signal(&self->eventcounter);
258: }
259:
260:
261: extern boolean_t se_use_mapped_interface[NLN];
262:
263: /*
264: * Device open procedure
265: */
266: int SE_open(dev, flag, ior)
267: io_req_t ior;
268: {
269: int unit = dev;
270: register struct SE_status *self = &SE_statii[unit];
271:
272: if (unit >= NLN)
273: return EINVAL;
274:
275: /*
276: * Silence interface, just in case
277: */
278: SE_stop(unit);
279:
280: /*
281: * Reset eventcounter
282: */
283: evc_signal(&self->eventcounter);
284:
285: se_use_mapped_interface[unit] = 1;
286:
287: /*
288: * Do not turn Ether interrupts on. The user can do it when ready
289: * to take them.
290: */
291:
292: return 0;
293: }
294:
295: /*
296: * Device close procedure
297: */
298: int SE_close(dev, flag)
299: {
300: int unit = dev;
301: register struct SE_status *self = &SE_statii[unit];
302:
303: if (unit >= NLN)
304: return EINVAL;
305:
306: /*
307: * Silence interface, in case user forgot
308: */
309: SE_stop(unit);
310: evc_signal(&self->eventcounter);
311:
312: se_normal(unit);
313:
314: return 0;
315: }
316:
317:
318: /*
319: * Get status procedure.
320: * We need to tell that we are mappable.
321: */
322: io_return_t
323: SE_get_status(ifp, flavor, status, status_count)
324: /* struct ifnet *ifp; not really..*/
325: int flavor;
326: dev_status_t status; /* pointer to OUT array */
327: unsigned int *status_count; /* OUT */
328: {
329: switch (flavor) {
330: case NET_STATUS:
331: {
332: register struct net_status *ns = (struct net_status *)status;
333:
334: ns->min_packet_size = sizeof(struct ether_header);
335: ns->max_packet_size = sizeof(struct ether_header) + ETHERMTU;
336: ns->header_format = HDR_ETHERNET;
337: ns->header_size = sizeof(struct ether_header);
338: ns->address_size = 6;
339: ns->flags = IFF_BROADCAST;
340: ns->mapped_size = SE_BUF_SIZE + (3 * PAGE_SIZE);
341:
342: *status_count = NET_STATUS_COUNT;
343: break;
344: }
345: /* case NET_ADDRESS: find it yourself */
346: default:
347: return (D_INVALID_OPERATION);
348: }
349: return (D_SUCCESS);
350: }
351:
352: /*
353: * Should not refuse this either
354: */
355: int SE_set_status(dev, flavor, status, status_count)
356: int dev;
357: int flavor;
358: dev_status_t status;
359: unsigned int status_count;
360: {
361: return (D_SUCCESS);
362: }
363:
364: /*
365: * Port death notification routine
366: */
367: void SE_portdeath(dev, dead_port)
368: {
369: }
370:
371:
372: /*
373: * Virtual->physical mapping routine.
374: */
375: vm_offset_t
376: SE_mmap(dev, off, prot)
377: int dev;
378: vm_offset_t off;
379: vm_prot_t prot;
380: {
381: vm_offset_t page;
382: vm_offset_t addr;
383: int unit = dev;
384:
385: /*
386: * The offset (into the VM object) defines the following layout
387: *
388: * off size what
389: * 0 1pg mapping information (csr & #interrupts)
390: * 1pg 1pg lance registers
391: * 2pg 1pg lance station address (ROM)
392: * 3pg 128k lance buffers
393: */
394: #define S0 PAGE_SIZE
395: #define S1 (S0+SE_REG_SIZE)
396: #define S2 (S1+SE_ADR_SIZE)
397: #define S3 (S2+SE_BUF_SIZE)
398:
399: if (off < S0) {
400: addr = kvctophys (SE_statii[unit].info);
401: } else if (off < S1) {
402: addr = (vm_offset_t) SE_REG_PHYS(unit);
403: off -= S0;
404: } else if (off < S2) {
405: addr = (vm_offset_t) SE_ADR_PHYS(unit);
406: off -= S1;
407: } else if (off < S3) {
408: addr = (vm_offset_t) SE_BUF_PHYS(unit);
409: off -= S2;
410: } else
411: return (EINVAL);
412:
413: page = machine_btop(addr + off);
414: return (page);
415: }
416:
417: #endif NLN > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.