1 /* $NetBSD: mlhsc.c,v 1.25 2002/01/28 09:57:01 aymeric Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Michael L. Hitch 5 * Copyright (c) 1982, 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)dma.c 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: mlhsc.c,v 1.25 2002/01/28 09:57:01 aymeric Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/device.h> 46 #include <dev/scsipi/scsi_all.h> 47 #include <dev/scsipi/scsipi_all.h> 48 #include <dev/scsipi/scsiconf.h> 49 #include <amiga/amiga/device.h> 50 #include <amiga/amiga/isr.h> 51 #include <amiga/dev/scireg.h> 52 #include <amiga/dev/scivar.h> 53 #include <amiga/dev/zbusvar.h> 54 55 void mlhscattach(struct device *, struct device *, void *); 56 int mlhscmatch(struct device *, struct cfdata *, void *); 57 58 int mlhsc_dma_xfer_in(struct sci_softc *dev, int len, 59 register u_char *buf, int phase); 60 int mlhsc_dma_xfer_out(struct sci_softc *dev, int len, 61 register u_char *buf, int phase); 62 63 #ifdef DEBUG 64 extern int sci_debug; 65 #define QPRINTF(a) if (sci_debug > 1) printf a 66 #else 67 #define QPRINTF(a) 68 #endif 69 70 extern int sci_data_wait; 71 72 struct cfattach mlhsc_ca = { 73 sizeof(struct sci_softc), mlhscmatch, mlhscattach 74 }; 75 76 /* 77 * if we are my Hacker's SCSI board we are here. 78 */ 79 int 80 mlhscmatch(struct device *pdp, struct cfdata *cfp, void *auxp) 81 { 82 struct zbus_args *zap; 83 84 zap = auxp; 85 86 /* 87 * Check manufacturer and product id. 88 */ 89 if (zap->manid == 2011 && zap->prodid == 1) 90 return(1); 91 else 92 return(0); 93 } 94 95 void 96 mlhscattach(struct device *pdp, struct device *dp, void *auxp) 97 { 98 volatile u_char *rp; 99 struct sci_softc *sc = (struct sci_softc *)dp; 100 struct zbus_args *zap; 101 struct scsipi_adapter *adapt = &sc->sc_adapter; 102 struct scsipi_channel *chan = &sc->sc_channel; 103 104 printf("\n"); 105 106 zap = auxp; 107 108 sc = (struct sci_softc *)dp; 109 rp = zap->va; 110 sc->sci_data = rp + 1; 111 sc->sci_odata = rp + 1; 112 sc->sci_icmd = rp + 3; 113 sc->sci_mode = rp + 5; 114 sc->sci_tcmd = rp + 7; 115 sc->sci_bus_csr = rp + 9; 116 sc->sci_sel_enb = rp + 9; 117 sc->sci_csr = rp + 11; 118 sc->sci_dma_send = rp + 11; 119 sc->sci_idata = rp + 13; 120 sc->sci_trecv = rp + 13; 121 sc->sci_iack = rp + 15; 122 sc->sci_irecv = rp + 15; 123 124 sc->dma_xfer_in = mlhsc_dma_xfer_in; 125 sc->dma_xfer_out = mlhsc_dma_xfer_out; 126 127 scireset(sc); 128 129 /* 130 * Fill in the scsipi_adapter. 131 */ 132 memset(adapt, 0, sizeof(*adapt)); 133 adapt->adapt_dev = &sc->sc_dev; 134 adapt->adapt_nchannels = 1; 135 adapt->adapt_openings = 7; 136 adapt->adapt_max_periph = 1; 137 adapt->adapt_request = sci_scsipi_request; 138 adapt->adapt_minphys = sci_minphys; 139 140 /* 141 * Fill in the scsipi_channel. 142 */ 143 memset(chan, 0, sizeof(*chan)); 144 chan->chan_adapter = adapt; 145 chan->chan_bustype = &scsi_bustype; 146 chan->chan_channel = 0; 147 chan->chan_ntargets = 8; 148 chan->chan_nluns = 8; 149 chan->chan_id = 7; 150 151 /* 152 * attach all scsi units on us 153 */ 154 config_found(dp, chan, scsiprint); 155 } 156 157 int 158 mlhsc_dma_xfer_in(struct sci_softc *dev, int len, register u_char *buf, 159 int phase) 160 { 161 int wait = sci_data_wait; 162 u_char csr; 163 volatile register u_char *sci_dma = dev->sci_data + 16; 164 volatile register u_char *sci_csr = dev->sci_csr; 165 #ifdef DEBUG 166 u_char *obp = buf; 167 #endif 168 169 csr = *dev->sci_bus_csr; 170 171 QPRINTF(("mlhdma_in %d, csr=%02x\n", len, csr)); 172 173 *dev->sci_tcmd = phase; 174 *dev->sci_mode |= SCI_MODE_DMA; 175 *dev->sci_icmd = 0; 176 *dev->sci_irecv = 0; 177 while (len > 128) { 178 wait = sci_data_wait; 179 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 180 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 181 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 182 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 183 || --wait < 0) { 184 #ifdef DEBUG 185 if (sci_debug) 186 printf("mlhdma_in fail: l%d i%x w%d\n", 187 len, csr, wait); 188 #endif 189 *dev->sci_mode &= ~SCI_MODE_DMA; 190 return 0; 191 } 192 } 193 194 #define R1 (*buf++ = *sci_dma) 195 R1; R1; R1; R1; R1; R1; R1; R1; 196 R1; R1; R1; R1; R1; R1; R1; R1; 197 R1; R1; R1; R1; R1; R1; R1; R1; 198 R1; R1; R1; R1; R1; R1; R1; R1; 199 R1; R1; R1; R1; R1; R1; R1; R1; 200 R1; R1; R1; R1; R1; R1; R1; R1; 201 R1; R1; R1; R1; R1; R1; R1; R1; 202 R1; R1; R1; R1; R1; R1; R1; R1; 203 R1; R1; R1; R1; R1; R1; R1; R1; 204 R1; R1; R1; R1; R1; R1; R1; R1; 205 R1; R1; R1; R1; R1; R1; R1; R1; 206 R1; R1; R1; R1; R1; R1; R1; R1; 207 R1; R1; R1; R1; R1; R1; R1; R1; 208 R1; R1; R1; R1; R1; R1; R1; R1; 209 R1; R1; R1; R1; R1; R1; R1; R1; 210 R1; R1; R1; R1; R1; R1; R1; R1; 211 len -= 128; 212 } 213 while (len > 0) { 214 wait = sci_data_wait; 215 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 216 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 217 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 218 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 219 || --wait < 0) { 220 #ifdef DEBUG 221 if (sci_debug) 222 printf("mlhdma_in fail: l%d i%x w%d\n", 223 len, csr, wait); 224 #endif 225 *dev->sci_mode &= ~SCI_MODE_DMA; 226 return 0; 227 } 228 } 229 230 *buf++ = *sci_dma; 231 len--; 232 } 233 234 QPRINTF(("mlhdma_in {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 235 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5], 236 obp[6], obp[7], obp[8], obp[9])); 237 238 *dev->sci_mode &= ~SCI_MODE_DMA; 239 return 0; 240 } 241 242 int 243 mlhsc_dma_xfer_out(struct sci_softc *dev, int len, register u_char *buf, 244 int phase) 245 { 246 int wait = sci_data_wait; 247 u_char csr; 248 volatile register u_char *sci_dma = dev->sci_data + 16; 249 volatile register u_char *sci_csr = dev->sci_csr; 250 251 csr = *dev->sci_bus_csr; 252 253 QPRINTF(("mlhdma_xfer %d, csr=%02x\n", len, csr)); 254 255 QPRINTF(("mlhgdma_out {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 256 len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], 257 buf[6], buf[7], buf[8], buf[9])); 258 259 *dev->sci_tcmd = phase; 260 *dev->sci_mode |= SCI_MODE_DMA; 261 *dev->sci_icmd = SCI_ICMD_DATA; 262 *dev->sci_dma_send = 0; 263 while (len > 64) { 264 wait = sci_data_wait; 265 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 266 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 267 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 268 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 269 || --wait < 0) { 270 #ifdef DEBUG 271 if (sci_debug) 272 printf("mlhdma_out fail: l%d i%x w%d\n", 273 len, csr, wait); 274 #endif 275 *dev->sci_mode &= ~SCI_MODE_DMA; 276 return 0; 277 } 278 } 279 280 #define W1 (*sci_dma = *buf++) 281 W1; W1; W1; W1; W1; W1; W1; W1; 282 W1; W1; W1; W1; W1; W1; W1; W1; 283 W1; W1; W1; W1; W1; W1; W1; W1; 284 W1; W1; W1; W1; W1; W1; W1; W1; 285 W1; W1; W1; W1; W1; W1; W1; W1; 286 W1; W1; W1; W1; W1; W1; W1; W1; 287 W1; W1; W1; W1; W1; W1; W1; W1; 288 W1; W1; W1; W1; W1; W1; W1; W1; 289 len -= 64; 290 } 291 while (len > 0) { 292 wait = sci_data_wait; 293 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 294 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 295 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 296 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 297 || --wait < 0) { 298 #ifdef DEBUG 299 if (sci_debug) 300 printf("mlhdma_out fail: l%d i%x w%d\n", 301 len, csr, wait); 302 #endif 303 *dev->sci_mode &= ~SCI_MODE_DMA; 304 return 0; 305 } 306 } 307 308 *sci_dma = *buf++; 309 len--; 310 } 311 312 wait = sci_data_wait; 313 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) == 314 SCI_CSR_PHASE_MATCH && --wait); 315 316 *dev->sci_mode &= ~SCI_MODE_DMA; 317 return 0; 318 } 319