1/* $NetBSD: oiocsc.c,v 1.4 2019/12/27 09:41:50 msaitoh 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.4 2019/12/27 09:41:50 msaitoh 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 68struct 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 transferred */ 88 } sc_oiocdma; 89}; 90 91 92void oiocsc_attach (device_t, device_t, void *); 93int oiocsc_match (device_t, struct cfdata *, void *); 94 95CFATTACH_DECL_NEW(oiocsc, sizeof(struct oiocsc_softc), 96 oiocsc_match, oiocsc_attach, NULL, NULL); 97 98int oiocsc_dmasetup (struct wd33c93_softc *, void **, size_t *, 99 int, size_t *); 100int oiocsc_dmago (struct wd33c93_softc *); 101void oiocsc_dmastop (struct wd33c93_softc *); 102void oiocsc_reset (struct wd33c93_softc *); 103int oiocsc_dmaintr (void *); 104int oiocsc_scsiintr (void *); 105 106/* 107 * Always present on IP4, IP6, IP10. 108 */ 109int 110oiocsc_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 */ 123void 124oiocsc_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 */ 200int 201oiocsc_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 */ 263int 264oiocsc_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 */ 291void 292oiocsc_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 */ 312void 313oiocsc_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 */ 327int 328oiocsc_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