lsi64854.c revision 226381
1181111Sdes/*- 2107553Sdes * Copyright (c) 2004 Scott Long 399059Sdes * All rights reserved. 4221420Sdes * 5221420Sdes * Redistribution and use in source and binary forms, with or without 6221420Sdes * modification, are permitted provided that the following conditions 7157020Sdes * are met: 8157020Sdes * 1. Redistributions of source code must retain the above copyright 9157020Sdes * notice, this list of conditions and the following disclaimer. 10124244Sdes * 2. Redistributions in binary form must reproduce the above copyright 11157020Sdes * notice, this list of conditions and the following disclaimer in the 12157020Sdes * documentation and/or other materials provided with the distribution. 1399059Sdes * 14181111Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15181111Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16181111Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17157020Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18157020Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1999059Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20247892Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21247892Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22247892Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23157020Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24157020Sdes * SUCH DAMAGE. 2599059Sdes * 26157020Sdes */ 27157020Sdes 28124244Sdes/* $NetBSD: lsi64854.c,v 1.33 2008/04/28 20:23:50 martin Exp $ */ 29157020Sdes 30157020Sdes/*- 31124244Sdes * Copyright (c) 1998 The NetBSD Foundation, Inc. 32181111Sdes * All rights reserved. 33181111Sdes * 34181111Sdes * This code is derived from software contributed to The NetBSD Foundation 3599059Sdes * by Paul Kranenburg. 3699059Sdes * 3799059Sdes * Redistribution and use in source and binary forms, with or without 38157020Sdes * modification, are permitted provided that the following conditions 39157020Sdes * are met: 4099059Sdes * 1. Redistributions of source code must retain the above copyright 41157020Sdes * notice, this list of conditions and the following disclaimer. 42157020Sdes * 2. Redistributions in binary form must reproduce the above copyright 4399059Sdes * notice, this list of conditions and the following disclaimer in the 44157020Sdes * documentation and/or other materials provided with the distribution. 45157020Sdes * 46157020Sdes * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 4799059Sdes * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 48181111Sdes * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 49181111Sdes * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 50181111Sdes * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 5199059Sdes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 5299059Sdes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 5399059Sdes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 54157020Sdes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 55157020Sdes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 5699059Sdes * POSSIBILITY OF SUCH DAMAGE. 57157020Sdes */ 58157020Sdes 5999059Sdes#include <sys/cdefs.h> 60157020Sdes__FBSDID("$FreeBSD: head/sys/sparc64/sbus/lsi64854.c 226381 2011-10-15 09:29:43Z marius $"); 61157020Sdes 6299059Sdes#include <sys/param.h> 63157020Sdes#include <sys/systm.h> 64157020Sdes#include <sys/bus.h> 65124244Sdes#include <sys/kernel.h> 66157020Sdes#include <sys/lock.h> 67157020Sdes#include <sys/mutex.h> 68128462Sdes#include <sys/rman.h> 69157020Sdes 70157020Sdes#include <machine/bus.h> 7199059Sdes 72181111Sdes#include <cam/cam.h> 73181111Sdes#include <cam/cam_ccb.h> 74181111Sdes#include <cam/scsi/scsi_all.h> 75157020Sdes 76157020Sdes#include <sparc64/sbus/lsi64854reg.h> 7799059Sdes#include <sparc64/sbus/lsi64854var.h> 78197679Sdes 79197679Sdes#include <dev/esp/ncr53c9xreg.h> 80197679Sdes#include <dev/esp/ncr53c9xvar.h> 81157020Sdes 82157020Sdes#ifdef DEBUG 8399059Sdes#define LDB_SCSI 1 84157020Sdes#define LDB_ENET 2 85157020Sdes#define LDB_PP 4 8699059Sdes#define LDB_ANY 0xff 87157020Sdesint lsi64854debug = 0; 88157020Sdes#define DPRINTF(a,x) \ 8999059Sdes do { \ 90157020Sdes if ((lsi64854debug & (a)) != 0) \ 91202213Sed printf x; \ 9299059Sdes } while (/* CONSTCOND */0) 93157020Sdes#else 94157020Sdes#define DPRINTF(a,x) 9599059Sdes#endif 96157020Sdes 97202213Sed#define MAX_DMA_SZ (16*1024*1024) 9899059Sdes 99157020Sdesstatic void lsi64854_reset(struct lsi64854_softc *); 100157020Sdesstatic void lsi64854_map_scsi(void *, bus_dma_segment_t *, int, int); 10199059Sdesstatic int lsi64854_setup(struct lsi64854_softc *, void **, size_t *, 102157020Sdes int, size_t *); 103247892Sdesstatic int lsi64854_scsi_intr(void *); 10499059Sdesstatic int lsi64854_enet_intr(void *); 10599059Sdesstatic int lsi64854_setup_pp(struct lsi64854_softc *, void **, 10699059Sdes size_t *, int, size_t *); 10799059Sdesstatic int lsi64854_pp_intr(void *); 10899059Sdes 10999059Sdes/* 11099059Sdes * Finish attaching this DMA device. 11199059Sdes * Front-end must fill in these fields: 11299059Sdes * sc_res 11399059Sdes * sc_burst 114157020Sdes * sc_channel (one of SCSI, ENET, PP) 115157020Sdes * sc_client (one of SCSI, ENET, PP `soft_c' pointers) 11699059Sdes */ 11799059Sdesint 118202213Sedlsi64854_attach(struct lsi64854_softc *sc) 11999059Sdes{ 12099059Sdes bus_dma_lock_t *lockfunc; 121202213Sed struct ncr53c9x_softc *nsc; 12299059Sdes void *lockfuncarg; 12399059Sdes uint32_t csr; 124202213Sed int error; 12599059Sdes 12699059Sdes lockfunc = NULL; 12799059Sdes lockfuncarg = NULL; 12899059Sdes 129204917Sdes switch (sc->sc_channel) { 130207319Sdes case L64854_CHANNEL_SCSI: 131204917Sdes nsc = sc->sc_client; 132221420Sdes if (NCR_LOCK_INITIALIZED(nsc) == 0) { 133221420Sdes device_printf(sc->sc_dev, "mutex not initialized\n"); 134221420Sdes return (ENXIO); 135197679Sdes } 136181111Sdes lockfunc = busdma_lock_mutex; 137181111Sdes lockfuncarg = &nsc->sc_lock; 138197679Sdes sc->intr = lsi64854_scsi_intr; 139197679Sdes sc->setup = lsi64854_setup; 140197679Sdes break; 141157020Sdes case L64854_CHANNEL_ENET: 142157020Sdes sc->intr = lsi64854_enet_intr; 14399059Sdes break; 144157020Sdes case L64854_CHANNEL_PP: 145157020Sdes sc->intr = lsi64854_pp_intr; 14699059Sdes sc->setup = lsi64854_setup_pp; 14799059Sdes break; 148159458Sdes default: 14999059Sdes device_printf(sc->sc_dev, "unknown channel\n"); 15099059Sdes } 151159458Sdes sc->reset = lsi64854_reset; 15299059Sdes 153221420Sdes if (sc->setup != NULL) { 154221420Sdes error = bus_dma_tag_create( 155221420Sdes sc->sc_parent_dmat, /* parent */ 156157020Sdes 1, 0, /* alignment, boundary */ 157157020Sdes BUS_SPACE_MAXADDR, /* lowaddr */ 15899059Sdes BUS_SPACE_MAXADDR, /* highaddr */ 159157020Sdes NULL, NULL, /* filter, filterarg */ 160157020Sdes MAX_DMA_SZ, /* maxsize */ 161124244Sdes 1, /* nsegments */ 162157020Sdes MAX_DMA_SZ, /* maxsegsize */ 163157020Sdes BUS_DMA_ALLOCNOW, /* flags */ 16499059Sdes lockfunc, lockfuncarg, /* lockfunc, lockfuncarg */ 165157020Sdes &sc->sc_buffer_dmat); 166157020Sdes if (error != 0) { 16799059Sdes device_printf(sc->sc_dev, 168157020Sdes "cannot allocate buffer DMA tag\n"); 169157020Sdes return (error); 17099059Sdes } 171157020Sdes 172157020Sdes error = bus_dmamap_create(sc->sc_buffer_dmat, 0, 17399059Sdes &sc->sc_dmamap); 174157020Sdes if (error != 0) { 175157020Sdes device_printf(sc->sc_dev, "DMA map create failed\n"); 17699059Sdes bus_dma_tag_destroy(sc->sc_buffer_dmat); 177157020Sdes return (error); 178157020Sdes } 17999059Sdes } 180181111Sdes 181181111Sdes csr = L64854_GCSR(sc); 182181111Sdes sc->sc_rev = csr & L64854_DEVID; 183181111Sdes if (sc->sc_rev == DMAREV_HME) 184181111Sdes return (0); 185181111Sdes device_printf(sc->sc_dev, "DMA rev. "); 186157020Sdes switch (sc->sc_rev) { 187157020Sdes case DMAREV_0: 18899059Sdes printf("0"); 189157020Sdes break; 190157020Sdes case DMAREV_ESC: 19199059Sdes printf("ESC"); 192181111Sdes break; 193181111Sdes case DMAREV_1: 194181111Sdes printf("1"); 195149754Sdes break; 196149754Sdes case DMAREV_PLUS: 197149754Sdes printf("1+"); 198181111Sdes break; 199181111Sdes case DMAREV_2: 200181111Sdes printf("2"); 201107553Sdes break; 20299059Sdes default: 20399059Sdes printf("unknown (0x%x)", sc->sc_rev); 204113912Sdes } 205113912Sdes 206113912Sdes DPRINTF(LDB_ANY, (", burst 0x%x, csr 0x%x", sc->sc_burst, csr)); 207157020Sdes printf("\n"); 208157020Sdes 209157020Sdes return (0); 210107553Sdes} 21199059Sdes 21299059Sdesint 213107553Sdeslsi64854_detach(struct lsi64854_softc *sc) 21499059Sdes{ 21599059Sdes 216221420Sdes if (sc->setup != NULL) { 217221420Sdes bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, 218221420Sdes (L64854_GCSR(sc) & L64854_WRITE) != 0 ? 219147006Sdes BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 220147006Sdes bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap); 221147006Sdes bus_dmamap_destroy(sc->sc_buffer_dmat, sc->sc_dmamap); 222107553Sdes bus_dma_tag_destroy(sc->sc_buffer_dmat); 22399059Sdes } 22499059Sdes 225107553Sdes return (0); 22699059Sdes} 22799059Sdes 228157020Sdes/* 229157020Sdes * DMAWAIT waits while condition is true. 230157020Sdes */ 231137019Sdes#define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) { \ 232194297Sjhb int count = 500000; \ 233137019Sdes while ((COND) && --count > 0) DELAY(1); \ 234124244Sdes if (count == 0) { \ 235147006Sdes printf("%s: line %d: CSR = 0x%lx\n", __FILE__, __LINE__, \ 236124244Sdes (u_long)L64854_GCSR(SC)); \ 237157020Sdes if (DONTPANIC) \ 238157020Sdes printf(MSG); \ 239157020Sdes else \ 240162860Sdes panic(MSG); \ 241162860Sdes } \ 242162860Sdes} while (/* CONSTCOND */0) 243107553Sdes 24499059Sdes#define DMA_DRAIN(sc, dontpanic) do { \ 24599059Sdes uint32_t csr; \ 246157020Sdes /* \ 247157020Sdes * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \ 248157020Sdes * and "drain" bits while it is still thinking about a \ 249157020Sdes * request. \ 250157020Sdes * other revs: D_ESC_R_PEND bit reads as 0 \ 251157020Sdes */ \ 252147006Sdes DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\ 253147006Sdes if (sc->sc_rev != DMAREV_HME) { \ 254147006Sdes /* \ 255147006Sdes * Select drain bit based on revision \ 256162860Sdes * also clears errors and D_TC flag \ 257162860Sdes */ \ 258162860Sdes csr = L64854_GCSR(sc); \ 259162860Sdes if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0) \ 260137019Sdes csr |= D_ESC_DRAIN; \ 261137019Sdes else \ 262137019Sdes csr |= L64854_INVALIDATE; \ 263137019Sdes \ 264147006Sdes L64854_SCSR(sc,csr); \ 265147006Sdes } \ 266147006Sdes /* \ 267147006Sdes * Wait for draining to finish \ 268147006Sdes * rev0 & rev1 call this PACKCNT \ 269147006Sdes */ \ 270147006Sdes DMAWAIT(sc, L64854_GCSR(sc) & L64854_DRAINING, "DRAINING", dontpanic);\ 271147006Sdes} while (/* CONSTCOND */0) 272147006Sdes 273147006Sdes#define DMA_FLUSH(sc, dontpanic) do { \ 274147006Sdes uint32_t csr; \ 275147006Sdes /* \ 276181111Sdes * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \ 277181111Sdes * and "drain" bits while it is still thinking about a \ 278181111Sdes * request. \ 279181111Sdes * other revs: D_ESC_R_PEND bit reads as 0 \ 280181111Sdes */ \ 281181111Sdes DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\ 282181111Sdes csr = L64854_GCSR(sc); \ 283181111Sdes csr &= ~(L64854_WRITE|L64854_EN_DMA); /* no-ops on ENET */ \ 284162860Sdes csr |= L64854_INVALIDATE; /* XXX FAS ? */ \ 285162860Sdes L64854_SCSR(sc,csr); \ 286162860Sdes} while (/* CONSTCOND */0) 287162860Sdes 288147006Sdesstatic void 289147006Sdeslsi64854_reset(struct lsi64854_softc *sc) 290147006Sdes{ 291147006Sdes uint32_t csr; 292147006Sdes 293147006Sdes DMA_FLUSH(sc, 1); 294147006Sdes csr = L64854_GCSR(sc); 295147006Sdes 296162860Sdes DPRINTF(LDB_ANY, ("%s: csr 0x%x\n", __func__, csr)); 297162860Sdes 298162860Sdes if (sc->sc_dmasize != 0) { 299162860Sdes bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, 300162860Sdes (csr & D_WRITE) != 0 ? BUS_DMASYNC_PREREAD : 301162860Sdes BUS_DMASYNC_PREWRITE); 302162860Sdes bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap); 303162860Sdes } 304149754Sdes 305149754Sdes if (sc->sc_rev == DMAREV_HME) 306149754Sdes L64854_SCSR(sc, csr | D_HW_RESET_FAS366); 307149754Sdes 308149754Sdes csr |= L64854_RESET; /* reset DMA */ 309149754Sdes L64854_SCSR(sc, csr); 310149754Sdes DELAY(200); /* > 10 Sbus clocks(?) */ 311149754Sdes 312157020Sdes /*DMAWAIT1(sc); why was this here? */ 313247892Sdes csr = L64854_GCSR(sc); 314157020Sdes csr &= ~L64854_RESET; /* de-assert reset line */ 315157020Sdes L64854_SCSR(sc, csr); 316157020Sdes DELAY(5); /* allow a few ticks to settle */ 317157020Sdes 318137019Sdes csr = L64854_GCSR(sc); 319137019Sdes csr |= L64854_INT_EN; /* enable interrupts */ 320137019Sdes if (sc->sc_rev > DMAREV_1 && sc->sc_channel == L64854_CHANNEL_SCSI) { 321137019Sdes if (sc->sc_rev == DMAREV_HME) 322247892Sdes csr |= D_TWO_CYCLE; 323137019Sdes else 324107553Sdes csr |= D_FASTER; 32599059Sdes } 32699059Sdes 327221420Sdes /* Set burst */ 328221420Sdes switch (sc->sc_rev) { 329221420Sdes case DMAREV_HME: 330107553Sdes case DMAREV_2: 33199059Sdes csr &= ~L64854_BURST_SIZE; 33299059Sdes if (sc->sc_burst == 32) 333107553Sdes csr |= L64854_BURST_32; 33499319Sdes else if (sc->sc_burst == 16) 33599059Sdes csr |= L64854_BURST_16; 336107553Sdes else 337202213Sed csr |= L64854_BURST_0; 33899059Sdes break; 339157020Sdes case DMAREV_ESC: 340157020Sdes csr |= D_ESC_AUTODRAIN; /* Auto-drain */ 341157020Sdes if (sc->sc_burst == 32) 342162860Sdes csr &= ~D_ESC_BURST; 343162860Sdes else 344162860Sdes csr |= D_ESC_BURST; 345157020Sdes break; 346157020Sdes default: 347157020Sdes break; 348107553Sdes } 34999059Sdes L64854_SCSR(sc, csr); 35099059Sdes 351107553Sdes if (sc->sc_rev == DMAREV_HME) { 35299059Sdes bus_write_4(sc->sc_res, L64854_REG_ADDR, 0); 35399059Sdes sc->sc_dmactl = csr; 354162860Sdes } 355162860Sdes sc->sc_active = 0; 356162860Sdes 357162860Sdes DPRINTF(LDB_ANY, ("%s: done, csr 0x%x\n", __func__, csr)); 358162860Sdes} 359162860Sdes 360124244Sdesstatic void 361124244Sdeslsi64854_map_scsi(void *arg, bus_dma_segment_t *segs, int nseg, int error) 362124244Sdes{ 363107553Sdes struct lsi64854_softc *sc; 36499059Sdes 36599059Sdes sc = (struct lsi64854_softc *)arg; 366181111Sdes 367181111Sdes if (nseg != 1) 368181111Sdes panic("%s: cannot map %d segments\n", __func__, nseg); 369107553Sdes 37099059Sdes bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, 37199059Sdes sc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 372181111Sdes bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr); 373181111Sdes} 374181111Sdes 375181111Sdes#define DMAMAX(a) (MAX_DMA_SZ - ((a) & (MAX_DMA_SZ - 1))) 376181111Sdes/* 377181111Sdes * setup a DMA transfer 378181111Sdes */ 379181111Sdesstatic int 380181111Sdeslsi64854_setup(struct lsi64854_softc *sc, void **addr, size_t *len, 381107553Sdes int datain, size_t *dmasize) 38299059Sdes{ 38399059Sdes long bcnt; 384107553Sdes uint32_t csr; 38599059Sdes 38699059Sdes DMA_FLUSH(sc, 0); 387107553Sdes 38899059Sdes#if 0 38999059Sdes DMACSR(sc) &= ~D_INT_EN; 390147006Sdes#endif 391147006Sdes sc->sc_dmaaddr = addr; 392147006Sdes sc->sc_dmalen = len; 393147006Sdes sc->sc_datain = datain; 394147006Sdes 395147006Sdes /* 396107553Sdes * The rules say we cannot transfer more than the limit 39799059Sdes * of this DMA chip (64k for old and 16Mb for new), 39899059Sdes * and we cannot cross a 16Mb boundary. 399107553Sdes */ 40099059Sdes *dmasize = sc->sc_dmasize = 40199059Sdes ulmin(*dmasize, DMAMAX((size_t)*sc->sc_dmaaddr)); 402181111Sdes 403181111Sdes DPRINTF(LDB_ANY, ("%s: dmasize=%ld\n", __func__, (long)sc->sc_dmasize)); 404181111Sdes 405192595Sdes /* 406192595Sdes * XXX what length? 407192595Sdes */ 408107553Sdes if (sc->sc_rev == DMAREV_HME) { 40999059Sdes L64854_SCSR(sc, sc->sc_dmactl | L64854_RESET); 41099059Sdes L64854_SCSR(sc, sc->sc_dmactl); 411107553Sdes 41299059Sdes bus_write_4(sc->sc_res, L64854_REG_CNT, *dmasize); 41399059Sdes } 414107553Sdes 41599059Sdes /* Program the DMA address */ 41699059Sdes if (sc->sc_dmasize != 0) 417107553Sdes if (bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap, 418107553Sdes *sc->sc_dmaaddr, sc->sc_dmasize, lsi64854_map_scsi, sc, 0)) 41999059Sdes panic("%s: cannot allocate DVMA address", __func__); 420157020Sdes 421157020Sdes if (sc->sc_rev == DMAREV_ESC) { 422157020Sdes /* DMA ESC chip bug work-around */ 423157020Sdes bcnt = sc->sc_dmasize; 424157020Sdes if (((bcnt + (long)*sc->sc_dmaaddr) & PAGE_MASK_8K) != 0) 425157020Sdes bcnt = roundup(bcnt, PAGE_SIZE_8K); 426107553Sdes bus_write_4(sc->sc_res, L64854_REG_CNT, bcnt); 427107553Sdes } 428107553Sdes 429181111Sdes /* Setup DMA control register */ 430181111Sdes csr = L64854_GCSR(sc); 431181111Sdes 432107553Sdes if (datain) 43399059Sdes csr |= L64854_WRITE; 43499059Sdes else 435107553Sdes csr &= ~L64854_WRITE; 43699059Sdes csr |= L64854_INT_EN; 43799059Sdes 438157020Sdes if (sc->sc_rev == DMAREV_HME) 439157020Sdes csr |= (D_DSBL_SCSI_DRN | D_EN_DMA); 440157020Sdes 441107553Sdes L64854_SCSR(sc, csr); 442124244Sdes 44399059Sdes return (0); 444162860Sdes} 445162860Sdes 446162860Sdes/* 447107553Sdes * Pseudo (chained) interrupt from the esp driver to kick the 44899059Sdes * current running DMA transfer. Called from ncr53c9x_intr() 44999059Sdes * for now. 450107553Sdes * 45199059Sdes * return 1 if it was a DMA continue. 45299059Sdes */ 453107553Sdesstatic int 45499059Sdeslsi64854_scsi_intr(void *arg) 45599059Sdes{ 456107553Sdes struct lsi64854_softc *sc = arg; 45799059Sdes struct ncr53c9x_softc *nsc = sc->sc_client; 45899059Sdes int trans, resid; 459107553Sdes uint32_t csr; 46099319Sdes 46199059Sdes csr = L64854_GCSR(sc); 462107553Sdes 463202213Sed DPRINTF(LDB_SCSI, ("%s: addr 0x%x, csr %b\n", __func__, 46499059Sdes bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, DDMACSR_BITS)); 465107553Sdes 466202213Sed if (csr & (D_ERR_PEND|D_SLAVE_ERR)) { 46799059Sdes device_printf(sc->sc_dev, "error: csr=%b\n", csr, DDMACSR_BITS); 468107553Sdes csr &= ~D_EN_DMA; /* Stop DMA */ 469202213Sed /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */ 47099059Sdes csr |= D_INVALIDATE|D_SLAVE_ERR; 471207319Sdes L64854_SCSR(sc, csr); 472207319Sdes return (-1); 473207319Sdes } 474162860Sdes 475162860Sdes /* This is an "assertion" :) */ 476162860Sdes if (sc->sc_active == 0) 477107553Sdes panic("%s: DMA wasn't active", __func__); 47899059Sdes 47999059Sdes DMA_DRAIN(sc, 0); 480107553Sdes 48199059Sdes /* DMA has stopped */ 48299059Sdes csr &= ~D_EN_DMA; 483204917Sdes L64854_SCSR(sc, csr); 484204917Sdes sc->sc_active = 0; 485204917Sdes 486126279Sdes if (sc->sc_dmasize == 0) { 487126279Sdes /* A "Transfer Pad" operation completed */ 488126279Sdes DPRINTF(LDB_SCSI, ("%s: discarded %d bytes (tcl=%d, tcm=%d)\n", 489126279Sdes __func__, NCR_READ_REG(nsc, NCR_TCL) | 490126279Sdes (NCR_READ_REG(nsc, NCR_TCM) << 8), 491126279Sdes NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM))); 492126279Sdes return (0); 493126279Sdes } 494126279Sdes 495126279Sdes resid = 0; 496126279Sdes /* 497126279Sdes * If a transfer onto the SCSI bus gets interrupted by the device 498124244Sdes * (e.g. for a SAVEPOINTER message), the data in the FIFO counts 499147006Sdes * as residual since the NCR53C9X counter registers get decremented 500124244Sdes * as bytes are clocked into the FIFO. 501126279Sdes */ 502126279Sdes if (!(csr & D_WRITE) && 503126279Sdes (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) { 504157020Sdes DPRINTF(LDB_SCSI, ("%s: empty esp FIFO of %d ", __func__, 505157020Sdes resid)); 506157020Sdes if (nsc->sc_rev == NCR_VARIANT_FAS366 && 507247892Sdes (NCR_READ_REG(nsc, NCR_CFG3) & NCRFASCFG3_EWIDE)) 508247892Sdes resid <<= 1; 509247892Sdes } 510157020Sdes 511202213Sed if ((nsc->sc_espstat & NCRSTAT_TC) == 0) { 512157020Sdes /* 513157020Sdes * `Terminal count' is off, so read the residue 514202213Sed * out of the NCR53C9X counter registers. 515157020Sdes */ 516149754Sdes resid += (NCR_READ_REG(nsc, NCR_TCL) | 517149754Sdes (NCR_READ_REG(nsc, NCR_TCM) << 8) | 518149754Sdes ((nsc->sc_cfg2 & NCRCFG2_FE) ? 519107553Sdes (NCR_READ_REG(nsc, NCR_TCH) << 16) : 0)); 520107553Sdes 521107553Sdes if (resid == 0 && sc->sc_dmasize == 65536 && 522157020Sdes (nsc->sc_cfg2 & NCRCFG2_FE) == 0) 523157020Sdes /* A transfer of 64K is encoded as `TCL=TCM=0' */ 524157020Sdes resid = 65536; 525157020Sdes } 526202213Sed 527157020Sdes trans = sc->sc_dmasize - resid; 528107553Sdes if (trans < 0) { /* transferred < 0? */ 52999059Sdes#if 0 53099059Sdes /* 531107553Sdes * This situation can happen in perfectly normal operation 53299059Sdes * if the ESP is reselected while using DMA to select 53399059Sdes * another target. As such, don't print the warning. 534107553Sdes */ 53599059Sdes device_printf(sc->sc_dev, "xfer (%d) > req (%d)\n", trans, 53699059Sdes sc->sc_dmasize); 537107553Sdes#endif 53899059Sdes trans = sc->sc_dmasize; 53999059Sdes } 540157020Sdes 541157020Sdes DPRINTF(LDB_SCSI, ("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n", 542157020Sdes __func__, NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM), 543107553Sdes (nsc->sc_cfg2 & NCRCFG2_FE) ? NCR_READ_REG(nsc, NCR_TCH) : 0, 544162953Sdes trans, resid)); 54599059Sdes 546157020Sdes if (sc->sc_dmasize != 0) { 547157020Sdes bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, 548157020Sdes (csr & D_WRITE) != 0 ? BUS_DMASYNC_POSTREAD : 549147006Sdes BUS_DMASYNC_POSTWRITE); 550147006Sdes bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap); 551147006Sdes } 552197679Sdes 553197679Sdes *sc->sc_dmalen -= trans; 554197679Sdes *sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans; 555221420Sdes 556221420Sdes#if 0 /* this is not normal operation just yet */ 557221420Sdes if (*sc->sc_dmalen == 0 || nsc->sc_phase != nsc->sc_prevphase) 558107553Sdes return (0); 55999059Sdes 56099059Sdes /* and again */ 561247892Sdes dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMACSR(sc) & D_WRITE); 562247892Sdes return (1); 563247892Sdes#endif 564221420Sdes return (0); 565221420Sdes} 566221420Sdes 567147006Sdes/* 568147006Sdes * Pseudo (chained) interrupt to le driver to handle DMA errors. 569147006Sdes */ 570107553Sdesstatic int 571107553Sdeslsi64854_enet_intr(void *arg) 572107553Sdes{ 573107553Sdes struct lsi64854_softc *sc = arg; 57499059Sdes uint32_t csr; 57599059Sdes int i, rv; 576107553Sdes 57799059Sdes csr = L64854_GCSR(sc); 57899059Sdes 579181111Sdes /* If the DMA logic shows an interrupt, claim it */ 580149754Sdes rv = ((csr & E_INT_PEND) != 0) ? 1 : 0; 581149754Sdes 582207319Sdes if (csr & (E_ERR_PEND|E_SLAVE_ERR)) { 583207319Sdes device_printf(sc->sc_dev, "error: csr=%b\n", csr, EDMACSR_BITS); 584207319Sdes csr &= ~L64854_EN_DMA; /* Stop DMA */ 585107553Sdes /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */ 58699059Sdes csr |= E_INVALIDATE|E_SLAVE_ERR; 58799059Sdes L64854_SCSR(sc, csr); 588107553Sdes /* Will be drained with the LE_C0_IDON interrupt. */ 58999059Sdes sc->sc_dodrain = 1; 59099059Sdes return (-1); 591107553Sdes } 59299059Sdes 59399059Sdes /* XXX - is this necessary with E_DSBL_WR_INVAL on? */ 594107553Sdes if (sc->sc_dodrain) { 59599059Sdes i = 10; 59699059Sdes csr |= E_DRAIN; 597107553Sdes L64854_SCSR(sc, csr); 598107553Sdes while (i-- > 0 && (L64854_GCSR(sc) & E_DRAINING)) 599107553Sdes DELAY(1); 600107553Sdes sc->sc_dodrain = 0; 60199059Sdes } 60299059Sdes 603107553Sdes return (rv); 60499059Sdes} 60599059Sdes 606247892Sdesstatic void 607247892Sdeslsi64854_map_pp(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 608247892Sdes{ 609247892Sdes struct lsi64854_softc *sc; 610247892Sdes 611247892Sdes sc = (struct lsi64854_softc *)arg; 612157020Sdes 613157020Sdes if (nsegs != 1) 614157020Sdes panic("%s: cannot map %d segments\n", __func__, nsegs); 615247892Sdes 616247892Sdes bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, sc->sc_datain ? 617247892Sdes BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 618247892Sdes bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr); 619202213Sed 620157020Sdes bus_write_4(sc->sc_res, L64854_REG_CNT, sc->sc_dmasize); 621107553Sdes} 62299059Sdes 62399059Sdes/* 624107553Sdes * setup a DMA transfer 62599059Sdes */ 62699059Sdesstatic int 627107553Sdeslsi64854_setup_pp(struct lsi64854_softc *sc, void **addr, size_t *len, 62899059Sdes int datain, size_t *dmasize) 62999059Sdes{ 630107553Sdes uint32_t csr; 631202213Sed 63299059Sdes DMA_FLUSH(sc, 0); 633107553Sdes 634202213Sed sc->sc_dmaaddr = addr; 63599059Sdes sc->sc_dmalen = len; 636157020Sdes sc->sc_datain = datain; 637157020Sdes 638157020Sdes DPRINTF(LDB_PP, ("%s: pp start %ld@%p,%d\n", __func__, 639157020Sdes (long)*sc->sc_dmalen, *sc->sc_dmaaddr, datain ? 1 : 0)); 640157020Sdes 641157020Sdes /* 642107553Sdes * the rules say we cannot transfer more than the limit 64399059Sdes * of this DMA chip (64k for old and 16Mb for new), 64499059Sdes * and we cannot cross a 16Mb boundary. 645107553Sdes */ 64699059Sdes *dmasize = sc->sc_dmasize = 64799059Sdes ulmin(*dmasize, DMAMAX((size_t)*sc->sc_dmaaddr)); 648157020Sdes 649157020Sdes DPRINTF(LDB_PP, ("%s: dmasize=%ld\n", __func__, (long)sc->sc_dmasize)); 650157020Sdes 651107553Sdes /* Program the DMA address */ 65299059Sdes if (sc->sc_dmasize != 0) 65399059Sdes if (bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap, 654107553Sdes *sc->sc_dmaaddr, sc->sc_dmasize, lsi64854_map_pp, sc, 0)) 655162953Sdes panic("%s: pp cannot allocate DVMA address", __func__); 65699059Sdes 657107553Sdes /* Setup DMA control register */ 65899059Sdes csr = L64854_GCSR(sc); 65999059Sdes csr &= ~L64854_BURST_SIZE; 660107553Sdes if (sc->sc_burst == 32) 66199059Sdes csr |= L64854_BURST_32; 66299059Sdes else if (sc->sc_burst == 16) 663157020Sdes csr |= L64854_BURST_16; 664157020Sdes else 665157020Sdes csr |= L64854_BURST_0; 666157020Sdes csr |= P_EN_DMA|P_INT_EN|P_EN_CNT; 667157020Sdes#if 0 668157020Sdes /* This bit is read-only in PP csr register */ 669137019Sdes if (datain) 670137019Sdes csr |= P_WRITE; 671137019Sdes else 672107553Sdes csr &= ~P_WRITE; 67399059Sdes#endif 67499059Sdes L64854_SCSR(sc, csr); 675107553Sdes 67699059Sdes return (0); 67799059Sdes} 678162860Sdes 679162860Sdes/* 68099059Sdes * Parallel port DMA interrupt. 681157020Sdes */ 682157020Sdesstatic int 683157020Sdeslsi64854_pp_intr(void *arg) 684107553Sdes{ 68599059Sdes struct lsi64854_softc *sc = arg; 68699059Sdes int ret, trans, resid = 0; 687113912Sdes uint32_t csr; 688113912Sdes 689113912Sdes csr = L64854_GCSR(sc); 690107553Sdes 69199059Sdes DPRINTF(LDB_PP, ("%s: addr 0x%x, csr %b\n", __func__, 69299059Sdes bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, PDMACSR_BITS)); 693157020Sdes 694157020Sdes if (csr & (P_ERR_PEND|P_SLAVE_ERR)) { 695157020Sdes resid = bus_read_4(sc->sc_res, L64854_REG_CNT); 696157020Sdes device_printf(sc->sc_dev, "error: resid %d csr=%b\n", resid, 697124244Sdes csr, PDMACSR_BITS); 698124244Sdes csr &= ~P_EN_DMA; /* Stop DMA */ 699124244Sdes /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */ 700107553Sdes csr |= P_INVALIDATE|P_SLAVE_ERR; 70199059Sdes L64854_SCSR(sc, csr); 70299059Sdes return (-1); 703157020Sdes } 704157020Sdes 705157020Sdes ret = (csr & P_INT_PEND) != 0; 706157020Sdes 707157020Sdes if (sc->sc_active != 0) { 708157020Sdes DMA_DRAIN(sc, 0); 709107553Sdes resid = bus_read_4(sc->sc_res, L64854_REG_CNT); 71099059Sdes } 71199059Sdes 712126279Sdes /* DMA has stopped */ 713126279Sdes csr &= ~D_EN_DMA; 714126279Sdes L64854_SCSR(sc, csr); 715124244Sdes sc->sc_active = 0; 716124244Sdes 717124244Sdes trans = sc->sc_dmasize - resid; 718107553Sdes if (trans < 0) /* transferred < 0? */ 71999059Sdes trans = sc->sc_dmasize; 72099059Sdes *sc->sc_dmalen -= trans; 721157020Sdes *sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans; 722157020Sdes 723157020Sdes if (sc->sc_dmasize != 0) { 724157020Sdes bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, 725157020Sdes (csr & D_WRITE) != 0 ? BUS_DMASYNC_POSTREAD : 726157020Sdes BUS_DMASYNC_POSTWRITE); 727181111Sdes bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap); 728181111Sdes } 729181111Sdes 730181111Sdes return (ret != 0); 731181111Sdes} 732181111Sdes