1 /* $NetBSD: asc.c,v 1.12 2003/05/04 10:01:20 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Izumi Tsutsui. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/device.h> 33 #include <sys/buf.h> 34 35 #include <machine/autoconf.h> 36 #include <machine/bus.h> 37 38 #include <uvm/uvm_extern.h> 39 40 #include <dev/scsipi/scsipi_all.h> 41 #include <dev/scsipi/scsi_all.h> 42 #include <dev/scsipi/scsiconf.h> 43 44 #include <arc/jazz/jazziovar.h> 45 #include <arc/jazz/dma.h> 46 #include <arc/jazz/pica.h> 47 48 #include <dev/ic/ncr53c9xreg.h> 49 #include <dev/ic/ncr53c9xvar.h> 50 51 #define ASC_NPORTS 0x10 52 #define ASC_ID_53CF94 0xa2 /* XXX should be in MI ncr53c9xreg.h? */ 53 54 struct asc_softc { 55 struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ 56 57 bus_space_tag_t sc_iot; /* bus space tag */ 58 bus_space_handle_t sc_ioh; /* bus space handle */ 59 bus_space_handle_t sc_dmaioh; /* bus space handle for DMAC */ 60 61 bus_dma_tag_t sc_dmat; /* DMA tag */ 62 bus_dmamap_t sc_dmamap; /* DMA map for transfers */ 63 64 int sc_active; /* DMA state */ 65 int sc_datain; /* DMA Data Direction */ 66 size_t sc_dmasize; /* DMA size */ 67 char **sc_dmaaddr; /* DMA address */ 68 size_t *sc_dmalen; /* DMA length */ 69 }; 70 71 /* 72 * Autoconfiguration data for config. 73 */ 74 int asc_match(struct device *, struct cfdata *, void *); 75 void asc_attach(struct device *, struct device *, void *); 76 77 CFATTACH_DECL(asc, sizeof(struct asc_softc), 78 asc_match, asc_attach, NULL, NULL); 79 80 /* 81 * Functions and the switch for the MI code. 82 */ 83 u_char asc_read_reg(struct ncr53c9x_softc *, int); 84 void asc_write_reg(struct ncr53c9x_softc *, int, u_char); 85 int asc_dma_isintr(struct ncr53c9x_softc *); 86 void asc_dma_reset(struct ncr53c9x_softc *); 87 int asc_dma_intr(struct ncr53c9x_softc *); 88 int asc_dma_setup(struct ncr53c9x_softc *, caddr_t *, size_t *, int, size_t *); 89 void asc_dma_go(struct ncr53c9x_softc *); 90 void asc_dma_stop(struct ncr53c9x_softc *); 91 int asc_dma_isactive(struct ncr53c9x_softc *); 92 93 struct ncr53c9x_glue asc_glue = { 94 asc_read_reg, 95 asc_write_reg, 96 asc_dma_isintr, 97 asc_dma_reset, 98 asc_dma_intr, 99 asc_dma_setup, 100 asc_dma_go, 101 asc_dma_stop, 102 asc_dma_isactive, 103 NULL /* gl_clear_latched_intr */ 104 }; 105 106 /* 107 * Match driver based on name 108 */ 109 int 110 asc_match(parent, match, aux) 111 struct device *parent; 112 struct cfdata *match; 113 void *aux; 114 { 115 struct jazzio_attach_args *ja = aux; 116 117 if (strcmp(ja->ja_name, "ESP216") != 0) 118 return 0; 119 return 1; 120 } 121 122 void 123 asc_attach(parent, self, aux) 124 struct device *parent; 125 struct device *self; 126 void *aux; 127 { 128 struct jazzio_attach_args *ja = aux; 129 struct asc_softc *asc = (void *)self; 130 struct ncr53c9x_softc *sc = &asc->sc_ncr53c9x; 131 bus_space_tag_t iot; 132 133 #if 0 134 /* Need info from platform dependent config?? */ 135 if (asc_conf == NULL) 136 panic("asc_conf isn't initialized"); 137 #endif 138 139 sc->sc_glue = &asc_glue; 140 141 asc->sc_iot = iot = ja->ja_bust; 142 asc->sc_dmat = ja->ja_dmat; 143 144 if (bus_space_map(iot, ja->ja_addr, ASC_NPORTS, 0, &asc->sc_ioh)) { 145 printf(": unable to map I/O space\n"); 146 return; 147 } 148 149 if (bus_space_map(iot, R4030_SYS_DMA0_REGS, R4030_DMA_RANGE, 150 0, &asc->sc_dmaioh)) { 151 printf(": unable to map DMA I/O space\n"); 152 goto out1; 153 } 154 155 if (bus_dmamap_create(asc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0, 156 BUS_DMA_ALLOCNOW|BUS_DMA_NOWAIT, &asc->sc_dmamap)) { 157 printf(": unable to create DMA map\n"); 158 goto out2; 159 } 160 161 /* 162 * XXX More of this should be in ncr53c9x_attach(), but 163 * XXX should we really poke around the chip that much in 164 * XXX the MI code? Think about this more... 165 */ 166 167 /* 168 * Set up static configuration info. 169 */ 170 sc->sc_id = 7; /* XXX should be taken from ARC BIOS */ 171 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 172 173 /* identify 53CF9x-2 or not */ 174 asc_write_reg(sc, NCR_CMD, NCRCMD_RSTCHIP); 175 DELAY(25); 176 asc_write_reg(sc, NCR_CMD, NCRCMD_DMA | NCRCMD_NOP); 177 DELAY(25); 178 asc_write_reg(sc, NCR_CFG2, NCRCFG2_FE); 179 DELAY(25); 180 asc_write_reg(sc, NCR_CMD, NCRCMD_DMA | NCRCMD_NOP); 181 DELAY(25); 182 if (asc_read_reg(sc, NCR_TCH) == ASC_ID_53CF94) { 183 /* XXX should be have NCR_VARIANT_NCR53CF94? */ 184 sc->sc_rev = NCR_VARIANT_NCR53C94; 185 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_FE; 186 sc->sc_cfg3 = NCRF9XCFG3_IDM | NCRF9XCFG3_FCLK; 187 sc->sc_features = NCR_F_FASTSCSI; 188 sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI; 189 sc->sc_freq = 40; /* MHz */ 190 sc->sc_maxxfer = 16 * 1024 * 1024; 191 } else { 192 sc->sc_rev = NCR_VARIANT_NCR53C94; 193 sc->sc_freq = 25; /* MHz */ 194 sc->sc_maxxfer = 64 * 1024; 195 } 196 197 /* 198 * XXX minsync and maxxfer _should_ be set up in MI code, 199 * XXX but it appears to have some dependency on what sort 200 * XXX of DMA we're hooked up to, etc. 201 */ 202 203 /* 204 * This is the value used to start sync negotiations 205 * Note that the NCR register "SYNCTP" is programmed 206 * in "clocks per byte", and has a minimum value of 4. 207 * The SCSI period used in negotiation is one-fourth 208 * of the time (in nanoseconds) needed to transfer one byte. 209 * Since the chip's clock is given in MHz, we have the following 210 * formula: 4 * period = (1000 / freq) * 4 211 */ 212 sc->sc_minsync = 1000 / sc->sc_freq; 213 214 /* establish interrupt */ 215 jazzio_intr_establish(ja->ja_intr, ncr53c9x_intr, asc); 216 217 /* Do the common parts of attachment. */ 218 sc->sc_adapter.adapt_minphys = minphys; 219 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request; 220 ncr53c9x_attach(sc); 221 222 /* Turn on target selection using the `DMA' method */ 223 sc->sc_features |= NCR_F_DMASELECT; 224 return; 225 226 out2: 227 bus_space_unmap(iot, asc->sc_dmaioh, R4030_DMA_RANGE); 228 out1: 229 bus_space_unmap(iot, asc->sc_ioh, ASC_NPORTS); 230 } 231 232 /* 233 * Glue functions. 234 */ 235 236 u_char 237 asc_read_reg(sc, reg) 238 struct ncr53c9x_softc *sc; 239 int reg; 240 { 241 struct asc_softc *asc = (struct asc_softc *)sc; 242 243 return bus_space_read_1(asc->sc_iot, asc->sc_ioh, reg); 244 } 245 246 void 247 asc_write_reg(sc, reg, val) 248 struct ncr53c9x_softc *sc; 249 int reg; 250 u_char val; 251 { 252 struct asc_softc *asc = (struct asc_softc *)sc; 253 254 bus_space_write_1(asc->sc_iot, asc->sc_ioh, reg, val); 255 } 256 257 int 258 asc_dma_isintr(sc) 259 struct ncr53c9x_softc *sc; 260 { 261 262 return asc_read_reg(sc, NCR_STAT) & NCRSTAT_INT; 263 } 264 265 void 266 asc_dma_reset(sc) 267 struct ncr53c9x_softc *sc; 268 { 269 struct asc_softc *asc = (struct asc_softc *)sc; 270 271 /* halt DMA */ 272 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_ENAB, 0); 273 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_MODE, 0); 274 } 275 276 int 277 asc_dma_intr(sc) 278 struct ncr53c9x_softc *sc; 279 { 280 struct asc_softc *asc = (struct asc_softc *)sc; 281 int datain, resid, trans; 282 283 datain = asc->sc_datain; 284 285 #ifdef DIAGNOSTIC 286 /* This is an "assertion" :) */ 287 if (asc->sc_active == 0) 288 panic("asc_dma_intr: DMA wasn't active"); 289 #endif 290 291 /* DMA has stopped */ 292 293 asc->sc_active = 0; 294 295 if (asc->sc_dmasize == 0) { 296 /* A "Transfer Pad" operation complete */ 297 NCR_DMA(("dmaintr: discarded %d bytes (tcl=%d, tcm=%d)\n", 298 NCR_READ_REG(sc, NCR_TCL) | 299 (NCR_READ_REG(sc, NCR_TCM) << 8), 300 NCR_READ_REG(sc, NCR_TCL), 301 NCR_READ_REG(sc, NCR_TCM))); 302 303 return 0; 304 } 305 306 resid = 0; 307 308 /* 309 * If a transfer onto the SCSI bus gets interrupted by the device 310 * (e.g. for a SAVEPOINTER message), the data in the FIFO counts 311 * as residual since the ESP counter registers get decremented as 312 * bytes are clocked into the FIFO. 313 */ 314 if (!datain && 315 (resid = (asc_read_reg(sc, NCR_FFLAG) & NCRFIFO_FF)) != 0) { 316 NCR_DMA(("asc_dma_intr: empty asc FIFO of %d ", resid)); 317 } 318 319 if ((sc->sc_espstat & NCRSTAT_TC) == 0) { 320 /* 321 * `Terminal count' is off, so read the residue 322 * out of the ASC counter registers. 323 */ 324 resid += (NCR_READ_REG(sc, NCR_TCL) | 325 (NCR_READ_REG(sc, NCR_TCM) << 8) | 326 ((sc->sc_cfg2 & NCRCFG2_FE) 327 ? (NCR_READ_REG(sc, NCR_TCH) << 16) : 0)); 328 329 if (resid == 0 && asc->sc_dmasize == 65536 && 330 (sc->sc_cfg2 & NCRCFG2_FE) == 0) 331 /* A transfer of 64K is encoded as `TCL=TCM=0' */ 332 resid = 65536; 333 } 334 335 /* halt DMA */ 336 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_COUNT, 0); 337 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_ENAB, 0); 338 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_MODE, 0); 339 340 bus_dmamap_sync(asc->sc_dmat, asc->sc_dmamap, 341 0, asc->sc_dmamap->dm_mapsize, 342 datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 343 bus_dmamap_unload(asc->sc_dmat, asc->sc_dmamap); 344 345 trans = asc->sc_dmasize - resid; 346 347 if (trans < 0) { /* transfered < 0 ? */ 348 #if 0 349 /* 350 * This situation can happen in perfectly normal operation 351 * if the ESP is reselected while using DMA to select 352 * another target. As such, don't print the warning. 353 */ 354 printf("%s: xfer (%d) > req (%d)\n", 355 sc->sc_dev.dv_xname, trans, asc->sc_dmasize); 356 #endif 357 trans = asc->sc_dmasize; 358 } 359 NCR_DMA(("dmaintr: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n", 360 NCR_READ_REG(sc, NCR_TCL), 361 NCR_READ_REG(sc, NCR_TCM), 362 (sc->sc_cfg2 & NCRCFG2_FE) ? NCR_READ_REG(sc, NCR_TCH) : 0, 363 trans, resid)); 364 365 *asc->sc_dmalen -= trans; 366 *asc->sc_dmaaddr += trans; 367 368 return 0; 369 } 370 371 int 372 asc_dma_setup(sc, addr, len, datain, dmasize) 373 struct ncr53c9x_softc *sc; 374 caddr_t *addr; 375 size_t *len; 376 int datain; 377 size_t *dmasize; 378 { 379 struct asc_softc *asc = (struct asc_softc *)sc; 380 381 /* halt DMA */ 382 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_ENAB, 0); 383 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_MODE, 0); 384 385 asc->sc_dmaaddr = addr; 386 asc->sc_dmalen = len; 387 asc->sc_dmasize = *dmasize; 388 asc->sc_datain = datain; 389 390 /* 391 * No need to set up DMA in `Transfer Pad' operation. 392 */ 393 if (*dmasize == 0) 394 return 0; 395 396 bus_dmamap_load(asc->sc_dmat, asc->sc_dmamap, *addr, *len, NULL, 397 ((sc->sc_nexus->xs->xs_control & XS_CTL_NOSLEEP) ? 398 BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | BUS_DMA_STREAMING | 399 (datain ? BUS_DMA_READ : BUS_DMA_WRITE)); 400 bus_dmamap_sync(asc->sc_dmat, asc->sc_dmamap, 401 0, asc->sc_dmamap->dm_mapsize, 402 datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 403 404 return 0; 405 } 406 407 void 408 asc_dma_go(sc) 409 struct ncr53c9x_softc *sc; 410 { 411 struct asc_softc *asc = (struct asc_softc *)sc; 412 413 /* No DMA transfer in Transfer Pad operation */ 414 if (asc->sc_dmasize == 0) 415 return; 416 417 /* load transfer parameters */ 418 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, 419 R4030_DMA_ADDR, asc->sc_dmamap->dm_segs[0].ds_addr); 420 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, 421 R4030_DMA_COUNT, asc->sc_dmamap->dm_segs[0].ds_len); 422 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, 423 R4030_DMA_MODE, R4030_DMA_MODE_160NS | R4030_DMA_MODE_16); 424 425 /* start DMA */ 426 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, 427 R4030_DMA_ENAB, R4030_DMA_ENAB_RUN | 428 (asc->sc_datain ? R4030_DMA_ENAB_READ : R4030_DMA_ENAB_WRITE)); 429 430 asc->sc_active = 1; 431 } 432 433 void 434 asc_dma_stop(sc) 435 struct ncr53c9x_softc *sc; 436 { 437 struct asc_softc *asc = (struct asc_softc *)sc; 438 439 /* halt DMA */ 440 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_ENAB, 0); 441 bus_space_write_4(asc->sc_iot, asc->sc_dmaioh, R4030_DMA_MODE, 0); 442 443 asc->sc_active = 0; 444 } 445 446 int 447 asc_dma_isactive(sc) 448 struct ncr53c9x_softc *sc; 449 { 450 struct asc_softc *asc = (struct asc_softc *)sc; 451 452 return asc->sc_active; 453 } 454