1 1.21 thorpej /* $NetBSD: csc.c,v 1.21 2021/08/07 16:18:40 thorpej Exp $ */ 2 1.1 reinoud 3 1.1 reinoud /*- 4 1.1 reinoud * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 1.1 reinoud * All rights reserved. 6 1.1 reinoud * 7 1.1 reinoud * This code is derived from software contributed to The NetBSD Foundation 8 1.1 reinoud * by Scott Stevens. 9 1.1 reinoud * 10 1.1 reinoud * Redistribution and use in source and binary forms, with or without 11 1.1 reinoud * modification, are permitted provided that the following conditions 12 1.1 reinoud * are met: 13 1.1 reinoud * 1. Redistributions of source code must retain the above copyright 14 1.1 reinoud * notice, this list of conditions and the following disclaimer. 15 1.1 reinoud * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 reinoud * notice, this list of conditions and the following disclaimer in the 17 1.1 reinoud * documentation and/or other materials provided with the distribution. 18 1.1 reinoud * 19 1.1 reinoud * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 reinoud * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 reinoud * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 reinoud * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 reinoud * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 reinoud * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 reinoud * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 reinoud * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 reinoud * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 reinoud * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 reinoud * POSSIBILITY OF SUCH DAMAGE. 30 1.1 reinoud */ 31 1.1 reinoud 32 1.1 reinoud /* 33 1.1 reinoud * Cumana SCSI-2 driver uses the SFAS216 generic driver 34 1.1 reinoud */ 35 1.12 lukem 36 1.12 lukem #include <sys/cdefs.h> 37 1.21 thorpej __KERNEL_RCSID(0, "$NetBSD: csc.c,v 1.21 2021/08/07 16:18:40 thorpej Exp $"); 38 1.1 reinoud 39 1.1 reinoud #include <sys/param.h> 40 1.1 reinoud #include <sys/systm.h> 41 1.1 reinoud #include <sys/kernel.h> 42 1.1 reinoud #include <sys/device.h> 43 1.10 thorpej 44 1.10 thorpej #include <uvm/uvm_extern.h> 45 1.10 thorpej 46 1.1 reinoud #include <dev/scsipi/scsi_all.h> 47 1.1 reinoud #include <dev/scsipi/scsipi_all.h> 48 1.1 reinoud #include <dev/scsipi/scsiconf.h> 49 1.1 reinoud #include <machine/io.h> 50 1.2 thorpej #include <machine/intr.h> 51 1.1 reinoud #include <machine/bootconfig.h> 52 1.1 reinoud #include <acorn32/podulebus/podulebus.h> 53 1.1 reinoud #include <acorn32/podulebus/sfasreg.h> 54 1.1 reinoud #include <acorn32/podulebus/sfasvar.h> 55 1.1 reinoud #include <acorn32/podulebus/cscreg.h> 56 1.1 reinoud #include <acorn32/podulebus/cscvar.h> 57 1.1 reinoud #include <dev/podulebus/podules.h> 58 1.1 reinoud #include <dev/podulebus/powerromreg.h> 59 1.1 reinoud 60 1.17 matt int cscmatch(device_t, cfdata_t, void *); 61 1.17 matt void cscattach(device_t, device_t, void *); 62 1.1 reinoud 63 1.18 chs CFATTACH_DECL_NEW(csc, sizeof(struct csc_softc), 64 1.8 thorpej cscmatch, cscattach, NULL, NULL); 65 1.1 reinoud 66 1.9 chs int csc_intr(void *); 67 1.9 chs int csc_setup_dma(void *, void *, int, int); 68 1.9 chs int csc_build_dma_chain(void *, void *, void *, int); 69 1.9 chs int csc_need_bump(void *, void *, int); 70 1.9 chs void csc_led(void *, int); 71 1.9 chs 72 1.9 chs void csc_set_dma_adr(struct sfas_softc *, void *); 73 1.9 chs void csc_set_dma_tc(struct sfas_softc *, unsigned int); 74 1.9 chs void csc_set_dma_mode(struct sfas_softc *, int); 75 1.1 reinoud 76 1.1 reinoud /* 77 1.1 reinoud * if we are a Cumana SCSI-2 card 78 1.1 reinoud */ 79 1.1 reinoud int 80 1.18 chs cscmatch(device_t parent, cfdata_t cf, void *aux) 81 1.1 reinoud { 82 1.18 chs struct podule_attach_args *pa = aux; 83 1.1 reinoud 84 1.1 reinoud /* Look for the card */ 85 1.3 bjh21 if (pa->pa_product == PODULE_CUMANA_SCSI2) 86 1.1 reinoud return 1; 87 1.1 reinoud 88 1.1 reinoud /* PowerROM */ 89 1.1 reinoud if (pa->pa_product == PODULE_ALSYSTEMS_SCSI && 90 1.1 reinoud podulebus_initloader(pa) == 0 && 91 1.1 reinoud podloader_callloader(pa, 0, 0) == PRID_CUMANA_SCSI2) 92 1.1 reinoud return 1; 93 1.1 reinoud 94 1.1 reinoud return 0; 95 1.1 reinoud } 96 1.1 reinoud 97 1.1 reinoud void 98 1.18 chs cscattach(device_t parent, device_t self, void *aux) 99 1.1 reinoud { 100 1.18 chs struct csc_softc *sc = device_private(self); 101 1.1 reinoud struct podule_attach_args *pa; 102 1.1 reinoud csc_regmap_p rp = &sc->sc_regmap; 103 1.1 reinoud vu_char *fas; 104 1.1 reinoud int loop; 105 1.1 reinoud 106 1.18 chs pa = aux; 107 1.1 reinoud 108 1.1 reinoud if (pa->pa_podule_number == -1) 109 1.1 reinoud panic("Podule has disappeared !"); 110 1.1 reinoud 111 1.1 reinoud sc->sc_specific.sc_podule_number = pa->pa_podule_number; 112 1.1 reinoud sc->sc_specific.sc_podule = pa->pa_podule; 113 1.1 reinoud sc->sc_specific.sc_iobase = 114 1.1 reinoud (vu_char *)sc->sc_specific.sc_podule->mod_base; 115 1.1 reinoud 116 1.1 reinoud rp->status0 = &sc->sc_specific.sc_iobase[CSC_STATUS0]; 117 1.1 reinoud rp->alatch = &sc->sc_specific.sc_iobase[CSC_ALATCH]; 118 1.1 reinoud rp->dack = (vu_short *)&sc->sc_specific.sc_iobase[CSC_DACK]; 119 1.1 reinoud fas = &sc->sc_specific.sc_iobase[CSC_FAS_OFFSET_BASE]; 120 1.1 reinoud 121 1.1 reinoud rp->FAS216.sfas_tc_low = &fas[CSC_FAS_OFFSET_TCL]; 122 1.1 reinoud rp->FAS216.sfas_tc_mid = &fas[CSC_FAS_OFFSET_TCM]; 123 1.1 reinoud rp->FAS216.sfas_fifo = &fas[CSC_FAS_OFFSET_FIFO]; 124 1.1 reinoud rp->FAS216.sfas_command = &fas[CSC_FAS_OFFSET_COMMAND]; 125 1.1 reinoud rp->FAS216.sfas_dest_id = &fas[CSC_FAS_OFFSET_DESTID]; 126 1.1 reinoud rp->FAS216.sfas_timeout = &fas[CSC_FAS_OFFSET_TIMEOUT]; 127 1.1 reinoud rp->FAS216.sfas_syncper = &fas[CSC_FAS_OFFSET_PERIOD]; 128 1.1 reinoud rp->FAS216.sfas_syncoff = &fas[CSC_FAS_OFFSET_OFFSET]; 129 1.1 reinoud rp->FAS216.sfas_config1 = &fas[CSC_FAS_OFFSET_CONFIG1]; 130 1.1 reinoud rp->FAS216.sfas_clkconv = &fas[CSC_FAS_OFFSET_CLKCONV]; 131 1.1 reinoud rp->FAS216.sfas_test = &fas[CSC_FAS_OFFSET_TEST]; 132 1.1 reinoud rp->FAS216.sfas_config2 = &fas[CSC_FAS_OFFSET_CONFIG2]; 133 1.1 reinoud rp->FAS216.sfas_config3 = &fas[CSC_FAS_OFFSET_CONFIG3]; 134 1.1 reinoud rp->FAS216.sfas_tc_high = &fas[CSC_FAS_OFFSET_TCH]; 135 1.1 reinoud rp->FAS216.sfas_fifo_bot = &fas[CSC_FAS_OFFSET_FIFOBOT]; 136 1.1 reinoud 137 1.18 chs sc->sc_softc.sc_dev = self; 138 1.1 reinoud sc->sc_softc.sc_fas = (sfas_regmap_p)rp; 139 1.1 reinoud sc->sc_softc.sc_spec = &sc->sc_specific; 140 1.1 reinoud 141 1.1 reinoud sc->sc_softc.sc_led = csc_led; 142 1.1 reinoud 143 1.1 reinoud sc->sc_softc.sc_setup_dma = csc_setup_dma; 144 1.1 reinoud sc->sc_softc.sc_build_dma_chain = csc_build_dma_chain; 145 1.1 reinoud sc->sc_softc.sc_need_bump = csc_need_bump; 146 1.1 reinoud 147 1.1 reinoud sc->sc_softc.sc_clock_freq = 8; /* Cumana runs at 8MHz */ 148 1.1 reinoud sc->sc_softc.sc_timeout = 250; /* Set default timeout to 250ms */ 149 1.1 reinoud sc->sc_softc.sc_config_flags = SFAS_NO_DMA /*| SFAS_NF_DEBUG*/; 150 1.1 reinoud sc->sc_softc.sc_host_id = 7; /* Should check the jumpers */ 151 1.1 reinoud 152 1.10 thorpej sc->sc_softc.sc_bump_sz = PAGE_SIZE; 153 1.1 reinoud sc->sc_softc.sc_bump_pa = 0x0; 154 1.1 reinoud 155 1.1 reinoud sfasinitialize((struct sfas_softc *)sc); 156 1.1 reinoud 157 1.18 chs sc->sc_softc.sc_adapter.adapt_dev = self; 158 1.1 reinoud sc->sc_softc.sc_adapter.adapt_nchannels = 1; 159 1.1 reinoud sc->sc_softc.sc_adapter.adapt_openings = 7; 160 1.1 reinoud sc->sc_softc.sc_adapter.adapt_max_periph = 1; 161 1.1 reinoud sc->sc_softc.sc_adapter.adapt_ioctl = NULL; 162 1.1 reinoud sc->sc_softc.sc_adapter.adapt_minphys = sfas_minphys; 163 1.4 bjh21 sc->sc_softc.sc_adapter.adapt_request = sfas_scsi_request; 164 1.1 reinoud 165 1.1 reinoud sc->sc_softc.sc_channel.chan_adapter = &sc->sc_softc.sc_adapter; 166 1.1 reinoud sc->sc_softc.sc_channel.chan_bustype = &scsi_bustype; 167 1.1 reinoud sc->sc_softc.sc_channel.chan_channel = 0; 168 1.1 reinoud sc->sc_softc.sc_channel.chan_ntargets = 8; 169 1.1 reinoud sc->sc_softc.sc_channel.chan_nluns = 8; 170 1.1 reinoud sc->sc_softc.sc_channel.chan_id = sc->sc_softc.sc_host_id; 171 1.1 reinoud 172 1.1 reinoud /* Provide an override for the host id */ 173 1.1 reinoud (void)get_bootconf_option(boot_args, "csc.hostid", 174 1.1 reinoud BOOTOPT_TYPE_INT, &sc->sc_softc.sc_channel.chan_id); 175 1.1 reinoud 176 1.1 reinoud printf(": host=%d", sc->sc_softc.sc_channel.chan_id); 177 1.1 reinoud 178 1.1 reinoud /* initialise the alatch */ 179 1.1 reinoud sc->sc_specific.sc_alatch_defs = (CSC_POLL?0:CSC_ALATCH_DEFS_INTEN); 180 1.1 reinoud for (loop = 0; loop < 8; loop ++) { 181 1.1 reinoud if(loop != 3) 182 1.1 reinoud *rp->alatch = (loop << 1) | 183 1.1 reinoud ((sc->sc_specific.sc_alatch_defs & (1 << loop))?1:0); 184 1.1 reinoud } 185 1.1 reinoud 186 1.1 reinoud #if CSC_POLL == 0 187 1.1 reinoud evcnt_attach_dynamic(&sc->sc_softc.sc_intrcnt, EVCNT_TYPE_INTR, NULL, 188 1.18 chs device_xname(self), "intr"); 189 1.1 reinoud sc->sc_softc.sc_ih = podulebus_irq_establish(pa->pa_ih, IPL_BIO, 190 1.1 reinoud csc_intr, &sc->sc_softc, &sc->sc_softc.sc_intrcnt); 191 1.1 reinoud if (sc->sc_softc.sc_ih == NULL) 192 1.18 chs panic("%s: Cannot install IRQ handler", device_xname(self)); 193 1.1 reinoud #else 194 1.1 reinoud printf(" polling"); 195 1.4 bjh21 sc->sc_softc.sc_adapter.adapt_flags |= SCSIPI_ADAPT_POLL_ONLY; 196 1.1 reinoud #endif 197 1.1 reinoud printf("\n"); 198 1.1 reinoud 199 1.1 reinoud /* attach all scsi units on us */ 200 1.21 thorpej config_found(self, &sc->sc_softc.sc_channel, scsiprint, CFARGS_NONE); 201 1.1 reinoud } 202 1.1 reinoud 203 1.1 reinoud 204 1.1 reinoud int 205 1.15 dsl csc_intr(void *arg) 206 1.1 reinoud { 207 1.1 reinoud struct sfas_softc *dev = arg; 208 1.1 reinoud csc_regmap_p rp; 209 1.1 reinoud int quickints; 210 1.1 reinoud 211 1.1 reinoud rp = (csc_regmap_p)dev->sc_fas; 212 1.1 reinoud 213 1.1 reinoud if (*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) { 214 1.1 reinoud quickints = 16; 215 1.1 reinoud do { 216 1.1 reinoud dev->sc_status = *rp->FAS216.sfas_status; 217 1.1 reinoud dev->sc_interrupt = *rp->FAS216.sfas_interrupt; 218 1.1 reinoud 219 1.1 reinoud if (dev->sc_interrupt & SFAS_INT_RESELECTED) { 220 1.1 reinoud dev->sc_resel[0] = *rp->FAS216.sfas_fifo; 221 1.1 reinoud dev->sc_resel[1] = *rp->FAS216.sfas_fifo; 222 1.1 reinoud } 223 1.1 reinoud sfasintr(dev); 224 1.1 reinoud 225 1.1 reinoud } while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) 226 1.1 reinoud && --quickints); 227 1.1 reinoud } 228 1.1 reinoud 229 1.1 reinoud return(0); /* Pass interrupt on down the chain */ 230 1.1 reinoud } 231 1.1 reinoud 232 1.11 wiz /* Load transfer address into DMA register */ 233 1.1 reinoud void 234 1.15 dsl csc_set_dma_adr(struct sfas_softc *sc, void *ptr) 235 1.1 reinoud { 236 1.1 reinoud return; 237 1.1 reinoud } 238 1.1 reinoud 239 1.1 reinoud /* Set DMA transfer counter */ 240 1.1 reinoud void 241 1.15 dsl csc_set_dma_tc(struct sfas_softc *sc, unsigned int len) 242 1.1 reinoud { 243 1.1 reinoud *sc->sc_fas->sfas_tc_low = len; len >>= 8; 244 1.1 reinoud *sc->sc_fas->sfas_tc_mid = len; len >>= 8; 245 1.1 reinoud *sc->sc_fas->sfas_tc_high = len; 246 1.1 reinoud } 247 1.1 reinoud 248 1.1 reinoud /* Set DMA mode */ 249 1.1 reinoud void 250 1.15 dsl csc_set_dma_mode(struct sfas_softc *sc, int mode) 251 1.1 reinoud { 252 1.1 reinoud } 253 1.1 reinoud 254 1.1 reinoud /* Initialize DMA for transfer */ 255 1.1 reinoud int 256 1.15 dsl csc_setup_dma(void *sc, void *ptr, int len, int mode) 257 1.1 reinoud { 258 1.9 chs 259 1.9 chs return (0); 260 1.1 reinoud } 261 1.1 reinoud 262 1.1 reinoud /* Check if address and len is ok for DMA transfer */ 263 1.1 reinoud int 264 1.15 dsl csc_need_bump(void *sc, void *ptr, int len) 265 1.1 reinoud { 266 1.1 reinoud int p; 267 1.1 reinoud 268 1.1 reinoud p = (int)ptr & 0x03; 269 1.1 reinoud 270 1.1 reinoud if (p) { 271 1.1 reinoud p = 4-p; 272 1.1 reinoud 273 1.1 reinoud if (len < 256) 274 1.1 reinoud p = len; 275 1.1 reinoud } 276 1.1 reinoud 277 1.1 reinoud return(p); 278 1.1 reinoud } 279 1.1 reinoud 280 1.1 reinoud /* Interrupt driven routines */ 281 1.1 reinoud int 282 1.15 dsl csc_build_dma_chain(void *sc, void *chain, void *p, int l) 283 1.1 reinoud { 284 1.1 reinoud return(0); 285 1.1 reinoud } 286 1.1 reinoud 287 1.1 reinoud /* Turn on/off led */ 288 1.1 reinoud void 289 1.15 dsl csc_led(void *v, int mode) 290 1.1 reinoud { 291 1.9 chs struct sfas_softc *sc = v; 292 1.1 reinoud 293 1.1 reinoud if (mode) { 294 1.1 reinoud sc->sc_led_status++; 295 1.1 reinoud } else { 296 1.1 reinoud if (sc->sc_led_status) 297 1.1 reinoud sc->sc_led_status--; 298 1.1 reinoud } 299 1.1 reinoud } 300