#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: zbus.c,v 1.78 2023/05/03 13:49:30 phx Exp $");
#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <machine/cpu.h>
#include <machine/pte.h>
#include <amiga/amiga/cfdev.h>
#include <amiga/amiga/device.h>
#include <amiga/dev/zbusvar.h>
#include <amiga/dev/z3rambdvar.h>
#include "z3rambd.h"
struct aconfdata {
const char *name;
int manid;
int prodid;
};
struct preconfdata {
int manid;
int prodid;
void *vaddr;
};
struct quirksdata {
int manid;
int prodid;
uint8_t quirks;
};
vaddr_t ZTWOROMADDR;
vaddr_t ZTWOMEMADDR;
u_int NZTWOMEMPG;
vaddr_t ZBUSADDR;
u_int ZBUSAVAIL;
static const struct aconfdata aconftab[] = {
{ "atzee", 513, 1 },
{ "atzsc", 514, 2 },
{ "atzsc", 514, 3 },
{ "bah", 514, 9 },
{ "ql", 514, 69 },
{ "ql", 514, 70 },
{ "atfsc", 514, 84 },
{ "le", 514, 112 },
{ "le", 1053, 1 },
{ "bah", 1053, 9 },
{ "es", 1053, 10 },
{ "grful", 1030, 0 },
{ "grfrs", 2129, 1 },
{ "grfrt", 18260, 6 },
{ "grfrh", 18260, 16},
{ "grfrh", 18260, 19},
{ "gvpbus", 2017, 2 },
{ "gvpbus", 2017, 11 },
{ "giv", 2017, 32 },
{ "gio", 2017, 255 },
{ "zssc", 2026, 150 },
{ "ppia", 2026, 187 },
{ "ppta", 2026, 105 },
{ "ppha", 2026, 1 },
{ "mrsc", 2026, 0 },
{ "mgnsc", 1058, 17 },
{ "otgsc", 1058, 21 },
{ "vhzsc", 1010, 69 },
{ "wstsc", 1056, 12 },
{ "wstsc", 1056, 13 },
{ "itrmp", 2112, 48 },
{ "itrmp", 2112, 52 },
{ "ivasc", 2112, 242 },
{ "ivsc", 2112, 243 },
{ "ed", 2121, 1 },
{ "ed", 1023, 254 },
{ "le", 2167, 201},
{ "ne", 2167, 202},
{ "Tandem", 2092, 6 },
{ "mfc", 2092, 16 },
{ "mfc", 2092, 17 },
{ "mfc", 2092, 18 },
{ "grfcl", 2167, 11},
{ "grfcl", 2167, 12},
{ "grfcl", 2167, 21},
{ "grfcl", 2167, 22},
{ "grfcl", 2167, 23},
{ "grfcl", 2167, 24},
{ "grfcl", 2193, 2},
{ "grfcl", 2193, 1},
{ "grfcl", 2195, 5},
{ "grfcl", 2195, 6},
{ "grfcl", 2195, 10},
{ "grfcl", 2195, 11},
{ "wesc", 2203, 19},
{ "flmem", 8512, 10},
{ "flsc", 8512, 11},
{ "cbsc", 8512, 12},
{ "bzivsc", 8512, 17},
{ "bztzsc", 8512, 24},
{ "cbiisc", 8512, 25},
{ "grfcv", 8512, 34},
{ "grfcv3d", 8512, 67},
{ "cbiiisc", 8512, 100},
{ "p5pb", 8512, 101},
{ "bppcsc", 8512, 110},
{ "mlhsc", 2011, 1 },
{ "qn", 2011, 2 },
{ "empsc", 2171, 21 },
{ "empsc", 2171, 32 },
{ "grfet", 2117, 3 },
{ "grfet", 2117, 4 },
{ "grfet", 2167, 1 },
{ "grfet", 2167, 2 },
{ "grfet", 2167, 3 },
{ "grfet", 2181, 0 },
{ "nxsc", 2102, 1 },
{ "mcsc", 8535, 4 },
{ "apssc", 8738, 35 },
{ "aumld", 2145, 128 },
{ "buddha", 4626, 0 },
{ "xsurf", 4626, 23 },
{ "blst", 5001, 1},
{ "hyper4", 5001, 2},
{ "hyper3Z", 5001, 3},
{ "hyper4+", 5001, 6},
{ "hyper3+", 5001, 7},
{ "mppb", 44359, 1},
{ "mntva", 28014, 1},
{ "zz9k", 28014, 3},
{ "zz9k", 28014, 4},
{ "zz9k", 28014, 5}
};
static int naconfent = sizeof(aconftab) / sizeof(struct aconfdata);
static struct preconfdata preconftab[] = {
{18260, 6, 0 },
{18260, 16, 0},
{18260, 19, 0},
{2167, 11, 0},
{2167, 12, 0},
{2167, 21, 0},
{2167, 22, 0},
{2167, 23, 0},
{2167, 24, 0},
{2193, 2, 0},
{2193, 1, 0},
{2195, 5, 0},
{2195, 6, 0},
{2195, 10, 0},
{2195, 11, 0},
{1030, 0, 0},
{8512, 34, 0},
{2117, 3, 0},
{2117, 4, 0},
{2167, 1, 0},
{2167, 2, 0},
{2167, 3, 0},
{2181, 0, 0},
{8512, 67, 0},
{28014, 3, 0},
{28014, 4, 0}
};
static int npreconfent = sizeof(preconftab) / sizeof(struct preconfdata);
#define ZORRO_QUIRK_NO_ZBUSMAP 1
static struct quirksdata quirkstab[] = {
{8512, 101, ZORRO_QUIRK_NO_ZBUSMAP}
};
static int nquirksent = sizeof(quirkstab) / sizeof(struct quirksdata);
void zbusattach(device_t, device_t, void *);
int zbusprint(void *, const char *);
int zbusmatch(device_t, cfdata_t, void *);
static const char *aconflookup(int, int);
static uint8_t
quirkslookup(int mid, int pid)
{
const struct quirksdata *qdp, *eqdp;
eqdp = &quirkstab[nquirksent];
for (qdp = quirkstab; qdp < eqdp; qdp++)
if (qdp->manid == mid && qdp->prodid == pid)
return(qdp->quirks);
return(0);
}
static const char *
aconflookup(int mid, int pid)
{
const struct aconfdata *adp, *eadp;
eadp = &aconftab[naconfent];
for (adp = aconftab; adp < eadp; adp++)
if (adp->manid == mid && adp->prodid == pid)
return(adp->name);
return("board");
}
CFATTACH_DECL_NEW(zbus, 0,
zbusmatch, zbusattach, NULL, NULL);
static cfdata_t early_cfdata;
int
zbusmatch(device_t parent, cfdata_t cf, void *aux)
{
if (matchname(aux, "zbus") == 0)
return(0);
if (amiga_realconfig == 0)
early_cfdata = cf;
return(1);
}
void
zbusattach(device_t parent, device_t self, void *aux)
{
struct zbus_args za;
struct preconfdata *pcp, *epcp;
struct cfdev *cdp, *ecdp;
epcp = &preconftab[npreconfent];
ecdp = &cfdev[ncfdev];
if (amiga_realconfig) {
if (ZTWOMEMADDR)
printf(": mem 0x%08lx-0x%08lx",
ZTWOMEMADDR,
ZTWOMEMADDR + PAGE_SIZE * NZTWOMEMPG - 1);
if (ZBUSAVAIL)
printf (": i/o size 0x%08x", ZBUSAVAIL);
printf("\n");
}
for (cdp = cfdev; cdp < ecdp; cdp++) {
for (pcp = preconftab; pcp < epcp; pcp++) {
if (pcp->manid == cdp->rom.manid &&
pcp->prodid == cdp->rom.prodid)
break;
}
if (amiga_realconfig == 0 && pcp >= epcp)
continue;
#if NZ3RAMBD > 0
if (z3rambd_match_id(cdp->rom.manid, cdp->rom.prodid) > 0)
{ }
else
#endif
switch (cdp->rom.type & (ERT_TYPEMASK | ERTF_MEMLIST)) {
case ERT_ZORROII:
case ERT_ZORROIII:
break;
default:
continue;
}
za.pa = cdp->addr;
za.size = cdp->size;
za.manid = cdp->rom.manid;
za.prodid = cdp->rom.prodid;
za.serno = cdp->rom.serno;
za.slot = (((u_long)za.pa >> 16) & 0xF) - 0x9;
if (amiga_realconfig && pcp < epcp && pcp->vaddr)
za.va = pcp->vaddr;
else {
if(quirkslookup(za.manid, za.prodid) !=
ZORRO_QUIRK_NO_ZBUSMAP)
za.va = (void *) (isztwopa(za.pa) ?
__UNVOLATILE(ztwomap(za.pa)) :
zbusmap(za.pa, za.size));
if (amiga_realconfig == 0)
pcp->vaddr = za.va;
}
amiga_config_found(early_cfdata, self, &za, zbusprint,
CFARGS_NONE);
}
}
int
zbusprint(void *aux, const char *pnp)
{
struct zbus_args *zap;
int rv;
rv = UNCONF;
zap = aux;
if (pnp) {
aprint_normal("%s at %s:",
aconflookup(zap->manid, zap->prodid), pnp);
if (zap->manid == -1)
rv = UNSUPP;
}
aprint_normal(" pa %8p man/pro %d/%d", zap->pa, zap->manid,
zap->prodid);
return(rv);
}
void *
zbusmap(void *pa, u_int size)
{
#if defined(__m68k__)
static vaddr_t nextkva = 0;
vaddr_t kva;
if (nextkva == 0)
nextkva = ZBUSADDR;
if (nextkva > ZBUSADDR + ZBUSAVAIL)
return 0;
kva = nextkva;
nextkva += size;
if (nextkva > ZBUSADDR + ZBUSAVAIL)
panic("allocating too much Zorro I/O address space");
physaccess((void *)kva, (void *)pa, size, PG_RW|PG_CI);
return((void *)kva);
#else
return(pa);
#endif
}