Added common sun68k autoconfiguration and bus_space

related code.  Currently used by sun2.
This commit is contained in:
fredette 2001-06-27 02:48:32 +00:00
parent 2de3233da6
commit 5d81b8d269
6 changed files with 2136 additions and 0 deletions

View File

@ -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 <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/reboot.h>
#include <dev/scsipi/scsi_all.h>
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsiconf.h>
#include <machine/autoconf.h>
#include <machine/intr.h>
#include <machine/promlib.h>
#ifdef KGDB
#include <sys/kgdb.h>
#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 = "<unknown>";
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);
}

View File

@ -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 <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/map.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <uvm/uvm.h> /* XXX: not _extern ... need vm_map_create */
#include <machine/pte.h>
#define _SUN68K_BUS_DMA_PRIVATE
#include <machine/autoconf.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <machine/pmap.h>
#include <sun68k/sun68k/control.h>
/*
* 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 */
};

View File

@ -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 <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/vmmeter.h>
#include <uvm/uvm_extern.h>
#include <net/netisr.h>
#include <machine/autoconf.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <machine/mon.h>
#include <sun68k/sun68k/vector.h>
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 <net/netisr_dispatch.h>
#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]);
}

View File

@ -0,0 +1,20 @@
/* $NetBSD: procfs_machdep.c,v 1.1 2001/06/27 02:48:32 fredette Exp $ */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <miscfs/procfs/procfs.h>
/*
* Linux-style /proc/cpuinfo.
* Only used when procfs is mounted with -o linux.
*/
int
procfs_getcpuinfstr(char *buf, int *len)
{
*len = 0;
return 0;
}

View File

@ -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 <sys/param.h>
#include <sys/extent.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/errno.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/syslog.h>
#include <uvm/uvm_extern.h>
#define _SUN68K_BUS_DMA_PRIVATE
#include <machine/bus.h>
#include <machine/autoconf.h>
#include <machine/pmap.h>
#include <machine/dvma.h>
#include <dev/vme/vmereg.h>
#include <dev/vme/vmevar.h>
#include <sun68k/sun68k/vme_sun68k.h>
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);
}

View File

@ -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 *));