1*c7fb772bSthorpej /* $NetBSD: asp.c,v 1.4 2021/08/07 16:18:55 thorpej Exp $ */
26d3ceb1dSskrll
36d3ceb1dSskrll /* $OpenBSD: asp.c,v 1.5 2000/02/09 05:04:22 mickey Exp $ */
46d3ceb1dSskrll
56d3ceb1dSskrll /*
66d3ceb1dSskrll * Copyright (c) 1998-2003 Michael Shalayeff
76d3ceb1dSskrll * All rights reserved.
86d3ceb1dSskrll *
96d3ceb1dSskrll * Redistribution and use in source and binary forms, with or without
106d3ceb1dSskrll * modification, are permitted provided that the following conditions
116d3ceb1dSskrll * are met:
126d3ceb1dSskrll * 1. Redistributions of source code must retain the above copyright
136d3ceb1dSskrll * notice, this list of conditions and the following disclaimer.
146d3ceb1dSskrll * 2. Redistributions in binary form must reproduce the above copyright
156d3ceb1dSskrll * notice, this list of conditions and the following disclaimer in the
166d3ceb1dSskrll * documentation and/or other materials provided with the distribution.
176d3ceb1dSskrll *
186d3ceb1dSskrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
196d3ceb1dSskrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
206d3ceb1dSskrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
216d3ceb1dSskrll * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
226d3ceb1dSskrll * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
236d3ceb1dSskrll * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
246d3ceb1dSskrll * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
256d3ceb1dSskrll * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
266d3ceb1dSskrll * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
276d3ceb1dSskrll * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
286d3ceb1dSskrll * THE POSSIBILITY OF SUCH DAMAGE.
296d3ceb1dSskrll */
306d3ceb1dSskrll
316d3ceb1dSskrll /*
326d3ceb1dSskrll * References:
336d3ceb1dSskrll *
346d3ceb1dSskrll * 1. Cobra/Coral I/O Subsystem External Reference Specification
356d3ceb1dSskrll * Hewlett-Packard
366d3ceb1dSskrll *
376d3ceb1dSskrll */
386d3ceb1dSskrll
396d3ceb1dSskrll #include <sys/cdefs.h>
40*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: asp.c,v 1.4 2021/08/07 16:18:55 thorpej Exp $");
416d3ceb1dSskrll
426d3ceb1dSskrll #include <sys/param.h>
436d3ceb1dSskrll #include <sys/systm.h>
446d3ceb1dSskrll #include <sys/device.h>
456d3ceb1dSskrll #include <sys/reboot.h>
466d3ceb1dSskrll
476d3ceb1dSskrll #include <sys/bus.h>
486d3ceb1dSskrll #include <machine/iomod.h>
496d3ceb1dSskrll #include <machine/autoconf.h>
506d3ceb1dSskrll #include <machine/cpufunc.h>
516d3ceb1dSskrll
526d3ceb1dSskrll #include <hppa/hppa/machdep.h>
536d3ceb1dSskrll #include <hppa/dev/cpudevs.h>
546d3ceb1dSskrll #include <hppa/dev/viper.h>
556d3ceb1dSskrll
566d3ceb1dSskrll #include <hppa/gsc/gscbusvar.h>
576d3ceb1dSskrll
586d3ceb1dSskrll struct asp_hwr {
596d3ceb1dSskrll uint8_t asp_reset;
606d3ceb1dSskrll uint8_t asp_resv[31];
616d3ceb1dSskrll uint8_t asp_version;
626d3ceb1dSskrll uint8_t asp_resv1[15];
636d3ceb1dSskrll uint8_t asp_scsidsync;
646d3ceb1dSskrll uint8_t asp_resv2[15];
656d3ceb1dSskrll uint8_t asp_error;
666d3ceb1dSskrll };
676d3ceb1dSskrll
686d3ceb1dSskrll struct asp_trs {
696d3ceb1dSskrll uint32_t asp_irr;
706d3ceb1dSskrll uint32_t asp_imr;
716d3ceb1dSskrll uint32_t asp_ipr;
726d3ceb1dSskrll uint32_t asp_icr;
736d3ceb1dSskrll uint32_t asp_iar;
746d3ceb1dSskrll uint32_t asp_resv[3];
756d3ceb1dSskrll uint8_t asp_cled;
766d3ceb1dSskrll uint8_t asp_resv1[3];
776d3ceb1dSskrll struct {
786d3ceb1dSskrll u_int :20,
796d3ceb1dSskrll asp_spu : 3, /* SPU ID board jumper */
806d3ceb1dSskrll #define ASP_SPUCOBRA 0
816d3ceb1dSskrll #define ASP_SPUCORAL 1
826d3ceb1dSskrll #define ASP_SPUBUSH 2
836d3ceb1dSskrll #define ASP_SPUHARDBALL 3
846d3ceb1dSskrll #define ASP_SPUSCORPIO 4
856d3ceb1dSskrll #define ASP_SPUCORAL2 5
866d3ceb1dSskrll asp_sw : 1, /* front switch is normal */
876d3ceb1dSskrll asp_clk : 1, /* SCSI clock is doubled */
886d3ceb1dSskrll asp_lan : 2, /* LAN iface selector */
896d3ceb1dSskrll #define ASP_LANINVAL 0
906d3ceb1dSskrll #define ASP_LANAUI 1
916d3ceb1dSskrll #define ASP_LANTHIN 2
926d3ceb1dSskrll #define ASP_LANMISS 3
936d3ceb1dSskrll asp_lanf: 1, /* LAN AUI fuse is ok */
946d3ceb1dSskrll asp_spwr: 1, /* SCSI power ok */
956d3ceb1dSskrll asp_scsi: 3; /* SCSI ctrl ID */
966d3ceb1dSskrll } _asp_ios;
976d3ceb1dSskrll #define asp_spu _asp_ios.asp_spu
986d3ceb1dSskrll #define asp_sw _asp_ios.asp_sw
996d3ceb1dSskrll #define asp_clk _asp_ios.asp_clk
1006d3ceb1dSskrll #define asp_lan _asp_ios.asp_lan
1016d3ceb1dSskrll #define asp_lanf _asp_ios.asp_lanf
1026d3ceb1dSskrll #define asp_spwr _asp_ios.asp_spwr
1036d3ceb1dSskrll #define asp_scsi _asp_ios.asp_scsi
1046d3ceb1dSskrll };
1056d3ceb1dSskrll
1066d3ceb1dSskrll #define ASP_BANK_SZ 0x02000000
1076d3ceb1dSskrll #define ASP_REG_INT 0x00800000
1086d3ceb1dSskrll #define ASP_ETHER_ADDR 0x00810000
1096d3ceb1dSskrll #define ASP_REG_MISC 0x0082f000
1106d3ceb1dSskrll
1116d3ceb1dSskrll const struct asp_spus_tag {
1126d3ceb1dSskrll char name[12];
1136d3ceb1dSskrll int ledword;
1146d3ceb1dSskrll } asp_spus[] = {
1156d3ceb1dSskrll { "Cobra", 0 },
1166d3ceb1dSskrll { "Coral", 0 },
1176d3ceb1dSskrll { "Bushmaster", 0 },
1186d3ceb1dSskrll { "Hardball", 1 },
1196d3ceb1dSskrll { "Scorpio", 0 },
1206d3ceb1dSskrll { "Coral II", 1 },
1216d3ceb1dSskrll { "#6", 0 },
1226d3ceb1dSskrll { "#7", 0 }
1236d3ceb1dSskrll };
1246d3ceb1dSskrll
1256d3ceb1dSskrll struct asp_softc {
1266d3ceb1dSskrll device_t sc_dev;
1276d3ceb1dSskrll
1286d3ceb1dSskrll struct hppa_interrupt_register sc_ir;
1296d3ceb1dSskrll
1306d3ceb1dSskrll volatile struct asp_hwr *sc_hw;
1316d3ceb1dSskrll volatile struct asp_trs *sc_trs;
1326d3ceb1dSskrll };
1336d3ceb1dSskrll
1346d3ceb1dSskrll int aspmatch(device_t, cfdata_t, void *);
1356d3ceb1dSskrll void aspattach(device_t, device_t, void *);
1366d3ceb1dSskrll
1376d3ceb1dSskrll CFATTACH_DECL_NEW(asp, sizeof(struct asp_softc),
1386d3ceb1dSskrll aspmatch, aspattach, NULL, NULL);
1396d3ceb1dSskrll
1406d3ceb1dSskrll /*
1416d3ceb1dSskrll * Before a module is matched, this fixes up its gsc_attach_args.
1426d3ceb1dSskrll */
1436d3ceb1dSskrll static void asp_fix_args(void *, struct gsc_attach_args *);
1446d3ceb1dSskrll static void
asp_fix_args(void * _sc,struct gsc_attach_args * ga)1456d3ceb1dSskrll asp_fix_args(void *_sc, struct gsc_attach_args *ga)
1466d3ceb1dSskrll {
1476d3ceb1dSskrll hppa_hpa_t module_offset;
1486d3ceb1dSskrll struct asp_softc *sc = _sc;
1496d3ceb1dSskrll
1506d3ceb1dSskrll /*
1516d3ceb1dSskrll * Determine this module's interrupt bit.
1526d3ceb1dSskrll */
1536d3ceb1dSskrll module_offset = ga->ga_hpa - (hppa_hpa_t) sc->sc_trs;
1546d3ceb1dSskrll ga->ga_irq = HPPACF_IRQ_UNDEF;
1556d3ceb1dSskrll #define ASP_IRQ(off, irq) if (module_offset == off) ga->ga_irq = irq
1566d3ceb1dSskrll ASP_IRQ(0x22000, 6); /* com1 */
1576d3ceb1dSskrll ASP_IRQ(0x23000, 5); /* com0 */
1586d3ceb1dSskrll ASP_IRQ(0x24000, 7); /* lpt */
1596d3ceb1dSskrll ASP_IRQ(0x25000, 9); /* osiop */
1606d3ceb1dSskrll ASP_IRQ(0x26000, 8); /* ie */
1616d3ceb1dSskrll ASP_IRQ(0x30000, 3); /* siop */
1626d3ceb1dSskrll ASP_IRQ(0x800000, 13); /* harmony */
1636d3ceb1dSskrll #undef ASP_IRQ
1646d3ceb1dSskrll }
1656d3ceb1dSskrll
1666d3ceb1dSskrll int
aspmatch(device_t parent,cfdata_t cf,void * aux)1676d3ceb1dSskrll aspmatch(device_t parent, cfdata_t cf, void *aux)
1686d3ceb1dSskrll {
1696d3ceb1dSskrll struct confargs *ca = aux;
1706d3ceb1dSskrll
1716d3ceb1dSskrll if (ca->ca_type.iodc_type != HPPA_TYPE_BHA ||
1726d3ceb1dSskrll ca->ca_type.iodc_sv_model != HPPA_BHA_ASP)
1736d3ceb1dSskrll return 0;
1746d3ceb1dSskrll
1756d3ceb1dSskrll /*
1766d3ceb1dSskrll * Forcibly mask the HPA down to the start of the ASP
1776d3ceb1dSskrll * chip address space.
1786d3ceb1dSskrll */
1796d3ceb1dSskrll ca->ca_hpa &= ~(ASP_BANK_SZ - 1);
1806d3ceb1dSskrll
1816d3ceb1dSskrll return 1;
1826d3ceb1dSskrll }
1836d3ceb1dSskrll
1846d3ceb1dSskrll void
aspattach(device_t parent,device_t self,void * aux)1856d3ceb1dSskrll aspattach(device_t parent, device_t self, void *aux)
1866d3ceb1dSskrll {
1876d3ceb1dSskrll struct confargs *ca = aux;
1886d3ceb1dSskrll struct asp_softc *sc = device_private(self);
1896d3ceb1dSskrll struct gsc_attach_args ga;
1906d3ceb1dSskrll struct cpu_info *ci = &cpus[0];
1916d3ceb1dSskrll bus_space_handle_t ioh;
1926d3ceb1dSskrll int s;
1936d3ceb1dSskrll
1946d3ceb1dSskrll sc->sc_dev = self;
1956d3ceb1dSskrll
1966d3ceb1dSskrll ca->ca_irq = hppa_intr_allocate_bit(&ci->ci_ir, ca->ca_irq);
1976d3ceb1dSskrll if (ca->ca_irq == HPPACF_IRQ_UNDEF) {
1986d3ceb1dSskrll aprint_error_dev(self, ": can't allocate interrupt");
1996d3ceb1dSskrll return;
2006d3ceb1dSskrll }
2016d3ceb1dSskrll
2026d3ceb1dSskrll /*
2036d3ceb1dSskrll * Map the ASP interrupt registers.
2046d3ceb1dSskrll */
2056d3ceb1dSskrll if (bus_space_map(ca->ca_iot, ca->ca_hpa + ASP_REG_INT,
2066d3ceb1dSskrll sizeof(struct asp_trs), 0, &ioh)) {
2076d3ceb1dSskrll aprint_error(": can't map interrupt registers.\n");
2086d3ceb1dSskrll return;
2096d3ceb1dSskrll }
2106d3ceb1dSskrll sc->sc_trs = (struct asp_trs *)ioh;
2116d3ceb1dSskrll
2126d3ceb1dSskrll /*
2136d3ceb1dSskrll * Map the ASP miscellaneous registers.
2146d3ceb1dSskrll */
2156d3ceb1dSskrll if (bus_space_map(ca->ca_iot, ca->ca_hpa + ASP_REG_MISC,
2166d3ceb1dSskrll sizeof(struct asp_hwr), 0, &ioh)) {
2176d3ceb1dSskrll aprint_error(": can't map miscellaneous registers.\n");
2186d3ceb1dSskrll return;
2196d3ceb1dSskrll }
2206d3ceb1dSskrll sc->sc_hw = (struct asp_hwr *)ioh;
2216d3ceb1dSskrll
2226d3ceb1dSskrll /*
2236d3ceb1dSskrll * Map the Ethernet address and read it out.
2246d3ceb1dSskrll */
2256d3ceb1dSskrll if (bus_space_map(ca->ca_iot, ca->ca_hpa + ASP_ETHER_ADDR,
2266d3ceb1dSskrll sizeof(ga.ga_ether_address), 0, &ioh)) {
2276d3ceb1dSskrll aprint_error(": can't map EEPROM.\n");
2286d3ceb1dSskrll return;
2296d3ceb1dSskrll }
2306d3ceb1dSskrll bus_space_read_region_1(ca->ca_iot, ioh, 0,
2316d3ceb1dSskrll ga.ga_ether_address, sizeof(ga.ga_ether_address));
2326d3ceb1dSskrll bus_space_unmap(ca->ca_iot, ioh, sizeof(ga.ga_ether_address));
2336d3ceb1dSskrll
2346d3ceb1dSskrll #ifdef USELEDS
2356d3ceb1dSskrll machine_ledaddr = &sc->sc_trs->asp_cled;
2366d3ceb1dSskrll machine_ledword = asp_spus[sc->sc_trs->asp_spu].ledword;
2376d3ceb1dSskrll #endif
2386d3ceb1dSskrll
2396d3ceb1dSskrll /* reset ASP */
2406d3ceb1dSskrll /* sc->sc_hw->asp_reset = 1; */
2416d3ceb1dSskrll /* delay(400000); */
2426d3ceb1dSskrll
2436d3ceb1dSskrll s = splhigh();
2446d3ceb1dSskrll viper_setintrwnd(1 << ca->ca_irq);
2456d3ceb1dSskrll
2466d3ceb1dSskrll sc->sc_trs->asp_imr = 0;
247fc85ec4fSskrll (void)sc->sc_trs->asp_irr;
2486d3ceb1dSskrll
2496d3ceb1dSskrll /* Establish the interrupt register. */
2506d3ceb1dSskrll hppa_interrupt_register_establish(ci, &sc->sc_ir);
2516d3ceb1dSskrll sc->sc_ir.ir_name = device_xname(self);
2526d3ceb1dSskrll sc->sc_ir.ir_mask = &sc->sc_trs->asp_imr;
2536d3ceb1dSskrll sc->sc_ir.ir_req = &sc->sc_trs->asp_irr;
2546d3ceb1dSskrll
2556d3ceb1dSskrll splx(s);
2566d3ceb1dSskrll
2576d3ceb1dSskrll aprint_normal(": %s rev %d, lan %d scsi %d\n",
2586d3ceb1dSskrll asp_spus[sc->sc_trs->asp_spu].name, sc->sc_hw->asp_version,
2596d3ceb1dSskrll sc->sc_trs->asp_lan, sc->sc_trs->asp_scsi);
2606d3ceb1dSskrll
2616d3ceb1dSskrll /* Attach the GSC bus. */
2626d3ceb1dSskrll ga.ga_ca = *ca; /* clone from us */
2636d3ceb1dSskrll if (strcmp(device_xname(parent), "mainbus0") == 0) {
2646d3ceb1dSskrll ga.ga_dp.dp_bc[0] = ga.ga_dp.dp_bc[1];
2656d3ceb1dSskrll ga.ga_dp.dp_bc[1] = ga.ga_dp.dp_bc[2];
2666d3ceb1dSskrll ga.ga_dp.dp_bc[2] = ga.ga_dp.dp_bc[3];
2676d3ceb1dSskrll ga.ga_dp.dp_bc[3] = ga.ga_dp.dp_bc[4];
2686d3ceb1dSskrll ga.ga_dp.dp_bc[4] = ga.ga_dp.dp_bc[5];
2696d3ceb1dSskrll ga.ga_dp.dp_bc[5] = ga.ga_dp.dp_mod;
2706d3ceb1dSskrll ga.ga_dp.dp_mod = 0;
2716d3ceb1dSskrll }
2726d3ceb1dSskrll
2736d3ceb1dSskrll ga.ga_name = "gsc";
2746d3ceb1dSskrll ga.ga_ir = &sc->sc_ir;
2756d3ceb1dSskrll ga.ga_fix_args = asp_fix_args;
2766d3ceb1dSskrll ga.ga_fix_args_cookie = sc;
2776d3ceb1dSskrll ga.ga_scsi_target = sc->sc_trs->asp_scsi;
278*c7fb772bSthorpej config_found(self, &ga, gscprint, CFARGS_NONE);
2796d3ceb1dSskrll }
280