From 5d81b8d26905479ddd7f50bdeb54702729d56866 Mon Sep 17 00:00:00 2001 From: fredette Date: Wed, 27 Jun 2001 02:48:32 +0000 Subject: [PATCH] Added common sun68k autoconfiguration and bus_space related code. Currently used by sun2. --- sys/arch/sun68k/sun68k/autoconf.c | 461 +++++++++++++ sys/arch/sun68k/sun68k/bus.c | 829 ++++++++++++++++++++++++ sys/arch/sun68k/sun68k/isr.c | 362 +++++++++++ sys/arch/sun68k/sun68k/procfs_machdep.c | 20 + sys/arch/sun68k/sun68k/vme_sun68k.c | 423 ++++++++++++ sys/arch/sun68k/sun68k/vme_sun68k.h | 41 ++ 6 files changed, 2136 insertions(+) create mode 100644 sys/arch/sun68k/sun68k/autoconf.c create mode 100644 sys/arch/sun68k/sun68k/bus.c create mode 100644 sys/arch/sun68k/sun68k/isr.c create mode 100644 sys/arch/sun68k/sun68k/procfs_machdep.c create mode 100644 sys/arch/sun68k/sun68k/vme_sun68k.c create mode 100644 sys/arch/sun68k/sun68k/vme_sun68k.h diff --git a/sys/arch/sun68k/sun68k/autoconf.c b/sys/arch/sun68k/sun68k/autoconf.c new file mode 100644 index 000000000000..b87257ae7639 --- /dev/null +++ b/sys/arch/sun68k/sun68k/autoconf.c @@ -0,0 +1,461 @@ +/* $NetBSD: autoconf.c,v 1.1 2001/06/27 02:48:32 fredette Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Adam Glass, Gordon W. Ross, and Matthew Fredette. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Setup the system to run on the current machine. + * + * Configure() is called at boot time. Available devices are + * determined (from possibilities mentioned in ioconf.c), and + * the drivers are initialized. + */ + +#include "opt_kgdb.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#ifdef KGDB +#include +#endif + +/* + * Do general device autoconfiguration, + * then choose root device (etc.) + * Called by machdep.c: cpu_startup() + */ +void +cpu_configure() +{ + + /* + * Consider stopping for a debugger before + * autoconfiguration. + */ + if (boothowto & RB_KDB) { +#ifdef KGDB + /* XXX - Ask on console for kgdb_dev? */ + /* Note: this will just return if kgdb_dev==NODEV */ + kgdb_connect(1); +#else /* KGDB */ + /* Either DDB or no debugger (just PROM). */ + Debugger(); +#endif /* KGDB */ + } + + /* + * Install handlers for our "soft" interrupts. + * There might be a better place to do this? + */ + softintr_init(); + + /* General device autoconfiguration. */ + if (config_rootfound("mainbus", NULL) == NULL) + panic("configure: mainbus not found"); + + /* + * Now that device autoconfiguration is finished, + * we can safely enable interrupts. + */ + printf("enabling interrupts\n"); + (void)spl0(); +} + +static int mainbus_match __P((struct device *, struct cfdata *, void *)); +static void mainbus_attach __P((struct device *, struct device *, void *)); + +struct cfattach mainbus_ca = { + sizeof(struct device), mainbus_match, mainbus_attach +}; + +/* + * Probe for the mainbus; always succeeds. + */ +static int +mainbus_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + + return 1; +} + +/* + * Do "direct" configuration for the bus types on mainbus. + * This controls the order of autoconfig for important things + * used early. For example, idprom is used by Ether drivers. + */ +static void +mainbus_attach(parent, self, args) + struct device *parent; + struct device *self; + void *args; +{ +extern struct sun68k_bus_dma_tag mainbus_dma_tag; +extern struct sun68k_bus_space_tag mainbus_space_tag; + + struct mainbus_attach_args ma; + const char *const *cpp; + static const char *const special[] = { + /* find these first */ + "obio", + "obmem", + NULL + }; + + printf("\n"); + + ma.ma_bustag = &mainbus_space_tag; + ma.ma_dmatag = &mainbus_dma_tag; + + /* Find all `early' mainbus buses */ + for (cpp = special; *cpp != NULL; cpp++) { + ma.ma_name = *cpp; + (void)config_found(self, &ma, NULL); + } + + /* Find the remaining buses */ + ma.ma_name = NULL; + (void) config_found(self, &ma, NULL); + + /* Lastly, find the PROM console */ + ma.ma_name = "pcons"; + (void) config_found(self, &ma, NULL); +} + +/* + * sun68k_bus_search: + * This function is passed to config_search() by the attach function + * for each of the "bus" drivers (obio, obmem, mbmem, vme, ...). + * The purpose of this function is to copy the "locators" into our + * _attach_args structure, so child drivers may use the _attach_args both + * as match parameters and as temporary storage for the defaulted + * locator values determined in the child_match and preserved for + * the child_attach function. If the bus attach functions just + * used config_found, then we would not have an opportunity to + * setup the _attach_args for each child match and attach call. + */ +int sun68k_bus_search(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct mainbus_attach_args *map = aux; + struct mainbus_attach_args ma; + cfmatch_t mf; + + /* Check whether we're looking for a specifically named device */ + if (map->ma_name != NULL && strcmp(map->ma_name, cf->cf_driver->cd_name) != 0) + return (0); + +#ifdef DIAGNOSTIC + if (cf->cf_fstate == FSTATE_STAR) + panic("bus_scan: FSTATE_STAR"); +#endif + + /* + * Prepare to copy the locators into our _attach_args. + */ + ma = *map; + ma.ma_name = NULL; + + /* + * Avoid entries which are missing attach information that + * they need, or that have attach information that they + * cannot have. The individual bus attach functions tell + * us this by initializing the locator fields in the attach + * args they provide us. + * + * At the same time we copy these values into the _attach_args + * will pass to the device's match and attach functions. + */ +#ifdef DIAGNOSTIC +#define BAD_LOCATOR(ma_loc, what) panic("sun68k_bus_search: %s %s for: %s%d\n", \ + map-> ma_loc == LOCATOR_REQUIRED ? "missing" : "unexpected", \ + what, cf->cf_driver->cd_name, cf->cf_unit) +#else +#define BAD_LOCATOR(ma_loc, what) return (0) +#endif +#define CHECK_LOCATOR(ma_loc, cf_loc, what) \ + if ((map-> ma_loc == LOCATOR_FORBIDDEN && cf->cf_loc != -1) || \ + (map-> ma_loc == LOCATOR_REQUIRED && cf->cf_loc == -1)) \ + BAD_LOCATOR( ma_loc, what); \ + else \ + ma. ma_loc = cf->cf_loc + ma.ma_paddr = LOCATOR_REQUIRED; + CHECK_LOCATOR(ma_paddr, cf_paddr, "address"); + CHECK_LOCATOR(ma_pri, cf_intpri, "ipl"); + + /* + * Note that this allows the match function to save + * defaulted locators in the _attach_args that will be + * preserved for the related attach call. + * XXX - This is a hack... + */ + mf = cf->cf_attach->ca_match; + if ((*mf)(parent, cf, &ma) > 0) { + config_attach(parent, cf, &ma, sun68k_bus_print); + } + return (0); +} + +/* + * sun68k_bus_print: + * Just print out the final (non-default) locators. + * The parent name is non-NULL when there was no match + * found by config_found(). + */ +int +sun68k_bus_print(args, name) + void *args; + const char *name; +{ + struct mainbus_attach_args *ma = args; + + if (name) + printf("%s:", name); + + if (ma->ma_paddr != -1) + printf(" addr 0x%x", (unsigned int) ma->ma_paddr); + if (ma->ma_pri != -1) + printf(" ipl %d", ma->ma_pri); + + return(UNCONF); +} + +/****************************************************************/ + +/* This takes the args: name, ctlr, unit */ +typedef struct device * (*findfunc_t) __P((char *, int, int)); + +static struct device * find_dev_byname __P((char *)); +static struct device * net_find __P((char *, int, int)); +static struct device * scsi_find __P((char *, int, int)); +static struct device * xx_find __P((char *, int, int)); + +struct prom_n2f { + const char name[4]; + findfunc_t func; +}; +static struct prom_n2f prom_dev_table[] = { + { "ie", net_find }, + { "ec", net_find }, + { "le", net_find }, + { "sd", scsi_find }, + { "xy", xx_find }, + { "xd", xx_find }, + { "", 0 }, +}; + +/* + * This converts one hex number to an integer, and returns + * an updated string pointer. + */ +static const char *str2hex __P((const char *, int *)); +static const char * +str2hex(p, _val) + const char *p; + int *_val; +{ + int val; + int c; + + for(val = 0;; val = (val << 4) + c, p++) { + c = *((unsigned char *) p); + if (c >= 'a') c-= ('a' + 10); + else if (c >= 'A') c -= ('A' + 10); + else if (c >= '0') c -= '0'; + if (c < 0 || c > 15) break; + } + *_val = val; + return (p); +} + +/* + * Choose root and swap devices. + */ +void +cpu_rootconf() +{ + struct prom_n2f *nf; + struct device *boot_device; + int boot_partition; + char *devname; + findfunc_t find; + char promname[4]; + char partname[4]; + const char *prompath; + int prom_ctlr, prom_unit, prom_part; + + /* Get the PROM boot path and take it apart. */ + prompath = prom_getbootpath(); + if (prompath == NULL) prompath = "zz(0,0,0)"; + promname[0] = *(prompath++); + promname[1] = *(prompath++); + promname[2] = '\0'; + prom_ctlr = prom_unit = prom_part = 0; + if (*prompath == '(' && + *(prompath = str2hex(++prompath, &prom_ctlr)) == ',' && + *(prompath = str2hex(++prompath, &prom_unit)) == ',') + (void) str2hex(++prompath, &prom_part); + + /* Default to "unknown" */ + boot_device = NULL; + boot_partition = 0; + devname = ""; + partname[0] = '\0'; + find = NULL; + + /* Do we know anything about the PROM boot device? */ + for (nf = prom_dev_table; nf->func; nf++) + if (!strcmp(nf->name, promname)) { + find = nf->func; + break; + } + if (find) + boot_device = (*find)(promname, prom_ctlr, prom_unit); + if (boot_device) { + devname = boot_device->dv_xname; + if (boot_device->dv_class == DV_DISK) { + boot_partition = prom_part & 7; + partname[0] = 'a' + boot_partition; + partname[1] = '\0'; + } + } + + printf("boot device: %s%s\n", devname, partname); + setroot(boot_device, boot_partition); +} + +/* + * Functions to find devices using PROM boot parameters. + */ + +/* + * Network device: Just use controller number. + */ +static struct device * +net_find(name, ctlr, unit) + char *name; + int ctlr, unit; +{ + char tname[16]; + + sprintf(tname, "%s%d", name, ctlr); + return (find_dev_byname(tname)); +} + +/* + * SCSI device: The controller number corresponds to the + * scsibus number, and the unit number is (targ*8 + LUN). + */ +static struct device * +scsi_find(name, ctlr, unit) + char *name; + int ctlr, unit; +{ + struct device *scsibus; + struct scsibus_softc *sbsc; + struct scsipi_periph *periph; + int target, lun; + char tname[16]; + + sprintf(tname, "scsibus%d", ctlr); + scsibus = find_dev_byname(tname); + if (scsibus == NULL) + return (NULL); + + /* Compute SCSI target/LUN from PROM unit. */ + target = prom_sd_target((unit >> 3) & 7); + lun = unit & 7; + + /* Find the device at this target/LUN */ + sbsc = (struct scsibus_softc *)scsibus; + periph = sbsc->sc_channel->chan_periphs[target][lun]; + if (periph == NULL) + return (NULL); + + return (periph->periph_dev); +} + +/* + * Xylogics SMD disk: (xy, xd) + * Assume wired-in unit numbers for now... + */ +static struct device * +xx_find(name, ctlr, unit) + char *name; + int ctlr, unit; +{ + int diskunit; + char tname[16]; + + diskunit = (ctlr * 2) + unit; + sprintf(tname, "%s%d", name, diskunit); + return (find_dev_byname(tname)); +} + +/* + * Given a device name, find its struct device + * XXX - Move this to some common file? + */ +static struct device * +find_dev_byname(name) + char *name; +{ + struct device *dv; + + for (dv = alldevs.tqh_first; dv != NULL; + dv = dv->dv_list.tqe_next) { + if (!strcmp(dv->dv_xname, name)) { + return(dv); + } + } + return (NULL); +} diff --git a/sys/arch/sun68k/sun68k/bus.c b/sys/arch/sun68k/sun68k/bus.c new file mode 100644 index 000000000000..82b203d983b7 --- /dev/null +++ b/sys/arch/sun68k/sun68k/bus.c @@ -0,0 +1,829 @@ +/* $NetBSD: bus.c,v 1.1 2001/06/27 02:48:32 fredette Exp $ */ + +/* + * Copyright (c) 2001 Matthew Fredette. + * Copyright (c) 1994, 1995 Gordon W. Ross + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah Hdr: machdep.c 1.74 92/12/20 + * from: @(#)machdep.c 8.10 (Berkeley) 4/20/94 + */ + +/*- + * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)machdep.c 8.6 (Berkeley) 1/14/94 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include /* XXX: not _extern ... need vm_map_create */ + +#include +#define _SUN68K_BUS_DMA_PRIVATE +#include +#include +#include +#include + +#include + +/* + * Common function for DMA map creation. May be called by bus-specific + * DMA map creation functions. + */ +int +_bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp) + bus_dma_tag_t t; + bus_size_t size; + int nsegments; + bus_size_t maxsegsz; + bus_size_t boundary; + int flags; + bus_dmamap_t *dmamp; +{ + struct sun68k_bus_dmamap *map; + void *mapstore; + size_t mapsize; + + /* + * Allocate and initialize the DMA map. The end of the map + * is a variable-sized array of segments, so we allocate enough + * room for them in one shot. + * + * Note we don't preserve the WAITOK or NOWAIT flags. Preservation + * of ALLOCNOW notifies others that we've reserved these resources, + * and they are not to be freed. + * + * The bus_dmamap_t includes one bus_dma_segment_t, hence + * the (nsegments - 1). + */ + mapsize = sizeof(struct sun68k_bus_dmamap) + + (sizeof(bus_dma_segment_t) * (nsegments - 1)); + if ((mapstore = malloc(mapsize, M_DMAMAP, + (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL) + return (ENOMEM); + + bzero(mapstore, mapsize); + map = (struct sun68k_bus_dmamap *)mapstore; + map->_dm_size = size; + map->_dm_segcnt = nsegments; + map->_dm_maxsegsz = maxsegsz; + map->_dm_boundary = boundary; + map->_dm_align = PAGE_SIZE; + map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT); + map->dm_mapsize = 0; /* no valid mappings */ + map->dm_nsegs = 0; + + *dmamp = map; + return (0); +} + +/* + * Common function for DMA map destruction. May be called by bus-specific + * DMA map destruction functions. + */ +void +_bus_dmamap_destroy(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + + /* + * If the handle contains a valid mapping, unload it. + */ + if (map->dm_mapsize != 0) + bus_dmamap_unload(t, map); + + free(map, M_DMAMAP); +} + +/* + * Common function for DMA-safe memory allocation. May be called + * by bus-specific DMA memory allocation functions. + */ +int +_bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags) + bus_dma_tag_t t; + bus_size_t size, alignment, boundary; + bus_dma_segment_t *segs; + int nsegs; + int *rsegs; + int flags; +{ + vaddr_t low, high; + struct pglist *mlist; + int error; +extern vm_offset_t avail_start; +extern vm_offset_t avail_end; + + /* Always round the size. */ + size = m68k_round_page(size); + low = avail_start; + high = avail_end; + + if ((mlist = malloc(sizeof(*mlist), M_DEVBUF, + (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL) + return (ENOMEM); + + /* + * Allocate physical pages from the VM system. + */ + TAILQ_INIT(mlist); + error = uvm_pglistalloc(size, low, high, 0, 0, + mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0); + if (error) + return (error); + + /* + * Simply keep a pointer around to the linked list, so + * bus_dmamap_free() can return it. + * + * NOBODY SHOULD TOUCH THE pageq FIELDS WHILE THESE PAGES + * ARE IN OUR CUSTODY. + */ + segs[0]._ds_mlist = mlist; + + /* + * We now have physical pages, but no DVMA addresses yet. These + * will be allocated in bus_dmamap_load*() routines. Hence we + * save any alignment and boundary requirements in this dma + * segment. + */ + segs[0].ds_addr = 0; + segs[0].ds_len = 0; + segs[0]._ds_va = 0; + *rsegs = 1; + return (0); +} + +/* + * Common function for freeing DMA-safe memory. May be called by + * bus-specific DMA memory free functions. + */ +void +_bus_dmamem_free(t, segs, nsegs) + bus_dma_tag_t t; + bus_dma_segment_t *segs; + int nsegs; +{ + + if (nsegs != 1) + panic("bus_dmamem_free: nsegs = %d", nsegs); + + /* + * Return the list of physical pages back to the VM system. + */ + uvm_pglistfree(segs[0]._ds_mlist); + free(segs[0]._ds_mlist, M_DEVBUF); +} + +/* + * Common function for mapping DMA-safe memory. May be called by + * bus-specific DMA memory map functions. + */ +int +_bus_dmamem_map(t, segs, nsegs, size, kvap, flags) + bus_dma_tag_t t; + bus_dma_segment_t *segs; + int nsegs; + size_t size; + caddr_t *kvap; + int flags; +{ + vm_page_t m; + vaddr_t va; + struct pglist *mlist; + + if (nsegs != 1) + panic("_bus_dmamem_map: nsegs = %d", nsegs); + + size = m68k_round_page(size); + + va = uvm_km_valloc(kernel_map, size); + if (va == 0) + return (ENOMEM); + + segs[0]._ds_va = va; + *kvap = (caddr_t)va; + + mlist = segs[0]._ds_mlist; + for (m = TAILQ_FIRST(mlist); m != NULL; m = TAILQ_NEXT(m,pageq)) { + paddr_t pa; + + if (size == 0) + panic("_bus_dmamem_map: size botch"); + + pa = VM_PAGE_TO_PHYS(m); + pmap_enter(pmap_kernel(), va, pa | PMAP_NC, + VM_PROT_READ | VM_PROT_WRITE, + VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED); + + va += PAGE_SIZE; + size -= PAGE_SIZE; + } + pmap_update(); + + return (0); +} + +/* + * Common function for unmapping DMA-safe memory. May be called by + * bus-specific DMA memory unmapping functions. + */ +void +_bus_dmamem_unmap(t, kva, size) + bus_dma_tag_t t; + caddr_t kva; + size_t size; +{ + +#ifdef DIAGNOSTIC + if ((u_long)kva & PAGE_MASK) + panic("_bus_dmamem_unmap"); +#endif + + size = m68k_round_page(size); + uvm_unmap(kernel_map, (vaddr_t)kva, (vaddr_t)kva + size); +} + +/* + * Common functin for mmap(2)'ing DMA-safe memory. May be called by + * bus-specific DMA mmap(2)'ing functions. + */ +paddr_t +_bus_dmamem_mmap(t, segs, nsegs, off, prot, flags) + bus_dma_tag_t t; + bus_dma_segment_t *segs; + int nsegs; + off_t off; + int prot, flags; +{ + + panic("_bus_dmamem_mmap: not implemented"); +} + +/* + * Utility to allocate an aligned kernel virtual address range + */ +vaddr_t +_bus_dma_valloc_skewed(size, boundary, align, skew) + size_t size; + u_long boundary; + u_long align; + u_long skew; +{ + size_t oversize; + vaddr_t va, sva; + + /* + * Find a region of kernel virtual addresses that is aligned + * to the given address modulo the requested alignment, i.e. + * + * (va - skew) == 0 mod align + * + * The following conditions apply to the arguments: + * + * - `size' must be a multiple of the VM page size + * - `align' must be a power of two + * and greater than or equal to the VM page size + * - `skew' must be smaller than `align' + * - `size' must be smaller than `boundary' + */ + +#ifdef DIAGNOSTIC + if ((size & PAGE_MASK) != 0) + panic("_bus_dma_valloc_skewed: invalid size %lx", (unsigned long) size); + if ((align & PAGE_MASK) != 0) + panic("_bus_dma_valloc_skewed: invalid alignment %lx", align); + if (align < skew) + panic("_bus_dma_valloc_skewed: align %lx < skew %lx", + align, skew); +#endif + + /* XXX - Implement this! */ + if (boundary) + panic("_bus_dma_valloc_skewed: not implemented"); + + /* + * First, find a region large enough to contain any aligned chunk + */ + oversize = size + align - PAGE_SIZE; + sva = uvm_km_valloc(kernel_map, oversize); + if (sva == 0) + return (ENOMEM); + + /* + * Compute start of aligned region + */ + va = sva; + va += (skew + align - va) & (align - 1); + + /* + * Return excess virtual addresses + */ + if (va != sva) + (void)uvm_unmap(kernel_map, sva, va); + if (va + size != sva + oversize) + (void)uvm_unmap(kernel_map, va + size, sva + oversize); + + return (va); +} + +/* + * Like _bus_dmamap_load(), but for mbufs. + */ +int +_bus_dmamap_load_mbuf(t, map, m, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct mbuf *m; + int flags; +{ + + panic("_bus_dmamap_load_mbuf: not implemented"); +} + +/* + * Like _bus_dmamap_load(), but for uios. + */ +int +_bus_dmamap_load_uio(t, map, uio, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct uio *uio; + int flags; +{ + + panic("_bus_dmamap_load_uio: not implemented"); +} + +/* + * Common function for DMA map synchronization. May be called + * by bus-specific DMA map synchronization functions. + */ +void +_bus_dmamap_sync(t, map, offset, len, ops) + bus_dma_tag_t t; + bus_dmamap_t map; + bus_addr_t offset; + bus_size_t len; + int ops; +{ +} + +struct sun68k_bus_dma_tag mainbus_dma_tag = { + NULL, + _bus_dmamap_create, + _bus_dmamap_destroy, + _bus_dmamap_load, + _bus_dmamap_load_mbuf, + _bus_dmamap_load_uio, + _bus_dmamap_load_raw, + _bus_dmamap_unload, + _bus_dmamap_sync, + + _bus_dmamem_alloc, + _bus_dmamem_free, + _bus_dmamem_map, + _bus_dmamem_unmap, + _bus_dmamem_mmap +}; + + +/* + * Base bus space handlers. + */ +int sun68k_find_prom_map __P(( bus_addr_t, bus_type_t, + int, bus_space_handle_t *)); +static int sun68k_bus_map __P(( bus_space_tag_t, bus_type_t, bus_addr_t, + bus_size_t, int, vaddr_t, + bus_space_handle_t *)); +static int sun68k_bus_unmap __P((bus_space_tag_t, bus_space_handle_t, + bus_size_t)); +static int sun68k_bus_subregion __P((bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, + bus_space_handle_t *)); +static int sun68k_bus_mmap __P((bus_space_tag_t, bus_type_t, + bus_addr_t, int, bus_space_handle_t *)); +static void *sun68k_mainbus_intr_establish __P((bus_space_tag_t, int, int, + int, int (*) __P((void *)), + void *)); +static void sun68k_bus_barrier __P(( bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, int)); +static int sun68k_bus_peek __P(( bus_space_tag_t, bus_space_handle_t, + bus_size_t, size_t, void *)); +static int sun68k_bus_poke __P(( bus_space_tag_t, bus_space_handle_t, + bus_size_t, size_t, u_int32_t)); + +/* + * If we can find a mapping that was established by the PROM, use it. + */ +int +sun68k_find_prom_map(pa, iospace, len, hp) + bus_addr_t pa; + bus_type_t iospace; + int len; + bus_space_handle_t *hp; +{ + u_long pf; + int pgtype; + u_long va, eva; + int sme; + u_long pte; + int saved_ctx; + + /* + * The mapping must fit entirely within one page. + */ + if ((((u_long)pa & PGOFSET) + len) > NBPG) + return (EINVAL); + + pf = PA_PGNUM(pa); + pgtype = iospace << PG_MOD_SHIFT; + saved_ctx = kernel_context(); + + /* + * Walk the PROM address space, looking for a page with the + * mapping we want. + */ + for (va = SUN_MONSTART; va < SUN_MONEND; ) { + + /* + * Make sure this segment is mapped. + */ + sme = get_segmap(va); + if (sme == SEGINV) { + va += NBSG; + continue; /* next segment */ + } + + /* + * Walk the pages of this segment. + */ + for(eva = va + NBSG; va < eva; va += NBPG) { + pte = get_pte(va); + + if ((pte & (PG_VALID | PG_TYPE)) == + (PG_VALID | pgtype) && + PG_PFNUM(pte) == pf) + { + /* + * Found the PROM mapping. + * note: preserve page offset + */ + *hp = (bus_space_handle_t)(va | ((u_long)pa & PGOFSET)); + restore_context(saved_ctx); + return (0); + } + } + } + restore_context(saved_ctx); + return (ENOENT); +} + +int +sun68k_bus_map(t, iospace, addr, size, flags, vaddr, hp) + bus_space_tag_t t; + bus_type_t iospace; + bus_addr_t addr; + bus_size_t size; + vaddr_t vaddr; + bus_space_handle_t *hp; +{ + bus_size_t offset; + vaddr_t v; + + /* + * If we suspect there might be one, try to find + * and use a PROM mapping. + */ + if ((flags & _SUN68K_BUS_MAP_USE_PROM) != 0 && + sun68k_find_prom_map(addr, iospace, size, hp) == 0) + return (0); + + /* + * Adjust the user's request to be page-aligned. + */ + offset = addr & PGOFSET; + addr -= offset; + size += offset; + size = m68k_round_page(size); + if (size == 0) { + printf("sun68k_bus_map: zero size\n"); + return (EINVAL); + } + + /* Get some kernel virtual address space. */ + if (vaddr) + v = vaddr; + else + v = uvm_km_valloc_wait(kernel_map, size); + if (v == 0) + panic("sun68k_bus_map: no memory"); + + /* note: preserve page offset */ + *hp = (bus_space_handle_t)(v | offset); + + /* + * Map the device. + */ + addr |= iospace | PMAP_NC; + pmap_map(v, addr, addr + size, VM_PROT_ALL); + + return (0); +} + +int +sun68k_bus_unmap(t, bh, size) + bus_space_tag_t t; + bus_size_t size; + bus_space_handle_t bh; +{ + bus_size_t offset; + vaddr_t va = (vaddr_t)bh; + + /* + * Adjust the user's request to be page-aligned. + */ + offset = va & PGOFSET; + va -= offset; + size += offset; + size = m68k_round_page(size); + if (size == 0) { + printf("sun68k_bus_unmap: zero size\n"); + return (EINVAL); + } + + /* + * If any part of the request is in the PROM's address space, + * don't unmap it. + */ +#ifdef DIAGNOSTIC + if ((va >= SUN_MONSTART && va < SUN_MONEND) != + ((va + size) >= SUN_MONSTART && (va + size) < SUN_MONEND)) + panic("sun_bus_unmap: bad PROM mapping\n"); +#endif + if (va >= SUN_MONSTART && va < SUN_MONEND) + return (0); + + uvm_km_free_wakeup(kernel_map, va, size); + return (0); +} + +int +sun68k_bus_subregion(tag, handle, offset, size, nhandlep) + bus_space_tag_t tag; + bus_space_handle_t handle; + bus_size_t offset; + bus_size_t size; + bus_space_handle_t *nhandlep; +{ + *nhandlep = handle + offset; + return (0); +} + +int +sun68k_bus_mmap(t, iospace, paddr, flags, hp) + bus_space_tag_t t; + bus_type_t iospace; + bus_addr_t paddr; + int flags; + bus_space_handle_t *hp; +{ + *hp = (bus_space_handle_t)(paddr | iospace | PMAP_NC); + return (0); +} + +/* + * These assist in device probes. + */ + +extern label_t *nofault; + +int +sun68k_bus_peek(tag, handle, offset, size, vp) + bus_space_tag_t tag; + bus_space_handle_t handle; + bus_size_t offset; + size_t size; + void *vp; +{ + int result; + label_t faultbuf; + u_int32_t junk; + + if (vp == NULL) + vp = &junk; + + nofault = &faultbuf; + if (setjmp(&faultbuf)) + result = -1; + else { + switch(size) { + case 1: + *((u_int8_t *) vp) = bus_space_read_1(tag, handle, offset); + break; + case 2: + *((u_int16_t *) vp) = bus_space_read_2(tag, handle, offset); + break; + case 4: + *((u_int32_t *) vp) = bus_space_read_4(tag, handle, offset); + break; + default: + panic("_bus_space_peek: bad size\n"); + } + result = 0; + } + + nofault = NULL; + return (result); +} + +int +sun68k_bus_poke(tag, handle, offset, size, v) + bus_space_tag_t tag; + bus_space_handle_t handle; + bus_size_t offset; + size_t size; + u_int32_t v; +{ + int result; + label_t faultbuf; + + nofault = &faultbuf; + if (setjmp(&faultbuf)) + result = -1; + else { + switch(size) { + case 1: + bus_space_write_1(tag, handle, offset, (u_int8_t) v); + break; + case 2: + bus_space_write_2(tag, handle, offset, (u_int16_t) v); + break; + case 4: + bus_space_write_4(tag, handle, offset, (u_int32_t) v); + break; + default: + panic("_bus_space_poke: bad size\n"); + } + result = 0; + } + + nofault = NULL; + return (result); +} + +void * +sun68k_mainbus_intr_establish(t, pil, level, flags, handler, arg) + bus_space_tag_t t; + int pil; + int level; + int flags; + int (*handler)__P((void *)); + void *arg; +{ + isr_add_autovect(handler, arg, pil); + return (NULL); +} + +void sun68k_bus_barrier (t, h, offset, size, flags) + bus_space_tag_t t; + bus_space_handle_t h; + bus_size_t offset; + bus_size_t size; + int flags; +{ + /* No default barrier action defined */ + return; +} + +struct sun68k_bus_space_tag mainbus_space_tag = { + NULL, /* cookie */ + NULL, /* parent bus tag */ + sun68k_bus_map, /* bus_space_map */ + sun68k_bus_unmap, /* bus_space_unmap */ + sun68k_bus_subregion, /* bus_space_subregion */ + sun68k_bus_barrier, /* bus_space_barrier */ + sun68k_bus_mmap, /* bus_space_mmap */ + sun68k_mainbus_intr_establish, /* bus_intr_establish */ + sun68k_bus_peek, /* bus_space_peek_N */ + sun68k_bus_poke /* bus_space_poke_N */ +}; diff --git a/sys/arch/sun68k/sun68k/isr.c b/sys/arch/sun68k/sun68k/isr.c new file mode 100644 index 000000000000..a5ff53d2f483 --- /dev/null +++ b/sys/arch/sun68k/sun68k/isr.c @@ -0,0 +1,362 @@ +/* $NetBSD: isr.c,v 1.1 2001/06/27 02:48:32 fredette Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Adam Glass and Gordon W. Ross. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This handles multiple attach of autovectored interrupts, + * and the handy software interrupt request register. + */ + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include + +extern int intrcnt[]; /* statistics */ + +#define NUM_LEVELS 8 + +struct isr { + struct isr *isr_next; + isr_func_t isr_intr; + void *isr_arg; + int isr_ipl; +}; + +/* + * Generic soft interrupt support. + */ +struct softintr_head soft_level_heads[(_IPL_SOFT_LEVEL_MAX - _IPL_SOFT_LEVEL_MIN) + 1]; +void *softnet_cookie; +static int softintr_handler __P((void *)); + +void set_vector_entry __P((int, void *)); +void * get_vector_entry __P((int)); + +/* + * These are called from locore. The "struct clockframe" arg + * is really just the normal H/W interrupt frame format. + * (kern_clock really wants it to be named that...) + */ +void isr_autovec __P((struct clockframe)); +void isr_vectored __P((struct clockframe)); + + +void +isr_add_custom(level, handler) + int level; + void *handler; +{ + set_vector_entry(AUTOVEC_BASE + level, handler); +} + + +/* + * netisr junk... + * should use an array of chars instead of + * a bitmask to avoid atomicity locking issues. + */ + +void netintr() +{ + int n, s; + + s = splhigh(); + n = netisr; + netisr = 0; + splx(s); + +#define DONETISR(bit, fn) do { \ + if (n & (1 << bit)) \ + fn(); \ +} while (0) + +#include + +#undef DONETISR +} + + +static struct isr *isr_autovec_list[NUM_LEVELS]; + +/* + * This is called by the assembly routines + * for handling auto-vectored interupts. + */ +void isr_autovec(cf) + struct clockframe cf; +{ + struct isr *isr; + register int n, ipl, vec; + + vec = (cf.cf_vo & 0xFFF) >> 2; + if ((vec < AUTOVEC_BASE) || (vec >= (AUTOVEC_BASE+8))) + panic("isr_autovec: bad vec"); + ipl = vec - AUTOVEC_BASE; + + n = intrcnt[ipl]; + intrcnt[ipl] = n+1; + uvmexp.intrs++; + + isr = isr_autovec_list[ipl]; + if (isr == NULL) { + if (n == 0) + printf("isr_autovec: ipl %d unexpected\n", ipl); + return; + } + + /* Give all the handlers a chance. */ + n = 0; + while (isr) { + n |= isr->isr_intr(isr->isr_arg); + isr = isr->isr_next; + } + if (!n) + printf("isr_autovec: ipl %d not claimed\n", ipl); +} + +/* + * Establish an interrupt handler. + * Called by driver attach functions. + */ +void isr_add_autovect(handler, arg, level) + isr_func_t handler; + void *arg; + int level; +{ + struct isr *new_isr; + + if ((level < 0) || (level >= NUM_LEVELS)) + panic("isr_add: bad level=%d", level); + new_isr = (struct isr *) + malloc(sizeof(struct isr), M_DEVBUF, M_NOWAIT); + if (!new_isr) + panic("isr_add: malloc failed"); + + new_isr->isr_intr = handler; + new_isr->isr_arg = arg; + new_isr->isr_ipl = level; + new_isr->isr_next = isr_autovec_list[level]; + isr_autovec_list[level] = new_isr; +} + +struct vector_handler { + isr_func_t func; + void *arg; +}; +static struct vector_handler isr_vector_handlers[192]; + +/* + * This is called by the assembly glue + * for handling vectored interupts. + */ +void +isr_vectored(cf) + struct clockframe cf; +{ + struct vector_handler *vh; + register int ipl, vec; + + vec = (cf.cf_vo & 0xFFF) >> 2; + ipl = _getsr(); + ipl = (ipl >> 8) & 7; + + intrcnt[ipl]++; + uvmexp.intrs++; + + if (vec < 64 || vec >= 256) { + printf("isr_vectored: vector=0x%x (invalid)\n", vec); + return; + } + vh = &isr_vector_handlers[vec - 64]; + if (vh->func == NULL) { + printf("isr_vectored: vector=0x%x (nul func)\n", vec); + set_vector_entry(vec, (void *)badtrap); + return; + } + + /* OK, call the isr function. */ + if (vh->func(vh->arg) == 0) + printf("isr_vectored: vector=0x%x (not claimed)\n", vec); +} + +/* + * Establish an interrupt handler. + * Called by driver attach functions. + */ +extern void _isr_vectored __P((void)); +void +isr_add_vectored(func, arg, level, vec) + isr_func_t func; + void *arg; + int level, vec; +{ + struct vector_handler *vh; + + if (vec < 64 || vec >= 256) { + printf("isr_add_vectored: vect=0x%x (invalid)\n", vec); + return; + } + vh = &isr_vector_handlers[vec - 64]; + if (vh->func) { + printf("isr_add_vectored: vect=0x%x (in use)\n", vec); + return; + } + vh->func = func; + vh->arg = arg; + set_vector_entry(vec, (void *)_isr_vectored); +} + +/* + * Generic soft interrupt support. + */ + +/* + * The soft interrupt handler. + */ +static int +softintr_handler(void *arg) +{ + struct softintr_head *shd = arg; + struct softintr_handler *sh; + + /* Clear the interrupt. */ + isr_soft_clear(shd->shd_ipl); + uvmexp.softs++; + + /* Dispatch any pending handlers. */ + for(sh = LIST_FIRST(&shd->shd_intrs); sh != NULL; sh = LIST_NEXT(sh, sh_link)) { + if (sh->sh_pending) { + (*sh->sh_func)(sh->sh_arg); + sh->sh_pending = 0; + } + } + + return (1); +} + +/* + * This initializes soft interrupts. + */ +void +softintr_init(void) +{ + int ipl; + struct softintr_head *shd; + + for(ipl = _IPL_SOFT_LEVEL_MIN; ipl <= _IPL_SOFT_LEVEL_MAX; ipl++) { + shd = &soft_level_heads[ipl - _IPL_SOFT_LEVEL_MIN]; + shd->shd_ipl = ipl; + LIST_INIT(&shd->shd_intrs); + isr_add_autovect(softintr_handler, shd, ipl); + } + + softnet_cookie = softintr_establish(IPL_SOFTNET, (void (*) __P((void *))) netintr, NULL); +} + +/* + * This establishes a soft interrupt handler. + */ +void * +softintr_establish(int ipl, void (*func)(void *), void *arg) +{ + struct softintr_handler *sh; + struct softintr_head *shd; + + if (ipl < _IPL_SOFT_LEVEL_MIN || ipl > _IPL_SOFT_LEVEL_MAX) + panic("softintr_establish: unsupported soft IPL"); + + shd = &soft_level_heads[ipl - _IPL_SOFT_LEVEL_MIN]; + + sh = malloc(sizeof(*sh), M_SOFTINTR, M_NOWAIT); + if (sh == NULL) + return NULL; + + LIST_INSERT_HEAD(&shd->shd_intrs, sh, sh_link); + sh->sh_head = shd; + sh->sh_pending = 0; + sh->sh_func = func; + sh->sh_arg = arg; + + return sh; +} + +/* + * This disestablishes a soft interrupt handler. + */ +void +softintr_disestablish(void *arg) +{ + struct softintr_handler *sh = arg; + LIST_REMOVE(sh, sh_link); + free(sh, M_SOFTINTR); +} + + +/* + * XXX - could just kill these... + */ +void +set_vector_entry(entry, handler) + int entry; + void *handler; +{ + if ((entry <0) || (entry >= NVECTORS)) + panic("set_vector_entry: setting vector too high or low\n"); + vector_table[entry] = handler; +} + +void * +get_vector_entry(entry) + int entry; +{ + if ((entry <0) || (entry >= NVECTORS)) + panic("get_vector_entry: setting vector too high or low\n"); + return ((void *) vector_table[entry]); +} diff --git a/sys/arch/sun68k/sun68k/procfs_machdep.c b/sys/arch/sun68k/sun68k/procfs_machdep.c new file mode 100644 index 000000000000..36a9ac79e65f --- /dev/null +++ b/sys/arch/sun68k/sun68k/procfs_machdep.c @@ -0,0 +1,20 @@ +/* $NetBSD: procfs_machdep.c,v 1.1 2001/06/27 02:48:32 fredette Exp $ */ + +#include +#include +#include +#include +#include + + +/* + * Linux-style /proc/cpuinfo. + * Only used when procfs is mounted with -o linux. + */ +int +procfs_getcpuinfstr(char *buf, int *len) +{ + *len = 0; + + return 0; +} diff --git a/sys/arch/sun68k/sun68k/vme_sun68k.c b/sys/arch/sun68k/sun68k/vme_sun68k.c new file mode 100644 index 000000000000..8aeaca36d1db --- /dev/null +++ b/sys/arch/sun68k/sun68k/vme_sun68k.c @@ -0,0 +1,423 @@ +/* $NetBSD: vme_sun68k.c,v 1.1 2001/06/27 02:48:32 fredette Exp $ */ + +/*- + * Copyright (c) 1997, 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg and Matthew Fredette. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define _SUN68K_BUS_DMA_PRIVATE +#include +#include +#include +#include + +#include +#include + +#include + +struct sun68kvme_softc { + struct device sc_dev; /* base device */ + bus_space_tag_t sc_bustag; + bus_dma_tag_t sc_dmatag; +}; +struct sun68kvme_softc *sun68kvme_sc;/*XXX*/ + +/* autoconfiguration driver */ +static int sun68kvme_match __P((struct device *, struct cfdata *, void *)); +static void sun68kvme_attach __P((struct device *, struct device *, void *)); + +static int sun68k_vme_probe __P((void *, vme_addr_t, vme_size_t, + vme_am_t, vme_datasize_t, + int (*) __P((void *, bus_space_tag_t, bus_space_handle_t)), void *)); +static int sun68k_vme_map __P((void *, vme_addr_t, vme_size_t, vme_am_t, + vme_datasize_t, vme_swap_t, + bus_space_tag_t *, bus_space_handle_t *, + vme_mapresc_t *)); +static void sun68k_vme_unmap __P((void *, vme_mapresc_t)); +static int sun68k_vme_intr_map __P((void *, int, int, vme_intr_handle_t *)); +static const struct evcnt *sun68k_vme_intr_evcnt __P((void *, + vme_intr_handle_t)); +static void * sun68k_vme_intr_establish __P((void *, vme_intr_handle_t, int, + int (*) __P((void *)), void *)); +static void sun68k_vme_intr_disestablish __P((void *, void *)); + +/* + * DMA functions. + */ +static void sun68k_vct_dmamap_destroy __P((void *, bus_dmamap_t)); + +static int sun68k_vct_dmamap_create __P((void *, vme_size_t, vme_am_t, + vme_datasize_t, vme_swap_t, int, vme_size_t, vme_addr_t, + int, bus_dmamap_t *)); +static int sun68k_vme_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int)); +static int sun68k_vme_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int)); + +int sun68k_vme_mmap_cookie __P((vme_addr_t, vme_am_t, bus_space_handle_t *)); + +struct cfattach sun68kvme_ca = { + sizeof(struct sun68kvme_softc), sun68kvme_match, sun68kvme_attach +}; + +/* + * The VME bus logic on sun68k machines maps DMA requests in the first MB + * of VME space to the last MB of DVMA space. The base bus_dma code + * in machdep.c manages DVMA space; all we must do is adjust the DMA + * addresses returned by bus_dmamap_load*() by ANDing them with + * DVMA_VME_SLAVE_MASK. + */ + +struct vme_chipset_tag sun68k_vme_chipset_tag = { + NULL, + sun68k_vme_map, + sun68k_vme_unmap, + sun68k_vme_probe, + sun68k_vme_intr_map, + sun68k_vme_intr_evcnt, + sun68k_vme_intr_establish, + sun68k_vme_intr_disestablish, + sun68k_vct_dmamap_create, + sun68k_vct_dmamap_destroy +}; + +struct sun68k_bus_dma_tag sun68k_vme_dma_tag; + +/* Does this machine have a VME bus? */ +extern int cpu_has_vme; + +/* + * Probe the VME bus. + */ +int +sun68kvme_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct mainbus_attach_args *ma = aux; + + return (cpu_has_vme && (ma->ma_name == NULL || strcmp(cf->cf_driver->cd_name, ma->ma_name) == 0)); +} + +/* + * Attach the VME bus. + */ +void +sun68kvme_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct mainbus_attach_args *ma = aux; + struct sun68kvme_softc *sc = (struct sun68kvme_softc *)self; + struct vmebus_attach_args vba; + + if (self->dv_unit > 0) { + printf(" unsupported\n"); + return; + } + + sun68kvme_sc = sc; + + sc->sc_bustag = ma->ma_bustag; + sc->sc_dmatag = ma->ma_dmatag; + + sun68k_vme_chipset_tag.cookie = self; + sun68k_vme_dma_tag = *ma->ma_dmatag; + sun68k_vme_dma_tag._cookie = self; + sun68k_vme_dma_tag._dmamap_load = sun68k_vme_dmamap_load; + sun68k_vme_dma_tag._dmamap_load_raw = sun68k_vme_dmamap_load_raw; + + vba.va_vct = &sun68k_vme_chipset_tag; + vba.va_bdt = &sun68k_vme_dma_tag; + vba.va_slaveconfig = 0; + + printf("\n"); + (void)config_found(self, &vba, 0); +} + +/* + * Probes for a device on the VME bus. + * Returns zero on success. + */ +int +sun68k_vme_probe(cookie, addr, len, mod, datasize, callback, arg) + void *cookie; + vme_addr_t addr; + vme_size_t len; + vme_am_t mod; + vme_datasize_t datasize; + int (*callback) __P((void *, bus_space_tag_t, bus_space_handle_t)); + void *arg; +{ + struct sun68kvme_softc *sc = (struct sun68kvme_softc *)cookie; + bus_type_t iospace; + bus_addr_t paddr; + bus_space_handle_t handle; + bus_size_t size; + bus_size_t off, max_off; + int error; + + /* Map in the space. */ + error = vmebus_translate(mod, addr, &iospace, &paddr); + if (error == 0) + error = bus_space_map2(sc->sc_bustag, iospace, paddr, len, + 0, NULL, &handle); + if (error) + return (error); + + /* Probe the space. */ + size = (datasize == VME_D8 ? 1 : (datasize == VME_D16 ? 2 : 4)); + max_off = (callback ? size : len); + for (off = 0; off < max_off; off += size) { + error = _bus_space_peek(sc->sc_bustag, handle, off, size, NULL); + if (error) + break; + } + if (error == 0 && callback) + error = (*callback)(arg, sc->sc_bustag, handle); + + /* Unmap the space. */ + bus_space_unmap(sc->sc_bustag, handle, len); + + return (error); +} + +/* + * Maps in a device on the VME bus. + */ +int +sun68k_vme_map(cookie, addr, size, mod, datasize, swap, tp, hp, rp) + void *cookie; + vme_addr_t addr; + vme_size_t size; + vme_am_t mod; + vme_datasize_t datasize; + vme_swap_t swap; + bus_space_tag_t *tp; + bus_space_handle_t *hp; + vme_mapresc_t *rp; +{ + struct sun68kvme_softc *sc = (struct sun68kvme_softc *)cookie; + bus_type_t iospace; + bus_addr_t paddr; + int error; + + error = vmebus_translate(mod, addr, &iospace, &paddr); + if (error != 0) + return (error); + + *tp = sc->sc_bustag; + return (bus_space_map2(sc->sc_bustag, iospace, paddr, size, 0, 0, hp)); +} + +/* + * Assists in mmap'ing a device on the VME bus. + */ +int +sun68k_vme_mmap_cookie(addr, mod, hp) + vme_addr_t addr; + vme_am_t mod; + bus_space_handle_t *hp; +{ + struct sun68kvme_softc *sc = sun68kvme_sc; + bus_type_t iospace; + bus_addr_t paddr; + int error; + + error = vmebus_translate(mod, addr, &iospace, &paddr); + if (error != 0) + return (error); + + return (bus_space_mmap(sc->sc_bustag, iospace, paddr, 0, hp)); +} + +struct sun68k_vme_intr_handle { + int vec; /* VME interrupt vector */ + int pri; /* VME interrupt priority */ +}; + +/* + * This maps a VME interrupt level and vector pair into + * a data structure that can subsequently be used to + * establish an interrupt handler. + */ +int +sun68k_vme_intr_map(cookie, level, vec, ihp) + void *cookie; + int level; + int vec; + vme_intr_handle_t *ihp; +{ + struct sun68k_vme_intr_handle *svih; + + svih = (vme_intr_handle_t) + malloc(sizeof(struct sun68k_vme_intr_handle), M_DEVBUF, M_NOWAIT); + svih->pri = level; + svih->vec = vec; + *ihp = svih; + return (0); +} + +const struct evcnt * +sun68k_vme_intr_evcnt(cookie, vih) + void *cookie; + vme_intr_handle_t vih; +{ + + /* XXX for now, no evcnt parent reported */ + return NULL; +} + +/* + * Establish a VME bus interrupt. + */ +void * +sun68k_vme_intr_establish(cookie, vih, pri, func, arg) + void *cookie; + vme_intr_handle_t vih; + int pri; + int (*func) __P((void *)); + void *arg; +{ + struct sun68k_vme_intr_handle *svih = + (struct sun68k_vme_intr_handle *)vih; + + /* Install interrupt handler. */ + isr_add_vectored(func, (void *)arg, + svih->pri, svih->vec); + + return (NULL); +} + +void +sun68k_vme_unmap(cookie, resc) + void * cookie; + vme_mapresc_t resc; +{ + /* Not implemented */ + panic("sun68k_vme_unmap"); +} + +void +sun68k_vme_intr_disestablish(cookie, a) + void *cookie; + void *a; +{ + /* Not implemented */ + panic("sun68k_vme_intr_disestablish"); +} + +/* + * VME DMA functions. + */ + +static void +sun68k_vct_dmamap_destroy(cookie, map) + void *cookie; + bus_dmamap_t map; +{ + struct sun68kvme_softc *sc = (struct sun68kvme_softc *)cookie; + bus_dmamap_destroy(sc->sc_dmatag, map); +} + +static int +sun68k_vct_dmamap_create(cookie, size, am, datasize, swap, nsegments, maxsegsz, + boundary, flags, dmamp) + void *cookie; + vme_size_t size; + vme_am_t am; + vme_datasize_t datasize; + vme_swap_t swap; + int nsegments; + vme_size_t maxsegsz; + vme_addr_t boundary; + int flags; + bus_dmamap_t *dmamp; +{ + struct sun68kvme_softc *sc = (struct sun68kvme_softc *)cookie; + + /* Allocate a base map through parent bus ops */ + return (bus_dmamap_create(sc->sc_dmatag, size, nsegments, maxsegsz, + boundary, flags, dmamp)); +} + +int +sun68k_vme_dmamap_load(t, map, buf, buflen, p, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + void *buf; + bus_size_t buflen; + struct proc *p; + int flags; +{ + int error; + + error = _bus_dmamap_load(t, map, buf, buflen, p, flags); + if (error == 0) + map->dm_segs[0].ds_addr &= DVMA_VME_SLAVE_MASK; + return (error); +} + +int +sun68k_vme_dmamap_load_raw(t, map, segs, nsegs, size, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + bus_dma_segment_t *segs; + int nsegs; + bus_size_t size; + int flags; +{ + int error; + + error = _bus_dmamap_load_raw(t, map, segs, nsegs, size, flags); + if (error == 0) + map->dm_segs[0].ds_addr &= DVMA_VME_SLAVE_MASK; + return (error); +} + diff --git a/sys/arch/sun68k/sun68k/vme_sun68k.h b/sys/arch/sun68k/sun68k/vme_sun68k.h new file mode 100644 index 000000000000..65d4d3fb6474 --- /dev/null +++ b/sys/arch/sun68k/sun68k/vme_sun68k.h @@ -0,0 +1,41 @@ +/* $NetBSD: vme_sun68k.h,v 1.1 2001/06/27 02:48:32 fredette Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Fredette. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +int vmebus_translate __P((vme_am_t, vme_addr_t, + bus_type_t *, bus_addr_t *)); +