1 /* $NetBSD: oiocsc.c,v 1.2 2011/07/01 18:53:47 dyoung Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Stephen M. Rumble 5 * Copyright (c) 2001 Wayne Knowles 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Wayne Knowles 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: oiocsc.c,v 1.2 2011/07/01 18:53:47 dyoung Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/device.h> 47 #include <sys/buf.h> 48 49 #include <dev/scsipi/scsi_all.h> 50 #include <dev/scsipi/scsipi_all.h> 51 #include <dev/scsipi/scsiconf.h> 52 53 #include <machine/cpu.h> 54 #include <sys/bus.h> 55 #include <machine/autoconf.h> 56 #include <machine/machtype.h> 57 #include <machine/sysconf.h> 58 59 #include <sgimips/ioc/oiocreg.h> 60 #include <sgimips/ioc/oiocvar.h> 61 62 #include <dev/ic/wd33c93reg.h> 63 #include <dev/ic/wd33c93var.h> 64 65 #include <opt_kgdb.h> 66 #include <sys/kgdb.h> 67 68 struct oiocsc_softc { 69 struct wd33c93_softc sc_wd33c93; /* Must be first */ 70 struct evcnt sc_intrcnt; /* Interrupt counter */ 71 bus_space_handle_t sc_sh; 72 bus_space_tag_t sc_st; 73 bus_dma_tag_t sc_dmat; 74 bus_dmamap_t sc_dmamap; 75 int sc_flags; 76 #define WDSC_DMA_ACTIVE 0x1 77 #define WDSC_DMA_MAPLOADED 0x2 78 struct oioc_dma_softc { 79 bus_space_tag_t sc_bst; 80 bus_space_handle_t sc_bsh; 81 bus_dma_tag_t sc_dmat; 82 83 uint32_t sc_flags; 84 uint32_t sc_dmalow; 85 int sc_ndesc; 86 bus_dmamap_t sc_dmamap; 87 ssize_t sc_dlen; /* # bytes transfered */ 88 } sc_oiocdma; 89 }; 90 91 92 void oiocsc_attach (device_t, device_t, void *); 93 int oiocsc_match (device_t, struct cfdata *, void *); 94 95 CFATTACH_DECL_NEW(oiocsc, sizeof(struct oiocsc_softc), 96 oiocsc_match, oiocsc_attach, NULL, NULL); 97 98 int oiocsc_dmasetup (struct wd33c93_softc *, void **, size_t *, 99 int, size_t *); 100 int oiocsc_dmago (struct wd33c93_softc *); 101 void oiocsc_dmastop (struct wd33c93_softc *); 102 void oiocsc_reset (struct wd33c93_softc *); 103 int oiocsc_dmaintr (void *); 104 int oiocsc_scsiintr (void *); 105 106 /* 107 * Always present on IP4, IP6, IP10. 108 */ 109 int 110 oiocsc_match(device_t parent, struct cfdata *cf, void *aux) 111 { 112 struct oioc_attach_args *oa = aux; 113 114 if (strcmp(oa->oa_name, cf->cf_name) == 0) 115 return (1); 116 117 return (0); 118 } 119 120 /* 121 * Attach the wdsc driver 122 */ 123 void 124 oiocsc_attach(device_t parent, device_t self, void *aux) 125 { 126 struct oiocsc_softc *osc = device_private(self); 127 struct wd33c93_softc *sc = &osc->sc_wd33c93; 128 struct oioc_attach_args *oa = aux; 129 int err; 130 131 sc->sc_dev = self; 132 sc->sc_regt = oa->oa_st; 133 osc->sc_st = oa->oa_st; 134 osc->sc_sh = oa->oa_sh; 135 osc->sc_dmat = oa->oa_dmat; 136 137 if ((err = bus_space_subregion(oa->oa_st, oa->oa_sh, OIOC_WD33C93_ASR, 138 OIOC_WD33C93_ASR_SIZE, &sc->sc_asr_regh)) != 0) { 139 printf(": unable to map regs, err=%d\n", err); 140 return; 141 } 142 143 if ((err = bus_space_subregion(oa->oa_st, oa->oa_sh, OIOC_WD33C93_DATA, 144 OIOC_WD33C93_DATA_SIZE, &sc->sc_data_regh)) != 0) { 145 printf(": unable to map regs, err=%d\n", err); 146 return; 147 } 148 149 if (bus_dmamap_create(osc->sc_dmat, 150 OIOC_SCSI_DMA_NSEGS * PAGE_SIZE, 151 OIOC_SCSI_DMA_NSEGS, PAGE_SIZE, PAGE_SIZE, 152 BUS_DMA_WAITOK, &osc->sc_dmamap) != 0) { 153 printf(": failed to create dmamap\n"); 154 return; 155 } 156 157 sc->sc_dmasetup = oiocsc_dmasetup; 158 sc->sc_dmago = oiocsc_dmago; 159 sc->sc_dmastop = oiocsc_dmastop; 160 sc->sc_reset = oiocsc_reset; 161 162 sc->sc_adapter.adapt_request = wd33c93_scsi_request; 163 sc->sc_adapter.adapt_minphys = minphys; 164 165 sc->sc_id = 0; /* Host ID = 0 */ 166 sc->sc_clkfreq = 100; /* 10MHz */ 167 168 /* Disable DMA - it's not ready for prime time, see oiocsc_dmasetup */ 169 #if 0 170 sc->sc_dmamode = (oa->oa_burst_dma) ? 171 SBIC_CTL_BURST_DMA : SBIC_CTL_DMA; 172 #else 173 sc->sc_dmamode = 0; 174 #endif 175 176 evcnt_attach_dynamic(&osc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, 177 device_xname(sc->sc_dev), "intr"); 178 179 if ((cpu_intr_establish(oa->oa_irq, IPL_BIO, 180 oiocsc_scsiintr, sc)) == NULL) { 181 printf(": unable to establish interrupt!\n"); 182 return; 183 } 184 185 wd33c93_attach(sc); 186 } 187 188 /* 189 * Prime the hardware for a DMA transfer 190 * 191 * Requires splbio() interrupts to be disabled by the caller 192 * 193 * XXX- I'm not sure if this works properly yet. Primarily, I'm not sure 194 * that all ds_addr's after the first will be page aligned. If they're 195 * not, we apparently cannot use this DMA engine... 196 * 197 * Unfortunately, I'm getting mutex panics while testing with EFS (haven't 198 * tried FFS), so I cannot yet confirm whether this works or not. 199 */ 200 int 201 oiocsc_dmasetup(struct wd33c93_softc *dev, void **addr, size_t *len, int datain, 202 size_t *dmasize) 203 { 204 struct oiocsc_softc *osc = (void *)dev; 205 struct oioc_dma_softc *dsc = &osc->sc_oiocdma; 206 int count, err, i; 207 void *vaddr; 208 209 KASSERT((osc->sc_flags & WDSC_DMA_ACTIVE) == 0); 210 211 vaddr = *addr; 212 count = dsc->sc_dlen = *len; 213 214 if (count) { 215 bus_dmamap_t dmamap = osc->sc_dmamap; 216 217 KASSERT((osc->sc_flags & WDSC_DMA_MAPLOADED) == 0); 218 219 /* Build list of physical addresses for this transfer */ 220 if ((err = bus_dmamap_load(osc->sc_dmat, osc->sc_dmamap, 221 vaddr, count, 222 NULL /* kernel address */, 223 BUS_DMA_NOWAIT)) != 0) 224 panic("%s: bus_dmamap_load err=%d", 225 device_xname(dev->sc_dev), err); 226 227 /* 228 * We can map the contiguous buffer with up to 256 pages. 229 * The DMA low address register contains a 12-bit offset for 230 * the first page (in case the buffer isn't aligned). The 256 231 * high registers contain 16 bits each for page numbers. 232 * 233 * We will fill in the high registers here. The low register 234 * fires off the DMA engine and is set in oiocsc_dmago. 235 */ 236 dsc->sc_dmalow = dmamap->dm_segs[0].ds_addr & 237 OIOC_SCSI_DMA_LOW_ADDR_MASK; 238 239 KASSERT(dmamap->dm_nsegs <= OIOC_SCSI_DMA_NSEGS); 240 241 for (i = 0; i < dmamap->dm_nsegs; i++) { 242 uint16_t pgnum; 243 244 pgnum = dmamap->dm_segs[i].ds_addr >> 245 OIOC_SCSI_DMA_HIGH_SHFT; 246 247 bus_space_write_2(osc->sc_st, osc->sc_sh, 248 OIOC_SCSI_DMA_HIGH(i), pgnum); 249 } 250 251 osc->sc_flags |= WDSC_DMA_MAPLOADED; 252 253 if (datain) 254 dsc->sc_dmalow |= OIOC_SCSI_DMA_LOW_ADDR_DMADIR; 255 } 256 257 return (count); 258 } 259 260 /* 261 * Prime the hardware for the next DMA transfer 262 */ 263 int 264 oiocsc_dmago(struct wd33c93_softc *dev) 265 { 266 struct oiocsc_softc *osc = (void *)dev; 267 struct oioc_dma_softc *dsc = &osc->sc_oiocdma; 268 269 if (dsc->sc_dlen == 0) 270 return(0); 271 272 KASSERT((osc->sc_flags & WDSC_DMA_ACTIVE) == 0); 273 KASSERT((osc->sc_flags & WDSC_DMA_MAPLOADED)); 274 275 osc->sc_flags |= WDSC_DMA_ACTIVE; 276 277 bus_dmamap_sync(osc->sc_dmat, osc->sc_dmamap, 0, 278 osc->sc_dmamap->dm_mapsize, 279 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 280 281 /* Blastoff! */ 282 bus_space_write_2(osc->sc_st, osc->sc_sh, 283 OIOC_SCSI_DMA_LOW, dsc->sc_dmalow); 284 285 return(osc->sc_dmamap->dm_mapsize); 286 } 287 288 /* 289 * Stop DMA and unload active DMA maps 290 */ 291 void 292 oiocsc_dmastop(struct wd33c93_softc *dev) 293 { 294 struct oiocsc_softc *osc = (void *)dev; 295 296 if (osc->sc_flags & WDSC_DMA_ACTIVE) { 297 /* Stop DMA, flush and sync */ 298 bus_space_write_4(osc->sc_st, osc->sc_sh, 299 OIOC_SCSI_DMA_FLUSH, 0); 300 bus_dmamap_sync(osc->sc_dmat, osc->sc_dmamap, 0, 301 osc->sc_dmamap->dm_mapsize, 302 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 303 } 304 if (osc->sc_flags & WDSC_DMA_MAPLOADED) 305 bus_dmamap_unload(osc->sc_dmat, osc->sc_dmamap); 306 osc->sc_flags &= ~(WDSC_DMA_ACTIVE | WDSC_DMA_MAPLOADED); 307 } 308 309 /* 310 * Reset the controller. 311 */ 312 void 313 oiocsc_reset(struct wd33c93_softc *dev) 314 { 315 struct oiocsc_softc *osc = (void *)dev; 316 317 /* hard reset the chip */ 318 bus_space_read_4(osc->sc_st, osc->sc_sh, OIOC_SCSI_RESET_ON); 319 delay(1000); 320 bus_space_read_4(osc->sc_st, osc->sc_sh, OIOC_SCSI_RESET_OFF); 321 delay(1000); 322 } 323 324 /* 325 * WD33c93 SCSI controller interrupt 326 */ 327 int 328 oiocsc_scsiintr(void *arg) 329 { 330 struct wd33c93_softc *dev = arg; 331 struct oiocsc_softc *osc = arg; 332 int found; 333 334 found = wd33c93_intr(dev); 335 if (found) 336 osc->sc_intrcnt.ev_count++; 337 return(found); 338 } 339