#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <machine/autoconf.h>
#include <machine/rpb.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <alpha/pci/tsreg.h>
#include <alpha/pci/tsvar.h>
#ifdef DEC_6600
#include <alpha/pci/pci_6600.h>
#endif
#define tsc() { Generate ctags(1) key. }
int tscmatch(struct device *, void *, void *);
void tscattach(struct device *, struct device *, void *);
const struct cfattach tsc_ca = {
sizeof(struct device), tscmatch, tscattach,
};
struct cfdriver tsc_cd = {
NULL, "tsc", DV_DULL,
};
struct tsp_config tsp_configuration[4];
static int tscprint(void *, const char *pnp);
int tspmatch(struct device *, void *, void *);
void tspattach(struct device *, struct device *, void *);
const struct cfattach tsp_ca = {
sizeof(struct tsp_softc), tspmatch, tspattach,
};
struct cfdriver tsp_cd = {
NULL, "tsp", DV_DULL,
};
static int tspprint(void *, const char *pnp);
static int tscfound;
int tsp_console_hose;
int
tscmatch(struct device *parent, void *match, void *aux)
{
struct mainbus_attach_args *ma = aux;
switch (cputype) {
case ST_DEC_6600:
case ST_DEC_TITAN:
return strcmp(ma->ma_name, tsc_cd.cd_name) == 0 && !tscfound;
default:
return 0;
}
}
void
tscattach(struct device *parent, struct device *self, void *aux)
{
int i;
int nbus;
u_int64_t csc, aar;
struct tsp_attach_args tsp;
struct mainbus_attach_args *ma = aux;
int titan = cputype == ST_DEC_TITAN;
tscfound = 1;
csc = LDQP(TS_C_CSC);
nbus = 1 + (CSC_BC(csc) >= 2);
printf(": 2127%c Chipset, Cchip rev %d\n"
"%s%d: %c Dchips, %d memory bus%s of %d bytes\n",
titan ? '4' : '2', (int)MISC_REV(LDQP(TS_C_MISC)),
ma->ma_name, ma->ma_slot, "2448"[CSC_BC(csc)],
nbus, nbus > 1 ? "es" : "", 16 + 16 * ((csc & CSC_AW) != 0));
printf("%s%d: arrays present: ", ma->ma_name, ma->ma_slot);
for(i = 0; i < 4; ++i) {
aar = LDQP(TS_C_AAR0 + i * TS_STEP);
printf("%s%dMB%s", i ? ", " : "", (8 << AAR_ASIZ(aar)) & ~0xf,
aar & AAR_SPLIT ? " (split)" : "");
}
printf(", Dchip 0 rev %d\n", (int)LDQP(TS_D_DREV) & 0xf);
tsp.tsp_name = "tsp";
tsp.tsp_slot = 0;
config_found(self, &tsp, tscprint);
if (titan) {
tsp.tsp_slot += 2;
config_found(self, &tsp, tscprint);
}
if (csc & CSC_P1P) {
tsp.tsp_slot = 1;
config_found(self, &tsp, tscprint);
if (titan) {
tsp.tsp_slot += 2;
config_found(self, &tsp, tscprint);
}
}
tsp.tsp_name = "tsciic";
tsp.tsp_slot = -1;
config_found(self, &tsp, tscprint);
}
static int
tscprint(void *aux, const char *p)
{
struct tsp_attach_args *tsp = aux;
if (p)
printf("%s at %s", tsp->tsp_name, p);
if (tsp->tsp_slot >= 0)
printf(" hose %d", tsp->tsp_slot);
return UNCONF;
}
#define tsp() { Generate ctags(1) key. }
int
tspmatch(struct device *parent, void *match, void *aux)
{
struct tsp_attach_args *t = aux;
switch (cputype) {
case ST_DEC_6600:
case ST_DEC_TITAN:
return strcmp(t->tsp_name, tsp_cd.cd_name) == 0;
default:
return 0;
}
}
void
tspattach(struct device *parent, struct device *self, void *aux)
{
struct pcibus_attach_args pba;
struct tsp_attach_args *t = aux;
struct tsp_config *pcp;
printf("\n");
pcp = tsp_init(1, t->tsp_slot);
tsp_dma_init(self, pcp);
tsp_bus_mem_init2(pcp);
pci_6600_pickintr(pcp);
bzero(&pba, sizeof(pba));
pba.pba_busname = "pci";
pba.pba_iot = &pcp->pc_iot;
pba.pba_memt = &pcp->pc_memt;
pba.pba_dmat =
alphabus_dma_get_tag(&pcp->pc_dmat_direct, ALPHA_BUS_PCI);
pba.pba_pc = &pcp->pc_pc;
pba.pba_domain = pci_ndomains++;
pba.pba_bus = 0;
#ifdef notyet
pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED |
PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY;
#endif
config_found(self, &pba, tspprint);
}
struct tsp_config *
tsp_init(int mallocsafe, int n)
{
struct tsp_config *pcp;
int titan = cputype == ST_DEC_TITAN;
KASSERT(n >= 0 && n < nitems(tsp_configuration));
pcp = &tsp_configuration[n];
pcp->pc_pslot = n;
pcp->pc_iobase = TS_Pn(n, 0);
pcp->pc_csr = S_PAGE(TS_Pn(n & 1, P_CSRBASE));
if (n & 2) {
pcp->pc_csr++;
}
if (titan) {
pcp->pc_tlbia = &pcp->pc_csr->port.g.tsp_tlbia.tsg_r;
} else {
pcp->pc_tlbia = &pcp->pc_csr->port.p.tsp_tlbia.tsg_r;
}
snprintf(pcp->pc_io_ex_name, sizeof pcp->pc_io_ex_name,
"tsp%d_bus_io", n);
snprintf(pcp->pc_mem_ex_name, sizeof pcp->pc_mem_ex_name,
"tsp%d_bus_mem", n);
if (!pcp->pc_initted) {
tsp_bus_io_init(&pcp->pc_iot, pcp);
tsp_bus_mem_init(&pcp->pc_memt, pcp);
}
pcp->pc_mallocsafe = mallocsafe;
tsp_pci_init(&pcp->pc_pc, pcp);
alpha_pci_chipset = &pcp->pc_pc;
if (titan)
alpha_pci_chipset->pc_name = "titan";
else
alpha_pci_chipset->pc_name = "tsunami";
alpha_pci_chipset->pc_mem = P_PCI_MEM;
alpha_pci_chipset->pc_ports = P_PCI_IO;
alpha_pci_chipset->pc_hae_mask = 0;
alpha_pci_chipset->pc_dense = TS_P0(0);
alpha_pci_chipset->pc_bwx = 1;
pcp->pc_initted = 1;
return pcp;
}
static int
tspprint(void *aux, const char *p)
{
register struct pcibus_attach_args *pci = aux;
if (p)
printf("%s at %s", pci->pba_busname, p);
printf(" bus %d", pci->pba_bus);
return UNCONF;
}