1 /* $NetBSD: asc.c,v 1.6 2002/05/22 22:43:18 bjh21 Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Richard Earnshaw 5 * All rights reserved. 6 * 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. The name of the company nor the name of the author may be used to 13 * endorse or promote products derived from this software without specific 14 * prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * POSSIBILITY OF SUCH DAMAGE. 27 * 28 * 29 * Copyright (c) 1996 Mark Brinicombe 30 * Copyright (c) 1982, 1990 The Regents of the University of California. 31 * All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. All advertising materials mentioning features or use of this software 42 * must display the following acknowledgement: 43 * This product includes software developed by the University of 44 * California, Berkeley and its contributors. 45 * 4. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * from:ahsc.c 62 */ 63 64 /* 65 * Driver for the Acorn SCSI card using the SBIC (WD33C93A) generic driver 66 * 67 * Thanks to Acorn for supplying programming information on this card. 68 */ 69 70 /* #define ASC_DMAMAP_DEBUG */ 71 /* #define DEBUG */ 72 73 #include "opt_ddb.h" 74 75 #include <sys/param.h> 76 77 __KERNEL_RCSID(0, "$NetBSD: asc.c,v 1.6 2002/05/22 22:43:18 bjh21 Exp $"); 78 79 #include <sys/systm.h> 80 #include <sys/kernel.h> 81 #include <sys/device.h> 82 #include <sys/buf.h> 83 84 #include <uvm/uvm_extern.h> 85 86 #include <machine/bus.h> 87 #include <machine/intr.h> 88 #include <machine/bootconfig.h> /* asc_poll */ 89 90 #include <dev/scsipi/scsi_all.h> 91 #include <dev/scsipi/scsipi_all.h> 92 #include <dev/scsipi/scsiconf.h> 93 94 #include <arm/arm32/katelib.h> 95 96 #include <dev/podulebus/podules.h> 97 #include <dev/podulebus/powerromreg.h> 98 99 #include <acorn32/podulebus/podulebus.h> 100 #include <acorn32/podulebus/sbicreg.h> 101 #include <acorn32/podulebus/sbicvar.h> 102 #include <acorn32/podulebus/ascreg.h> 103 #include <acorn32/podulebus/ascvar.h> 104 105 void ascattach (struct device *, struct device *, void *); 106 int ascmatch (struct device *, struct cfdata *, void *); 107 108 void asc_enintr (struct sbic_softc *); 109 110 int asc_dmaok (void *, bus_dma_tag_t, struct sbic_acb *); 111 int asc_dmasetup (void *, bus_dma_tag_t, struct sbic_acb *, int); 112 int asc_dmanext (void *, bus_dma_tag_t, struct sbic_acb *, int); 113 void asc_dmastop (void *, bus_dma_tag_t, struct sbic_acb *); 114 void asc_dmafinish (void *, bus_dma_tag_t, struct sbic_acb *); 115 116 void asc_scsi_request (struct scsipi_channel *, 117 scsipi_adapter_req_t, void *); 118 int asc_intr (void *); 119 void asc_minphys (struct buf *); 120 121 void asc_dump (void); 122 123 #ifdef DEBUG 124 int asc_dmadebug = 0; 125 #endif 126 127 struct cfattach asc_ca = { 128 sizeof(struct asc_softc), ascmatch, ascattach 129 }; 130 131 extern struct cfdriver asc_cd; 132 133 u_long scsi_nosync; 134 int shift_nosync; 135 136 #if ASC_POLL > 0 137 int asc_poll = 0; 138 139 #endif 140 141 int 142 ascmatch(struct device *pdp, struct cfdata *cf, void *auxp) 143 { 144 struct podule_attach_args *pa = (struct podule_attach_args *)auxp; 145 146 /* Look for the card */ 147 148 /* Standard ROM, skipping the MCS card that used the same ID. */ 149 if (pa->pa_product == PODULE_ACORN_SCSI && 150 strncmp(pa->pa_podule->description, "MCS", 3) != 0) 151 return 1; 152 153 /* PowerROM */ 154 if (pa->pa_product == PODULE_ALSYSTEMS_SCSI && 155 podulebus_initloader(pa) == 0 && 156 podloader_callloader(pa, 0, 0) == PRID_ACORN_SCSI1) 157 return 1; 158 159 return 0; 160 } 161 162 void 163 ascattach(struct device *pdp, struct device *dp, void *auxp) 164 { 165 /* volatile struct sdmac *rp;*/ 166 struct asc_softc *sc; 167 struct sbic_softc *sbic; 168 struct podule_attach_args *pa; 169 170 sc = (struct asc_softc *)dp; 171 pa = (struct podule_attach_args *)auxp; 172 173 if (pa->pa_podule_number == -1) 174 panic("Podule has disappeared !"); 175 176 sc->sc_podule_number = pa->pa_podule_number; 177 sc->sc_podule = pa->pa_podule; 178 podules[sc->sc_podule_number].attached = 1; 179 180 sbic = &sc->sc_softc; 181 182 sbic->sc_enintr = asc_enintr; 183 sbic->sc_dmaok = asc_dmaok; 184 sbic->sc_dmasetup = asc_dmasetup; 185 sbic->sc_dmanext = asc_dmanext; 186 sbic->sc_dmastop = asc_dmastop; 187 sbic->sc_dmafinish = asc_dmafinish; 188 189 /* Map sbic */ 190 sbic->sc_sbicp.sc_sbiciot = pa->pa_iot; 191 if (bus_space_map (sbic->sc_sbicp.sc_sbiciot, 192 sc->sc_podule->mod_base + ASC_SBIC, ASC_SBIC_SPACE, 0, 193 &sbic->sc_sbicp.sc_sbicioh)) 194 panic("%s: Cannot map SBIC\n", dp->dv_xname); 195 196 sbic->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 143; 197 198 sbic->sc_adapter.adapt_dev = &sbic->sc_dev; 199 sbic->sc_adapter.adapt_nchannels = 1; 200 sbic->sc_adapter.adapt_openings = 7; 201 sbic->sc_adapter.adapt_max_periph = 1; 202 sbic->sc_adapter.adapt_ioctl = NULL; 203 sbic->sc_adapter.adapt_minphys = asc_minphys; 204 sbic->sc_adapter.adapt_request = asc_scsi_request; 205 206 sbic->sc_channel.chan_adapter = &sbic->sc_adapter; 207 sbic->sc_channel.chan_bustype = &scsi_bustype; 208 sbic->sc_channel.chan_channel = 0; 209 sbic->sc_channel.chan_ntargets = 8; 210 sbic->sc_channel.chan_nluns = 8; 211 sbic->sc_channel.chan_id = 7; 212 213 /* Provide an override for the host id */ 214 (void)get_bootconf_option(boot_args, "asc.hostid", 215 BOOTOPT_TYPE_INT, &sbic->sc_channel.chan_id); 216 217 printf(": hostid=%d", sbic->sc_channel.chan_id); 218 219 #if ASC_POLL > 0 220 if (boot_args) 221 get_bootconf_option(boot_args, "ascpoll", BOOTOPT_TYPE_BOOLEAN, 222 &asc_poll); 223 224 if (asc_poll) 225 printf(" polling"); 226 #endif 227 printf("\n"); 228 229 sc->sc_pagereg = sc->sc_podule->fast_base + ASC_PAGEREG; 230 sc->sc_intstat = sc->sc_podule->fast_base + ASC_INTSTATUS; 231 232 /* Reset the card */ 233 234 WriteByte(sc->sc_pagereg, 0x80); 235 DELAY(500000); 236 WriteByte(sc->sc_pagereg, 0x00); 237 DELAY(250000); 238 239 sbicinit(sbic); 240 241 /* If we are polling only, we don't need a interrupt handler. */ 242 243 #ifdef ASC_POLL 244 if (!asc_poll) 245 #endif 246 { 247 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, 248 dp->dv_xname, "intr"); 249 sc->sc_ih = podulebus_irq_establish(pa->pa_ih, IPL_BIO, 250 asc_intr, sc, &sc->sc_intrcnt); 251 if (sc->sc_ih == NULL) 252 panic("%s: Cannot claim podule IRQ\n", dp->dv_xname); 253 } 254 255 /* 256 * attach all scsi units on us 257 */ 258 config_found(dp, &sbic->sc_channel, scsiprint); 259 } 260 261 262 void 263 asc_enintr(struct sbic_softc *sbicsc) 264 { 265 struct asc_softc *sc = (struct asc_softc *)sbicsc; 266 267 sbicsc->sc_flags |= SBICF_INTR; 268 WriteByte(sc->sc_pagereg, 0x40); 269 } 270 271 int 272 asc_dmaok (void *dma_h, bus_dma_tag_t dma_t, struct sbic_acb *acb) 273 { 274 return 0; 275 } 276 277 int 278 asc_dmasetup (void *dma_h, bus_dma_tag_t dma_t, struct sbic_acb *acb, int dir) 279 { 280 printf("asc_dmasetup()"); 281 #ifdef DDB 282 Debugger(); 283 #else 284 panic("Hit a brick wall\n"); 285 #endif 286 return 0; 287 } 288 289 int 290 asc_dmanext (void *dma_h, bus_dma_tag_t dma_t, struct sbic_acb *acb, int dir) 291 { 292 printf("asc_dmanext()"); 293 #ifdef DDB 294 Debugger(); 295 #else 296 panic("Hit a brick wall\n"); 297 #endif 298 return 0; 299 } 300 301 void 302 asc_dmastop (void *dma_h, bus_dma_tag_t dma_t, struct sbic_acb *acb) 303 { 304 printf("asc_dmastop\n"); 305 } 306 307 void 308 asc_dmafinish (void *dma_h, bus_dma_tag_t dma_t, struct sbic_acb *acb) 309 { 310 printf("asc_dmafinish\n"); 311 } 312 313 void 314 asc_dump(void) 315 { 316 int i; 317 318 for (i = 0; i < asc_cd.cd_ndevs; ++i) 319 if (asc_cd.cd_devs[i]) 320 sbic_dump(asc_cd.cd_devs[i]); 321 } 322 323 void 324 asc_scsi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 325 void *arg) 326 { 327 struct scsipi_xfer *xs; 328 329 switch (req) { 330 case ADAPTER_REQ_RUN_XFER: 331 xs = arg; 332 333 #if ASC_POLL > 0 334 /* ensure command is polling for the moment */ 335 336 if (asc_poll) 337 xs->xs_control |= XS_CTL_POLL; 338 #endif 339 340 /* printf("id=%d lun=%dcmdlen=%d datalen=%d opcode=%02x flags=%08x status=%02x blk=%02x %02x\n", 341 xs->xs_periph->periph_target, xs->xs_periph->periph_lun, xs->cmdlen, xs->datalen, xs->cmd->opcode, 342 xs->xs_control, xs->status, xs->cmd->bytes[0], xs->cmd->bytes[1]);*/ 343 344 default: 345 } 346 sbic_scsi_request(chan, req, arg); 347 } 348 349 350 int 351 asc_intr(void *arg) 352 { 353 struct asc_softc *sc = arg; 354 int intr; 355 356 /* printf("ascintr:");*/ 357 intr = ReadByte(sc->sc_intstat); 358 /* printf("%02x\n", intr);*/ 359 360 if (intr & IS_SBIC_IRQ) 361 sbicintr((struct sbic_softc *)sc); 362 363 return 0; /* Pass interrupt on down the chain */ 364 } 365 366 /* 367 * limit the transfer as required. 368 */ 369 void 370 asc_minphys(struct buf *bp) 371 { 372 #if 0 373 /* 374 * We must limit the DMA xfer size 375 */ 376 if (bp->b_bcount > MAX_DMA_LEN) { 377 printf("asc: Reducing dma length\n"); 378 bp->b_bcount = MAX_DMA_LEN; 379 } 380 #endif 381 minphys(bp); 382 } 383 384