Added common sun68k autoconfiguration and bus_space
related code. Currently used by sun2.
This commit is contained in:
parent
2de3233da6
commit
5d81b8d269
461
sys/arch/sun68k/sun68k/autoconf.c
Normal file
461
sys/arch/sun68k/sun68k/autoconf.c
Normal 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);
|
||||
}
|
829
sys/arch/sun68k/sun68k/bus.c
Normal file
829
sys/arch/sun68k/sun68k/bus.c
Normal 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 */
|
||||
};
|
362
sys/arch/sun68k/sun68k/isr.c
Normal file
362
sys/arch/sun68k/sun68k/isr.c
Normal 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]);
|
||||
}
|
20
sys/arch/sun68k/sun68k/procfs_machdep.c
Normal file
20
sys/arch/sun68k/sun68k/procfs_machdep.c
Normal 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;
|
||||
}
|
423
sys/arch/sun68k/sun68k/vme_sun68k.c
Normal file
423
sys/arch/sun68k/sun68k/vme_sun68k.c
Normal 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);
|
||||
}
|
||||
|
41
sys/arch/sun68k/sun68k/vme_sun68k.h
Normal file
41
sys/arch/sun68k/sun68k/vme_sun68k.h
Normal 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 *));
|
||||
|
Loading…
Reference in New Issue
Block a user