1 /* $NetBSD: mlhsc.c,v 1.22 1998/12/05 19:43:37 mjacob 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 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/device.h> 42 #include <dev/scsipi/scsi_all.h> 43 #include <dev/scsipi/scsipi_all.h> 44 #include <dev/scsipi/scsiconf.h> 45 #include <amiga/amiga/device.h> 46 #include <amiga/amiga/isr.h> 47 #include <amiga/dev/scireg.h> 48 #include <amiga/dev/scivar.h> 49 #include <amiga/dev/zbusvar.h> 50 51 void mlhscattach __P((struct device *, struct device *, void *)); 52 int mlhscmatch __P((struct device *, struct cfdata *, void *)); 53 54 int mlhsc_dma_xfer_in __P((struct sci_softc *dev, int len, 55 register u_char *buf, int phase)); 56 int mlhsc_dma_xfer_out __P((struct sci_softc *dev, int len, 57 register u_char *buf, int phase)); 58 59 struct scsipi_device mlhsc_scsidev = { 60 NULL, /* use default error handler */ 61 NULL, /* do not have a start functio */ 62 NULL, /* have no async handler */ 63 NULL, /* Use default done routine */ 64 }; 65 66 #ifdef DEBUG 67 extern int sci_debug; 68 #define QPRINTF(a) if (sci_debug > 1) printf a 69 #else 70 #define QPRINTF(a) 71 #endif 72 73 extern int sci_data_wait; 74 75 struct cfattach mlhsc_ca = { 76 sizeof(struct sci_softc), mlhscmatch, mlhscattach 77 }; 78 79 /* 80 * if we are my Hacker's SCSI board we are here. 81 */ 82 int 83 mlhscmatch(pdp, cfp, auxp) 84 struct device *pdp; 85 struct cfdata *cfp; 86 void *auxp; 87 { 88 struct zbus_args *zap; 89 90 zap = auxp; 91 92 /* 93 * Check manufacturer and product id. 94 */ 95 if (zap->manid == 2011 && zap->prodid == 1) 96 return(1); 97 else 98 return(0); 99 } 100 101 void 102 mlhscattach(pdp, dp, auxp) 103 struct device *pdp, *dp; 104 void *auxp; 105 { 106 volatile u_char *rp; 107 struct sci_softc *sc; 108 struct zbus_args *zap; 109 110 printf("\n"); 111 112 zap = auxp; 113 114 sc = (struct sci_softc *)dp; 115 rp = zap->va; 116 sc->sci_data = rp + 1; 117 sc->sci_odata = rp + 1; 118 sc->sci_icmd = rp + 3; 119 sc->sci_mode = rp + 5; 120 sc->sci_tcmd = rp + 7; 121 sc->sci_bus_csr = rp + 9; 122 sc->sci_sel_enb = rp + 9; 123 sc->sci_csr = rp + 11; 124 sc->sci_dma_send = rp + 11; 125 sc->sci_idata = rp + 13; 126 sc->sci_trecv = rp + 13; 127 sc->sci_iack = rp + 15; 128 sc->sci_irecv = rp + 15; 129 130 sc->dma_xfer_in = mlhsc_dma_xfer_in; 131 sc->dma_xfer_out = mlhsc_dma_xfer_out; 132 133 scireset(sc); 134 135 sc->sc_adapter.scsipi_cmd = sci_scsicmd; 136 sc->sc_adapter.scsipi_minphys = sci_minphys; 137 138 sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE; 139 sc->sc_link.adapter_softc = sc; 140 sc->sc_link.scsipi_scsi.adapter_target = 7; 141 sc->sc_link.adapter = &sc->sc_adapter; 142 sc->sc_link.device = &mlhsc_scsidev; 143 sc->sc_link.openings = 1; 144 sc->sc_link.scsipi_scsi.max_target = 7; 145 sc->sc_link.scsipi_scsi.max_lun = 7; 146 sc->sc_link.type = BUS_SCSI; 147 TAILQ_INIT(&sc->sc_xslist); 148 149 /* 150 * attach all scsi units on us 151 */ 152 config_found(dp, &sc->sc_link, scsiprint); 153 } 154 155 int 156 mlhsc_dma_xfer_in (dev, len, buf, phase) 157 struct sci_softc *dev; 158 int len; 159 register u_char *buf; 160 int phase; 161 { 162 int wait = sci_data_wait; 163 u_char csr; 164 volatile register u_char *sci_dma = dev->sci_data + 16; 165 volatile register u_char *sci_csr = dev->sci_csr; 166 #ifdef DEBUG 167 u_char *obp = buf; 168 #endif 169 170 csr = *dev->sci_bus_csr; 171 172 QPRINTF(("mlhdma_in %d, csr=%02x\n", len, csr)); 173 174 *dev->sci_tcmd = phase; 175 *dev->sci_mode |= SCI_MODE_DMA; 176 *dev->sci_icmd = 0; 177 *dev->sci_irecv = 0; 178 while (len > 128) { 179 wait = sci_data_wait; 180 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 181 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 182 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 183 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 184 || --wait < 0) { 185 #ifdef DEBUG 186 if (sci_debug) 187 printf("mlhdma_in fail: l%d i%x w%d\n", 188 len, csr, wait); 189 #endif 190 *dev->sci_mode &= ~SCI_MODE_DMA; 191 return 0; 192 } 193 } 194 195 #define R1 (*buf++ = *sci_dma) 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 R1; R1; R1; R1; R1; R1; R1; R1; 212 len -= 128; 213 } 214 while (len > 0) { 215 wait = sci_data_wait; 216 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 217 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 218 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 219 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 220 || --wait < 0) { 221 #ifdef DEBUG 222 if (sci_debug) 223 printf("mlhdma_in fail: l%d i%x w%d\n", 224 len, csr, wait); 225 #endif 226 *dev->sci_mode &= ~SCI_MODE_DMA; 227 return 0; 228 } 229 } 230 231 *buf++ = *sci_dma; 232 len--; 233 } 234 235 QPRINTF(("mlhdma_in {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 236 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5], 237 obp[6], obp[7], obp[8], obp[9])); 238 239 *dev->sci_mode &= ~SCI_MODE_DMA; 240 return 0; 241 } 242 243 int 244 mlhsc_dma_xfer_out (dev, len, buf, phase) 245 struct sci_softc *dev; 246 int len; 247 register u_char *buf; 248 int phase; 249 { 250 int wait = sci_data_wait; 251 u_char csr; 252 volatile register u_char *sci_dma = dev->sci_data + 16; 253 volatile register u_char *sci_csr = dev->sci_csr; 254 255 csr = *dev->sci_bus_csr; 256 257 QPRINTF(("mlhdma_xfer %d, csr=%02x\n", len, csr)); 258 259 QPRINTF(("mlhgdma_out {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 260 len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], 261 buf[6], buf[7], buf[8], buf[9])); 262 263 *dev->sci_tcmd = phase; 264 *dev->sci_mode |= SCI_MODE_DMA; 265 *dev->sci_icmd = SCI_ICMD_DATA; 266 *dev->sci_dma_send = 0; 267 while (len > 64) { 268 wait = sci_data_wait; 269 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 270 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 271 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 272 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 273 || --wait < 0) { 274 #ifdef DEBUG 275 if (sci_debug) 276 printf("mlhdma_out fail: l%d i%x w%d\n", 277 len, csr, wait); 278 #endif 279 *dev->sci_mode &= ~SCI_MODE_DMA; 280 return 0; 281 } 282 } 283 284 #define W1 (*sci_dma = *buf++) 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 W1; W1; W1; W1; W1; W1; W1; W1; 290 W1; W1; W1; W1; W1; W1; W1; W1; 291 W1; W1; W1; W1; W1; W1; W1; W1; 292 W1; W1; W1; W1; W1; W1; W1; W1; 293 len -= 64; 294 } 295 while (len > 0) { 296 wait = sci_data_wait; 297 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) != 298 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) { 299 if (!(*sci_csr & SCI_CSR_PHASE_MATCH) 300 || !(*dev->sci_bus_csr & SCI_BUS_BSY) 301 || --wait < 0) { 302 #ifdef DEBUG 303 if (sci_debug) 304 printf("mlhdma_out fail: l%d i%x w%d\n", 305 len, csr, wait); 306 #endif 307 *dev->sci_mode &= ~SCI_MODE_DMA; 308 return 0; 309 } 310 } 311 312 *sci_dma = *buf++; 313 len--; 314 } 315 316 wait = sci_data_wait; 317 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) == 318 SCI_CSR_PHASE_MATCH && --wait); 319 320 *dev->sci_mode &= ~SCI_MODE_DMA; 321 return 0; 322 } 323