1 /* $NetBSD: siop_gsc.c,v 1.1 2014/02/24 07:23:43 skrll Exp $ */ 2 3 /* $OpenBSD: siop_gsc.c,v 1.4 2007/08/23 21:01:22 kettenis Exp $ */ 4 5 /* 6 * Copyright (c) 2007 Mark Kettenis 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/cdefs.h> 22 __KERNEL_RCSID(0, "$NetBSD: siop_gsc.c,v 1.1 2014/02/24 07:23:43 skrll Exp $"); 23 24 #include <sys/param.h> 25 #include <sys/device.h> 26 #include <sys/systm.h> 27 28 #include <uvm/uvm_extern.h> 29 30 #include <machine/autoconf.h> 31 #include <sys/bus.h> 32 #include <machine/iomod.h> 33 34 #include <dev/scsipi/scsi_all.h> 35 #include <dev/scsipi/scsipi_all.h> 36 #include <dev/scsipi/scsiconf.h> 37 38 #include <dev/ic/siopreg.h> 39 #include <dev/ic/siopvar_common.h> 40 #include <dev/ic/siopvar.h> 41 42 #include <hppa/dev/cpudevs.h> 43 #include <hppa/gsc/gscbusvar.h> 44 45 #define SIOP_GSC_RESET 0x0000 46 #define SIOP_GSC_OFFSET 0x0100 47 48 int siop_gsc_match(device_t, cfdata_t, void *); 49 void siop_gsc_attach(device_t, device_t, void *); 50 int siop_gsc_intr(void *); 51 void siop_gsc_reset(struct siop_common_softc *); 52 53 uint8_t siop_gsc_r1(void *, bus_space_handle_t, bus_size_t); 54 uint16_t siop_gsc_r2(void *, bus_space_handle_t, bus_size_t); 55 void siop_gsc_w1(void *, bus_space_handle_t, bus_size_t, uint8_t); 56 void siop_gsc_w2(void *, bus_space_handle_t, bus_size_t, uint16_t); 57 58 struct siop_gsc_softc { 59 struct siop_softc sc_siop; 60 bus_space_tag_t sc_iot; 61 bus_space_handle_t sc_ioh; 62 struct hppa_bus_space_tag sc_bustag; 63 }; 64 65 CFATTACH_DECL_NEW(siop_gsc, sizeof(struct siop_gsc_softc), 66 siop_gsc_match, siop_gsc_attach, NULL, NULL); 67 68 int 69 siop_gsc_match(device_t parent, cfdata_t match, void *aux) 70 { 71 struct gsc_attach_args *ga = aux; 72 73 if (ga->ga_type.iodc_type != HPPA_TYPE_FIO || 74 ga->ga_type.iodc_sv_model != HPPA_FIO_FWSCSI) 75 return 0; 76 77 return 1; 78 } 79 80 void 81 siop_gsc_attach(device_t parent, device_t self, void *aux) 82 { 83 struct siop_gsc_softc *gsc = device_private(self); 84 struct siop_softc *sc = &gsc->sc_siop; 85 struct gsc_attach_args *ga = aux; 86 87 sc->sc_c.sc_dev = self; 88 gsc->sc_iot = ga->ga_iot; 89 if (bus_space_map(gsc->sc_iot, ga->ga_hpa, 90 IOMOD_HPASIZE, 0, &gsc->sc_ioh)) { 91 aprint_error(": can't map io space\n"); 92 return; 93 } 94 95 gsc->sc_bustag = *gsc->sc_iot; 96 gsc->sc_bustag.hbt_r1 = siop_gsc_r1; 97 gsc->sc_bustag.hbt_r2 = siop_gsc_r2; 98 gsc->sc_bustag.hbt_w1 = siop_gsc_w1; 99 gsc->sc_bustag.hbt_w2 = siop_gsc_w2; 100 101 sc->sc_c.features = SF_CHIP_PF | SF_CHIP_BE | SF_BUS_WIDE; 102 sc->sc_c.maxburst = 4; 103 sc->sc_c.maxoff = 8; 104 sc->sc_c.clock_div = 3; 105 sc->sc_c.clock_period = 250; 106 sc->sc_c.ram_size = 0; 107 108 sc->sc_c.sc_reset = siop_gsc_reset; 109 sc->sc_c.sc_dmat = ga->ga_dmatag; 110 111 sc->sc_c.sc_rt = &gsc->sc_bustag; 112 bus_space_subregion(gsc->sc_iot, gsc->sc_ioh, SIOP_GSC_OFFSET, 113 IOMOD_HPASIZE - SIOP_GSC_OFFSET, &sc->sc_c.sc_rh); 114 115 /* 116 * Reset the SCSI subsystem. 117 */ 118 bus_space_write_1(gsc->sc_iot, gsc->sc_ioh, SIOP_GSC_RESET, 0); 119 DELAY(1000); 120 siop_gsc_reset(&sc->sc_c); 121 122 aprint_normal(": NCR53C720 rev %d\n", bus_space_read_1(sc->sc_c.sc_rt, 123 sc->sc_c.sc_rh, SIOP_CTEST3) >> 4); 124 125 siop_attach(sc); 126 127 (void)hppa_intr_establish(IPL_BIO, siop_intr, sc, ga->ga_ir, 128 ga->ga_irq); 129 130 } 131 132 void 133 siop_gsc_reset(struct siop_common_softc *sc) 134 { 135 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, DCNTL_EA); 136 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST0, CTEST0_EHP); 137 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4, CTEST4_MUX); 138 139 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STIME0, 140 (0xc << STIME0_SEL_SHIFT)); 141 } 142 143 uint8_t 144 siop_gsc_r1(void *v, bus_space_handle_t h, bus_size_t o) 145 { 146 return *(volatile uint8_t *)(h + (o ^ 3)); 147 } 148 149 uint16_t 150 siop_gsc_r2(void *v, bus_space_handle_t h, bus_size_t o) 151 { 152 if (o == SIOP_SIST0) { 153 uint16_t reg; 154 155 reg = siop_gsc_r1(v, h, SIOP_SIST0); 156 reg |= siop_gsc_r1(v, h, SIOP_SIST1) << 8; 157 return reg; 158 } 159 return *(volatile uint16_t *)(h + (o ^ 2)); 160 } 161 162 void 163 siop_gsc_w1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t vv) 164 { 165 *(volatile uint8_t *)(h + (o ^ 3)) = vv; 166 } 167 168 void 169 siop_gsc_w2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv) 170 { 171 *(volatile uint16_t *)(h + (o ^ 2)) = vv; 172 } 173