/* * Mach Operating System * Copyright (c) 1992 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ #include #if NATM > 0 #include #include /* spl definitions */ #include /* ? maybe */ #include #include #include #include #include #include #include struct bus_device *atm_info[NATM]; int atm_probe(); static void atm_attach(); struct bus_driver atm_driver = { atm_probe, 0, atm_attach, 0, /* csr */ 0, "atm", atm_info, "", 0, /* flags */ 0 }; /* ENABLED BUS INTR? */ /* XX "", 0, BUS_INTR_DISABLED}; */ typedef struct atm_softc { struct atm_device *atm_dev; struct evc atm_eventcounter; mapped_atm_info_t atm_mapped_info; } atm_softc_t; natural_t atm_nintrs = 0; atm_softc_t atm_softc[NATM]; atm_probe(reg, ui) vm_offset_t reg; register struct bus_device *ui; { register atm_softc_t *atm; mapped_atm_info_t info; /* info struct to hand to users */ vm_offset_t addr; int unit = ui->unit; if (check_memory(reg, 0)) { return 0; } atm_info[unit] = ui; atm = &atm_softc[unit]; atm->atm_dev = (struct atm_device *) reg; /* k1 address */ evc_init(&atm->atm_eventcounter); printf("evc_init of atm: event counter id is %d\n", atm->atm_eventcounter.ev_id); /* initialize the interface to deliver. No interrupts by default */ atm->atm_dev->sreg = 0; atm->atm_dev->creg = (CR_RX_RESET | CR_TX_RESET); atm->atm_dev->creg = 0; atm->atm_dev->creg_set = (CR_RX_ENABLE | CR_TX_ENABLE); #ifdef notdef atm->atm_dev->rxthresh = 0; atm->atm_dev->rxtimerv = 0; atm->atm_dev->creg_s = RX_EOM_INTR; /* enable interrupt on end of message */ #endif /* * Grab a page to be mapped later to users */ (void) kmem_alloc_wired(kernel_map, &addr, PAGE_SIZE); /* kseg2 */ bzero(addr, PAGE_SIZE); addr = pmap_extract(pmap_kernel(), addr); /* phys */ info = (mapped_atm_info_t) PHYS_TO_K0SEG(addr); atm->atm_mapped_info = info; /* * Set some permanent info */ info->hello_world = 0xdeadbeef; info->interrupt_count = 0; info->wait_event = atm->atm_eventcounter.ev_id; info->saved_status_reg = 0; return 1; } static void atm_attach(ui) register struct bus_device *ui; { } int atm_disable_interrupts_after_each = 1; #define ATM_INTERRUPTS (RX_COUNT_INTR | RX_EOM_INTR | RX_TIME_INTR) atm_intr(unit, spllevel) int unit; int spllevel; { register struct atm_softc *atm = &atm_softc[unit]; struct atm_device *atm_dev = atm->atm_dev; unsigned int intr; if (atm_dev == 0) { printf("atm: stray interrupt\n"); return; } /* Acknowledge interrupt request */ intr = ATM_READ_REG(atm_dev->sreg); atm_dev->sreg = ~(intr & ATM_INTERRUPTS); /* clear the reason for the interrupt */ if (atm_disable_interrupts_after_each) atm_dev->creg &= ~intr; splx(spllevel); /* drop priority now */ atm_intr_occurred(); /* Pass status info up to user */ if (atm->atm_mapped_info) { atm->atm_mapped_info->interrupt_count++; atm->atm_mapped_info->saved_status_reg = intr; } /* Awake user thread */ evc_signal(&atm->atm_eventcounter); /* NOTE: INTERRUPTS ARE DISABLED. */ } atm_intr_occurred() { atm_nintrs++; } atm_output(dev, ior) int dev; io_req_t ior; { } atm_start(unit) int unit; { } atm_open(dev, flag, ior) int dev; int flag; io_req_t ior; { register int unit = dev; register atm_softc_t *atm = &atm_softc[unit]; if (unit >= NATM) return EINVAL; if (!atm->atm_dev) return ENXIO; return KERN_SUCCESS; } atm_close(dev, flag) int dev; { } atm_read(dev, ior) int dev; io_req_t ior; { } atm_write(dev, ior) int dev; io_req_t ior; { } atm_get_status(dev, flavor, status, status_count) int dev; int flavor; dev_status_t status; /* pointer to OUT array */ natural_t *status_count; /* out */ { switch (flavor) { case NET_STATUS: { register struct net_status *ns = (struct net_status *)status; ns->min_packet_size = sizeof(struct sar_data); ns->max_packet_size = sizeof(struct sar_data); ns->header_format = 999; /* XX */ ns->header_size = sizeof(int); /* XX */ ns->address_size = 0; ns->flags = 0; ns->mapped_size = sizeof(struct atm_device) + PAGE_SIZE; *status_count = NET_STATUS_COUNT; break; } case NET_ADDRESS: /* This would be a good place for it */ default: return (D_INVALID_OPERATION); } return (D_SUCCESS); } atm_set_status(dev, flavor, status, status_count) int dev; int flavor; dev_status_t status; natural_t status_count; { } atm_mmap(dev, off, prot) int dev; vm_offset_t off; int prot; { int unit = dev; vm_offset_t addr; /* * Layout of mapped area is: * 000 -- FA_END: DEVICE * FA_END -- FA_END + PAGE_SIZE: SHARED STATE */ if (off < sizeof(struct atm_device)) { addr = K1SEG_TO_PHYS((vm_offset_t)(atm_softc[unit].atm_dev)) + off; } else if (off < sizeof(struct atm_device) + PAGE_SIZE) { addr = K0SEG_TO_PHYS(atm_softc[unit].atm_mapped_info); } else return -1; return mips_btop(addr); } atm_setinput(dev, receive_port, priority, filter, filter_count) int dev; ipc_port_t receive_port; int priority; /*filter_t *filter;*/ natural_t filter_count; { } atm_restart(ifp) /* register struct ifnet *ifp; */ { } atm_portdeath(dev, port) int dev; mach_port_t port; { } #endif NATM > 0