1 1.29 thorpej /* $NetBSD: tcds.c,v 1.29 2022/09/25 21:28:51 thorpej Exp $ */ 2 1.1 nisimura 3 1.1 nisimura /*- 4 1.1 nisimura * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 1.1 nisimura * All rights reserved. 6 1.1 nisimura * 7 1.1 nisimura * This code is derived from software contributed to The NetBSD Foundation 8 1.1 nisimura * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 1.1 nisimura * NASA Ames Research Center. 10 1.1 nisimura * 11 1.1 nisimura * Redistribution and use in source and binary forms, with or without 12 1.1 nisimura * modification, are permitted provided that the following conditions 13 1.1 nisimura * are met: 14 1.1 nisimura * 1. Redistributions of source code must retain the above copyright 15 1.1 nisimura * notice, this list of conditions and the following disclaimer. 16 1.1 nisimura * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 nisimura * notice, this list of conditions and the following disclaimer in the 18 1.1 nisimura * documentation and/or other materials provided with the distribution. 19 1.1 nisimura * 20 1.1 nisimura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 nisimura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 nisimura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 nisimura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 nisimura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 nisimura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 nisimura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 nisimura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 nisimura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 nisimura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 nisimura * POSSIBILITY OF SUCH DAMAGE. 31 1.1 nisimura */ 32 1.1 nisimura 33 1.1 nisimura /* 34 1.1 nisimura * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 35 1.1 nisimura * All rights reserved. 36 1.1 nisimura * 37 1.1 nisimura * Author: Keith Bostic, Chris G. Demetriou 38 1.14 perry * 39 1.1 nisimura * Permission to use, copy, modify and distribute this software and 40 1.1 nisimura * its documentation is hereby granted, provided that both the copyright 41 1.1 nisimura * notice and this permission notice appear in all copies of the 42 1.1 nisimura * software, derivative works or modified versions, and any portions 43 1.1 nisimura * thereof, and that both notices appear in supporting documentation. 44 1.14 perry * 45 1.14 perry * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 46 1.14 perry * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 47 1.1 nisimura * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 48 1.14 perry * 49 1.1 nisimura * Carnegie Mellon requests users of this software to return to 50 1.1 nisimura * 51 1.1 nisimura * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 52 1.1 nisimura * School of Computer Science 53 1.1 nisimura * Carnegie Mellon University 54 1.1 nisimura * Pittsburgh PA 15213-3890 55 1.1 nisimura * 56 1.1 nisimura * any improvements or extensions that they make and grant Carnegie the 57 1.1 nisimura * rights to redistribute these changes. 58 1.1 nisimura */ 59 1.1 nisimura 60 1.3 lukem #include <sys/cdefs.h> 61 1.29 thorpej __KERNEL_RCSID(0, "$NetBSD: tcds.c,v 1.29 2022/09/25 21:28:51 thorpej Exp $"); 62 1.1 nisimura 63 1.1 nisimura #include <sys/param.h> 64 1.1 nisimura #include <sys/kernel.h> 65 1.1 nisimura #include <sys/systm.h> 66 1.1 nisimura #include <sys/device.h> 67 1.1 nisimura 68 1.1 nisimura #ifdef __alpha__ 69 1.1 nisimura #include <machine/rpb.h> 70 1.1 nisimura #endif /* __alpha__ */ 71 1.1 nisimura 72 1.1 nisimura #include <dev/scsipi/scsi_all.h> 73 1.1 nisimura #include <dev/scsipi/scsipi_all.h> 74 1.1 nisimura #include <dev/scsipi/scsiconf.h> 75 1.1 nisimura 76 1.1 nisimura #include <dev/ic/ncr53c9xvar.h> 77 1.1 nisimura 78 1.20 ad #include <sys/bus.h> 79 1.1 nisimura 80 1.1 nisimura #include <dev/tc/tcvar.h> 81 1.1 nisimura #include <dev/tc/tcdsreg.h> 82 1.1 nisimura #include <dev/tc/tcdsvar.h> 83 1.1 nisimura 84 1.1 nisimura #include "locators.h" 85 1.1 nisimura 86 1.1 nisimura struct tcds_softc { 87 1.23 joerg device_t sc_dev; 88 1.1 nisimura bus_space_tag_t sc_bst; 89 1.1 nisimura bus_space_handle_t sc_bsh; 90 1.1 nisimura bus_dma_tag_t sc_dmat; 91 1.1 nisimura void *sc_cookie; 92 1.1 nisimura int sc_flags; 93 1.1 nisimura struct tcds_slotconfig sc_slots[2]; 94 1.1 nisimura }; 95 1.1 nisimura 96 1.1 nisimura /* sc_flags */ 97 1.1 nisimura #define TCDSF_BASEBOARD 0x01 /* baseboard on DEC 3000 */ 98 1.1 nisimura #define TCDSF_FASTSCSI 0x02 /* supports Fast SCSI */ 99 1.1 nisimura 100 1.1 nisimura /* Definition of the driver for autoconfig. */ 101 1.23 joerg static int tcdsmatch(device_t, cfdata_t, void *); 102 1.23 joerg static void tcdsattach(device_t, device_t, void *); 103 1.19 thorpej static int tcdsprint(void *, const char *); 104 1.1 nisimura 105 1.23 joerg CFATTACH_DECL_NEW(tcds, sizeof(struct tcds_softc), 106 1.9 thorpej tcdsmatch, tcdsattach, NULL, NULL); 107 1.1 nisimura 108 1.13 perry /*static*/ int tcds_intr(void *); 109 1.13 perry /*static*/ int tcds_intrnull(void *); 110 1.1 nisimura 111 1.19 thorpej static const struct tcds_device { 112 1.1 nisimura const char *td_name; 113 1.1 nisimura int td_flags; 114 1.1 nisimura } tcds_devices[] = { 115 1.1 nisimura #ifdef __alpha__ 116 1.1 nisimura { "PMAZ-DS ", TCDSF_BASEBOARD }, 117 1.1 nisimura { "PMAZ-FS ", TCDSF_BASEBOARD|TCDSF_FASTSCSI }, 118 1.1 nisimura #endif /* __alpha__ */ 119 1.1 nisimura { "PMAZB-AA", 0 }, 120 1.1 nisimura { "PMAZC-AA", TCDSF_FASTSCSI }, 121 1.1 nisimura { NULL, 0 }, 122 1.1 nisimura }; 123 1.1 nisimura 124 1.19 thorpej static void tcds_params(struct tcds_softc *, int, int *, int *); 125 1.1 nisimura 126 1.19 thorpej static const struct tcds_device * 127 1.19 thorpej tcds_lookup(const char *modname) 128 1.1 nisimura { 129 1.19 thorpej const struct tcds_device *td; 130 1.1 nisimura 131 1.1 nisimura for (td = tcds_devices; td->td_name != NULL; td++) 132 1.1 nisimura if (strncmp(td->td_name, modname, TC_ROM_LLEN) == 0) 133 1.1 nisimura return (td); 134 1.1 nisimura 135 1.1 nisimura return (NULL); 136 1.1 nisimura } 137 1.1 nisimura 138 1.19 thorpej static int 139 1.23 joerg tcdsmatch(device_t parent, cfdata_t cfdata, void *aux) 140 1.1 nisimura { 141 1.1 nisimura struct tc_attach_args *ta = aux; 142 1.1 nisimura 143 1.1 nisimura return (tcds_lookup(ta->ta_modname) != NULL); 144 1.1 nisimura } 145 1.1 nisimura 146 1.19 thorpej static void 147 1.23 joerg tcdsattach(device_t parent, device_t self, void *aux) 148 1.1 nisimura { 149 1.18 thorpej struct tcds_softc *sc = device_private(self); 150 1.1 nisimura struct tc_attach_args *ta = aux; 151 1.1 nisimura struct tcdsdev_attach_args tcdsdev; 152 1.1 nisimura struct tcds_slotconfig *slotc; 153 1.19 thorpej const struct tcds_device *td; 154 1.1 nisimura bus_space_handle_t sbsh[2]; 155 1.1 nisimura int i, gpi2; 156 1.1 nisimura const struct evcnt *pevcnt; 157 1.15 drochner int locs[TCDSCF_NLOCS]; 158 1.1 nisimura 159 1.23 joerg sc->sc_dev = self; 160 1.23 joerg 161 1.1 nisimura td = tcds_lookup(ta->ta_modname); 162 1.1 nisimura if (td == NULL) 163 1.1 nisimura panic("\ntcdsattach: impossible"); 164 1.1 nisimura 165 1.26 flxd printf(": TURBOchannel Dual SCSI"); 166 1.1 nisimura if (td->td_flags & TCDSF_BASEBOARD) 167 1.1 nisimura printf(" (baseboard)"); 168 1.1 nisimura printf("\n"); 169 1.1 nisimura 170 1.1 nisimura sc->sc_flags = td->td_flags; 171 1.1 nisimura 172 1.1 nisimura sc->sc_bst = ta->ta_memt; 173 1.1 nisimura sc->sc_dmat = ta->ta_dmat; 174 1.1 nisimura 175 1.1 nisimura /* 176 1.1 nisimura * Map the device. 177 1.1 nisimura */ 178 1.1 nisimura if (bus_space_map(sc->sc_bst, ta->ta_addr, 179 1.1 nisimura (TCDS_SCSI1_OFFSET + 0x100), 0, &sc->sc_bsh)) { 180 1.23 joerg aprint_error_dev(self, "unable to map device\n"); 181 1.1 nisimura return; 182 1.1 nisimura } 183 1.1 nisimura 184 1.1 nisimura /* 185 1.1 nisimura * Now, slice off two subregions for the individual NCR SCSI chips. 186 1.1 nisimura */ 187 1.1 nisimura if (bus_space_subregion(sc->sc_bst, sc->sc_bsh, TCDS_SCSI0_OFFSET, 188 1.1 nisimura 0x100, &sbsh[0]) || 189 1.1 nisimura bus_space_subregion(sc->sc_bst, sc->sc_bsh, TCDS_SCSI1_OFFSET, 190 1.1 nisimura 0x100, &sbsh[1])) { 191 1.23 joerg aprint_error_dev(self, "unable to subregion SCSI chip space\n"); 192 1.1 nisimura return; 193 1.1 nisimura } 194 1.1 nisimura 195 1.1 nisimura sc->sc_cookie = ta->ta_cookie; 196 1.1 nisimura 197 1.1 nisimura pevcnt = tc_intr_evcnt(parent, sc->sc_cookie); 198 1.1 nisimura tc_intr_establish(parent, sc->sc_cookie, TC_IPL_BIO, tcds_intr, sc); 199 1.1 nisimura 200 1.1 nisimura /* 201 1.1 nisimura * XXX 202 1.1 nisimura * IMER apparently has some random (or, not so random, but still 203 1.1 nisimura * not useful) bits set in it when the system boots. Clear it. 204 1.1 nisimura */ 205 1.1 nisimura bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_IMER, 0); 206 1.1 nisimura 207 1.1 nisimura /* XXX Initial contents of CIR? */ 208 1.1 nisimura 209 1.1 nisimura /* 210 1.1 nisimura * Remember if GPI2 is set in the CIR; we'll need it later. 211 1.1 nisimura */ 212 1.1 nisimura gpi2 = (bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR) & 213 1.1 nisimura TCDS_CIR_GPI_2) != 0; 214 1.1 nisimura 215 1.1 nisimura /* 216 1.7 wiz * Set up the per-slot definitions for later use. 217 1.1 nisimura */ 218 1.1 nisimura 219 1.1 nisimura /* fill in common information first */ 220 1.1 nisimura for (i = 0; i < 2; i++) { 221 1.2 nisimura char *cp; 222 1.2 nisimura 223 1.1 nisimura slotc = &sc->sc_slots[i]; 224 1.24 cegger memset(slotc, 0, sizeof *slotc); /* clear everything */ 225 1.1 nisimura 226 1.2 nisimura cp = slotc->sc_name; 227 1.2 nisimura snprintf(cp, sizeof(slotc->sc_name), "chip %d", i); 228 1.1 nisimura evcnt_attach_dynamic(&slotc->sc_evcnt, EVCNT_TYPE_INTR, 229 1.23 joerg pevcnt, device_xname(self), cp); 230 1.1 nisimura 231 1.1 nisimura slotc->sc_slot = i; 232 1.1 nisimura slotc->sc_bst = sc->sc_bst; 233 1.1 nisimura slotc->sc_bsh = sc->sc_bsh; 234 1.1 nisimura slotc->sc_intrhand = tcds_intrnull; 235 1.1 nisimura slotc->sc_intrarg = (void *)(long)i; 236 1.1 nisimura } 237 1.1 nisimura 238 1.1 nisimura /* information for slot 0 */ 239 1.1 nisimura slotc = &sc->sc_slots[0]; 240 1.1 nisimura slotc->sc_resetbits = TCDS_CIR_SCSI0_RESET; 241 1.1 nisimura slotc->sc_intrmaskbits = 242 1.1 nisimura TCDS_IMER_SCSI0_MASK | TCDS_IMER_SCSI0_ENB; 243 1.1 nisimura slotc->sc_intrbits = TCDS_CIR_SCSI0_INT; 244 1.1 nisimura slotc->sc_dmabits = TCDS_CIR_SCSI0_DMAENA; 245 1.1 nisimura slotc->sc_errorbits = 0; /* XXX */ 246 1.1 nisimura slotc->sc_sda = TCDS_SCSI0_DMA_ADDR; 247 1.1 nisimura slotc->sc_dic = TCDS_SCSI0_DMA_INTR; 248 1.1 nisimura slotc->sc_dud0 = TCDS_SCSI0_DMA_DUD0; 249 1.1 nisimura slotc->sc_dud1 = TCDS_SCSI0_DMA_DUD1; 250 1.1 nisimura 251 1.1 nisimura /* information for slot 1 */ 252 1.1 nisimura slotc = &sc->sc_slots[1]; 253 1.1 nisimura slotc->sc_resetbits = TCDS_CIR_SCSI1_RESET; 254 1.1 nisimura slotc->sc_intrmaskbits = 255 1.1 nisimura TCDS_IMER_SCSI1_MASK | TCDS_IMER_SCSI1_ENB; 256 1.1 nisimura slotc->sc_intrbits = TCDS_CIR_SCSI1_INT; 257 1.1 nisimura slotc->sc_dmabits = TCDS_CIR_SCSI1_DMAENA; 258 1.1 nisimura slotc->sc_errorbits = 0; /* XXX */ 259 1.1 nisimura slotc->sc_sda = TCDS_SCSI1_DMA_ADDR; 260 1.1 nisimura slotc->sc_dic = TCDS_SCSI1_DMA_INTR; 261 1.1 nisimura slotc->sc_dud0 = TCDS_SCSI1_DMA_DUD0; 262 1.1 nisimura slotc->sc_dud1 = TCDS_SCSI1_DMA_DUD1; 263 1.1 nisimura 264 1.1 nisimura /* find the hardware attached to the TCDS ASIC */ 265 1.1 nisimura for (i = 0; i < 2; i++) { 266 1.1 nisimura tcds_params(sc, i, &tcdsdev.tcdsda_id, 267 1.1 nisimura &tcdsdev.tcdsda_fast); 268 1.1 nisimura 269 1.1 nisimura tcdsdev.tcdsda_bst = sc->sc_bst; 270 1.1 nisimura tcdsdev.tcdsda_bsh = sbsh[i]; 271 1.1 nisimura tcdsdev.tcdsda_dmat = sc->sc_dmat; 272 1.1 nisimura tcdsdev.tcdsda_chip = i; 273 1.1 nisimura tcdsdev.tcdsda_sc = &sc->sc_slots[i]; 274 1.1 nisimura /* 275 1.1 nisimura * Determine the chip frequency. TCDSF_FASTSCSI will be set 276 1.1 nisimura * for TC option cards. For baseboard chips, GPI2 is set, for a 277 1.1 nisimura * 25MHz clock, else a 40MHz clock. 278 1.1 nisimura */ 279 1.1 nisimura if ((sc->sc_flags & TCDSF_BASEBOARD && gpi2 == 0) || 280 1.1 nisimura sc->sc_flags & TCDSF_FASTSCSI) { 281 1.1 nisimura tcdsdev.tcdsda_freq = 40000000; 282 1.1 nisimura tcdsdev.tcdsda_period = tcdsdev.tcdsda_fast ? 4 : 8; 283 1.1 nisimura } else { 284 1.1 nisimura tcdsdev.tcdsda_freq = 25000000; 285 1.1 nisimura tcdsdev.tcdsda_period = 5; 286 1.1 nisimura } 287 1.1 nisimura if (sc->sc_flags & TCDSF_BASEBOARD) 288 1.1 nisimura tcdsdev.tcdsda_variant = NCR_VARIANT_NCR53C94; 289 1.1 nisimura else 290 1.1 nisimura tcdsdev.tcdsda_variant = NCR_VARIANT_NCR53C96; 291 1.1 nisimura 292 1.1 nisimura tcds_scsi_reset(tcdsdev.tcdsda_sc); 293 1.1 nisimura 294 1.15 drochner locs[TCDSCF_CHIP] = i; 295 1.11 drochner 296 1.27 thorpej config_found(self, &tcdsdev, tcdsprint, 297 1.28 thorpej CFARGS(.submatch = config_stdsubmatch, 298 1.28 thorpej .locators = locs)); 299 1.1 nisimura #ifdef __alpha__ 300 1.1 nisimura /* 301 1.1 nisimura * The second SCSI chip isn't present on the baseboard TCDS 302 1.1 nisimura * on the DEC Alpha 3000/300 series. 303 1.1 nisimura */ 304 1.1 nisimura if (sc->sc_flags & TCDSF_BASEBOARD && 305 1.1 nisimura cputype == ST_DEC_3000_300) 306 1.1 nisimura break; 307 1.1 nisimura #endif /* __alpha__ */ 308 1.1 nisimura } 309 1.1 nisimura } 310 1.1 nisimura 311 1.19 thorpej static int 312 1.19 thorpej tcdsprint(void *aux, const char *pnp) 313 1.1 nisimura { 314 1.1 nisimura struct tcdsdev_attach_args *tcdsdev = aux; 315 1.1 nisimura 316 1.1 nisimura /* Only ASCs can attach to TCDSs; easy. */ 317 1.1 nisimura if (pnp) 318 1.10 thorpej aprint_normal("asc at %s", pnp); 319 1.1 nisimura 320 1.10 thorpej aprint_normal(" chip %d", tcdsdev->tcdsda_chip); 321 1.1 nisimura 322 1.1 nisimura return (UNCONF); 323 1.1 nisimura } 324 1.1 nisimura 325 1.1 nisimura void 326 1.23 joerg tcds_intr_establish(device_t tcds, int slot, int (*func)(void *), 327 1.19 thorpej void *arg) 328 1.1 nisimura { 329 1.19 thorpej struct tcds_softc *sc = device_private(tcds); 330 1.1 nisimura 331 1.1 nisimura if (sc->sc_slots[slot].sc_intrhand != tcds_intrnull) 332 1.1 nisimura panic("tcds_intr_establish: chip %d twice", slot); 333 1.1 nisimura 334 1.1 nisimura sc->sc_slots[slot].sc_intrhand = func; 335 1.1 nisimura sc->sc_slots[slot].sc_intrarg = arg; 336 1.1 nisimura tcds_scsi_reset(&sc->sc_slots[slot]); 337 1.1 nisimura } 338 1.1 nisimura 339 1.1 nisimura void 340 1.23 joerg tcds_intr_disestablish(device_t tcds, int slot) 341 1.1 nisimura { 342 1.19 thorpej struct tcds_softc *sc = device_private(tcds); 343 1.1 nisimura 344 1.1 nisimura if (sc->sc_slots[slot].sc_intrhand == tcds_intrnull) 345 1.1 nisimura panic("tcds_intr_disestablish: chip %d missing intr", 346 1.1 nisimura slot); 347 1.1 nisimura 348 1.1 nisimura sc->sc_slots[slot].sc_intrhand = tcds_intrnull; 349 1.1 nisimura sc->sc_slots[slot].sc_intrarg = (void *)(u_long)slot; 350 1.1 nisimura 351 1.1 nisimura tcds_dma_enable(&sc->sc_slots[slot], 0); 352 1.1 nisimura tcds_scsi_enable(&sc->sc_slots[slot], 0); 353 1.1 nisimura } 354 1.1 nisimura 355 1.1 nisimura int 356 1.19 thorpej tcds_intrnull(void *val) 357 1.1 nisimura { 358 1.1 nisimura 359 1.5 provos panic("tcds_intrnull: uncaught TCDS intr for chip %lu", 360 1.1 nisimura (u_long)val); 361 1.1 nisimura } 362 1.1 nisimura 363 1.1 nisimura void 364 1.19 thorpej tcds_scsi_reset(struct tcds_slotconfig *sc) 365 1.1 nisimura { 366 1.25 tsutsui uint32_t cir; 367 1.1 nisimura 368 1.1 nisimura tcds_dma_enable(sc, 0); 369 1.1 nisimura tcds_scsi_enable(sc, 0); 370 1.1 nisimura 371 1.1 nisimura cir = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); 372 1.1 nisimura TCDS_CIR_CLR(cir, sc->sc_resetbits); 373 1.1 nisimura bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR, cir); 374 1.1 nisimura 375 1.1 nisimura DELAY(1); 376 1.1 nisimura 377 1.1 nisimura cir = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); 378 1.1 nisimura TCDS_CIR_SET(cir, sc->sc_resetbits); 379 1.1 nisimura bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR, cir); 380 1.1 nisimura 381 1.1 nisimura tcds_scsi_enable(sc, 1); 382 1.1 nisimura tcds_dma_enable(sc, 1); 383 1.1 nisimura } 384 1.1 nisimura 385 1.1 nisimura void 386 1.19 thorpej tcds_scsi_enable(struct tcds_slotconfig *sc, int on) 387 1.1 nisimura { 388 1.25 tsutsui uint32_t imer; 389 1.1 nisimura 390 1.1 nisimura imer = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_IMER); 391 1.1 nisimura 392 1.1 nisimura if (on) 393 1.1 nisimura imer |= sc->sc_intrmaskbits; 394 1.1 nisimura else 395 1.1 nisimura imer &= ~sc->sc_intrmaskbits; 396 1.1 nisimura 397 1.1 nisimura bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_IMER, imer); 398 1.1 nisimura } 399 1.1 nisimura 400 1.1 nisimura void 401 1.19 thorpej tcds_dma_enable(struct tcds_slotconfig *sc, int on) 402 1.1 nisimura { 403 1.25 tsutsui uint32_t cir; 404 1.1 nisimura 405 1.1 nisimura cir = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); 406 1.1 nisimura 407 1.1 nisimura /* XXX Clear/set IOSLOT/PBS bits. */ 408 1.14 perry if (on) 409 1.1 nisimura TCDS_CIR_SET(cir, sc->sc_dmabits); 410 1.1 nisimura else 411 1.1 nisimura TCDS_CIR_CLR(cir, sc->sc_dmabits); 412 1.1 nisimura 413 1.1 nisimura bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR, cir); 414 1.1 nisimura } 415 1.1 nisimura 416 1.1 nisimura int 417 1.19 thorpej tcds_scsi_isintr(struct tcds_slotconfig *sc, int clear) 418 1.1 nisimura { 419 1.25 tsutsui uint32_t cir; 420 1.1 nisimura 421 1.1 nisimura cir = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); 422 1.1 nisimura 423 1.1 nisimura if ((cir & sc->sc_intrbits) != 0) { 424 1.1 nisimura if (clear) { 425 1.1 nisimura TCDS_CIR_CLR(cir, sc->sc_intrbits); 426 1.1 nisimura bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR, 427 1.1 nisimura cir); 428 1.1 nisimura } 429 1.1 nisimura return (1); 430 1.1 nisimura } else 431 1.1 nisimura return (0); 432 1.1 nisimura } 433 1.1 nisimura 434 1.1 nisimura int 435 1.19 thorpej tcds_scsi_iserr(struct tcds_slotconfig *sc) 436 1.1 nisimura { 437 1.25 tsutsui uint32_t cir; 438 1.1 nisimura 439 1.1 nisimura cir = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); 440 1.1 nisimura return ((cir & sc->sc_errorbits) != 0); 441 1.1 nisimura } 442 1.1 nisimura 443 1.1 nisimura int 444 1.19 thorpej tcds_intr(void *arg) 445 1.1 nisimura { 446 1.1 nisimura struct tcds_softc *sc = arg; 447 1.25 tsutsui uint32_t ir, ir0; 448 1.1 nisimura 449 1.1 nisimura /* 450 1.1 nisimura * XXX 451 1.1 nisimura * Copy and clear (gag!) the interrupts. 452 1.1 nisimura */ 453 1.1 nisimura ir = ir0 = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR); 454 1.1 nisimura TCDS_CIR_CLR(ir0, TCDS_CIR_ALLINTR); 455 1.1 nisimura bus_space_write_4(sc->sc_bst, sc->sc_bsh, TCDS_CIR, ir0); 456 1.1 nisimura tc_syncbus(); 457 1.1 nisimura 458 1.1 nisimura #define INCRINTRCNT(slot) sc->sc_slots[slot].sc_evcnt.ev_count++ 459 1.1 nisimura 460 1.1 nisimura #define CHECKINTR(slot) \ 461 1.1 nisimura if (ir & sc->sc_slots[slot].sc_intrbits) { \ 462 1.1 nisimura INCRINTRCNT(slot); \ 463 1.1 nisimura (void)(*sc->sc_slots[slot].sc_intrhand) \ 464 1.1 nisimura (sc->sc_slots[slot].sc_intrarg); \ 465 1.1 nisimura } 466 1.1 nisimura CHECKINTR(0); 467 1.1 nisimura CHECKINTR(1); 468 1.1 nisimura #undef CHECKINTR 469 1.1 nisimura 470 1.1 nisimura #ifdef DIAGNOSTIC 471 1.14 perry /* 472 1.1 nisimura * Interrupts not currently handled, but would like to know if they 473 1.1 nisimura * occur. 474 1.1 nisimura * 475 1.1 nisimura * XXX 476 1.1 nisimura * Don't know if we have to set the interrupt mask and enable bits 477 1.1 nisimura * in the IMER to allow some of them to happen? 478 1.1 nisimura */ 479 1.1 nisimura #define PRINTINTR(msg, bits) \ 480 1.1 nisimura if (ir & bits) \ 481 1.23 joerg printf("%s: %s", device_xname(sc->sc_dev), msg); 482 1.1 nisimura PRINTINTR("SCSI0 DREQ interrupt.\n", TCDS_CIR_SCSI0_DREQ); 483 1.1 nisimura PRINTINTR("SCSI1 DREQ interrupt.\n", TCDS_CIR_SCSI1_DREQ); 484 1.1 nisimura PRINTINTR("SCSI0 prefetch interrupt.\n", TCDS_CIR_SCSI0_PREFETCH); 485 1.1 nisimura PRINTINTR("SCSI1 prefetch interrupt.\n", TCDS_CIR_SCSI1_PREFETCH); 486 1.1 nisimura PRINTINTR("SCSI0 DMA error.\n", TCDS_CIR_SCSI0_DMA); 487 1.1 nisimura PRINTINTR("SCSI1 DMA error.\n", TCDS_CIR_SCSI1_DMA); 488 1.1 nisimura PRINTINTR("SCSI0 DB parity error.\n", TCDS_CIR_SCSI0_DB); 489 1.1 nisimura PRINTINTR("SCSI1 DB parity error.\n", TCDS_CIR_SCSI1_DB); 490 1.1 nisimura PRINTINTR("SCSI0 DMA buffer parity error.\n", TCDS_CIR_SCSI0_DMAB_PAR); 491 1.1 nisimura PRINTINTR("SCSI1 DMA buffer parity error.\n", TCDS_CIR_SCSI1_DMAB_PAR); 492 1.1 nisimura PRINTINTR("SCSI0 DMA read parity error.\n", TCDS_CIR_SCSI0_DMAR_PAR); 493 1.1 nisimura PRINTINTR("SCSI1 DMA read parity error.\n", TCDS_CIR_SCSI1_DMAR_PAR); 494 1.1 nisimura PRINTINTR("TC write parity error.\n", TCDS_CIR_TCIOW_PAR); 495 1.1 nisimura PRINTINTR("TC I/O address parity error.\n", TCDS_CIR_TCIOA_PAR); 496 1.1 nisimura #undef PRINTINTR 497 1.1 nisimura #endif 498 1.1 nisimura 499 1.1 nisimura /* 500 1.1 nisimura * XXX 501 1.1 nisimura * The MACH source had this, with the comment: 502 1.1 nisimura * This is wrong, but machine keeps dying. 503 1.1 nisimura */ 504 1.1 nisimura DELAY(1); 505 1.1 nisimura 506 1.1 nisimura return (1); 507 1.1 nisimura } 508 1.1 nisimura 509 1.19 thorpej static void 510 1.19 thorpej tcds_params(struct tcds_softc *sc, int chip, int *idp, int *fastp) 511 1.1 nisimura { 512 1.1 nisimura int id, fast; 513 1.25 tsutsui uint32_t ids; 514 1.1 nisimura 515 1.1 nisimura #ifdef __alpha__ 516 1.1 nisimura if (sc->sc_flags & TCDSF_BASEBOARD) { 517 1.25 tsutsui extern uint8_t dec_3000_scsiid[], dec_3000_scsifast[]; 518 1.1 nisimura 519 1.1 nisimura id = dec_3000_scsiid[chip]; 520 1.1 nisimura fast = dec_3000_scsifast[chip]; 521 1.1 nisimura } else 522 1.1 nisimura #endif /* __alpha__ */ 523 1.1 nisimura { 524 1.1 nisimura /* 525 1.1 nisimura * SCSI IDs are stored in the EEPROM, along with whether or 526 1.1 nisimura * not the device is "fast". Chip 0 is the high nibble, 527 1.1 nisimura * chip 1 the low nibble. 528 1.1 nisimura */ 529 1.1 nisimura ids = bus_space_read_4(sc->sc_bst, sc->sc_bsh, TCDS_EEPROM_IDS); 530 1.1 nisimura if (chip == 0) 531 1.1 nisimura ids >>= 4; 532 1.1 nisimura 533 1.1 nisimura id = ids & 0x7; 534 1.1 nisimura fast = ids & 0x8; 535 1.1 nisimura } 536 1.1 nisimura 537 1.1 nisimura if (id < 0 || id > 7) { 538 1.1 nisimura printf("%s: WARNING: bad SCSI ID %d for chip %d, using 7\n", 539 1.23 joerg device_xname(sc->sc_dev), id, chip); 540 1.1 nisimura id = 7; 541 1.1 nisimura } 542 1.1 nisimura 543 1.1 nisimura if (fast) 544 1.1 nisimura printf("%s: fast mode set for chip %d\n", 545 1.23 joerg device_xname(sc->sc_dev), chip); 546 1.1 nisimura 547 1.1 nisimura *idp = id; 548 1.1 nisimura *fastp = fast; 549 1.1 nisimura } 550