|
|
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.