1 /* $NetBSD: sbc_obio.c,v 1.14 2001/04/25 17:53:15 bouyer Exp $ */ 2 3 /* 4 * Copyright (C) 1996,1997 Scott Reynolds. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/types.h> 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/errno.h> 34 #include <sys/device.h> 35 #include <sys/buf.h> 36 #include <sys/proc.h> 37 #include <sys/user.h> 38 39 #include <dev/scsipi/scsi_all.h> 40 #include <dev/scsipi/scsipi_all.h> 41 #include <dev/scsipi/scsipi_debug.h> 42 #include <dev/scsipi/scsiconf.h> 43 44 #include <dev/ic/ncr5380reg.h> 45 #include <dev/ic/ncr5380var.h> 46 47 #include <machine/cpu.h> 48 #include <machine/viareg.h> 49 50 #include <mac68k/dev/sbcreg.h> 51 #include <mac68k/dev/sbcvar.h> 52 53 /* 54 * From Guide to the Macintosh Family Hardware, pp. 137-143 55 * These are offsets from SCSIBase (see pmap_bootstrap.c) 56 */ 57 #define SBC_REG_OFS 0x10000 58 #define SBC_DMA_OFS 0x12000 59 #define SBC_HSK_OFS 0x06000 60 61 #define SBC_DMA_OFS_PB500 0x06000 62 63 #define SBC_REG_OFS_IIFX 0x08000 /* Just guessing... */ 64 #define SBC_DMA_OFS_IIFX 0x0c000 65 #define SBC_HSK_OFS_IIFX 0x0e000 66 67 #define SBC_REG_OFS_DUO2 0x00000 68 #define SBC_DMA_OFS_DUO2 0x02000 69 #define SBC_HSK_OFS_DUO2 0x04000 70 71 static int sbc_obio_match __P((struct device *, struct cfdata *, void *)); 72 static void sbc_obio_attach __P((struct device *, struct device *, void *)); 73 74 void sbc_intr_enable __P((struct ncr5380_softc *)); 75 void sbc_intr_disable __P((struct ncr5380_softc *)); 76 void sbc_obio_clrintr __P((struct ncr5380_softc *)); 77 78 struct cfattach sbc_obio_ca = { 79 sizeof(struct sbc_softc), sbc_obio_match, sbc_obio_attach 80 }; 81 82 static int 83 sbc_obio_match(parent, cf, args) 84 struct device *parent; 85 struct cfdata *cf; 86 void *args; 87 { 88 switch (current_mac_model->machineid) { 89 case MACH_MACIIFX: /* Note: the IIfx isn't (yet) supported. */ 90 /* 91 if (cf->cf_unit == 0) 92 return 1; 93 */ 94 break; 95 case MACH_MACPB210: 96 case MACH_MACPB230: 97 case MACH_MACPB250: 98 case MACH_MACPB270: 99 case MACH_MACPB280: 100 case MACH_MACPB280C: 101 if (cf->cf_unit == 1) 102 return 1; 103 /*FALLTHROUGH*/ 104 default: 105 if (cf->cf_unit == 0 && mac68k_machine.scsi80) 106 return 1; 107 } 108 return 0; 109 } 110 111 static void 112 sbc_obio_attach(parent, self, args) 113 struct device *parent, *self; 114 void *args; 115 { 116 struct sbc_softc *sc = (struct sbc_softc *) self; 117 struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *) sc; 118 char bits[64]; 119 extern vaddr_t SCSIBase; 120 121 /* Pull in the options flags. */ 122 sc->sc_options = ((ncr_sc->sc_dev.dv_cfdata->cf_flags | sbc_options) 123 & SBC_OPTIONS_MASK); 124 125 /* 126 * Set up offsets to 5380 registers and GLUE I/O space, and turn 127 * off options we know we can't support on certain models. 128 */ 129 switch (current_mac_model->machineid) { 130 case MACH_MACIIFX: /* Note: the IIfx isn't (yet) supported. */ 131 sc->sc_regs = (struct sbc_regs *)(SCSIBase + SBC_REG_OFS_IIFX); 132 sc->sc_drq_addr = (vaddr_t)(SCSIBase + SBC_HSK_OFS_IIFX); 133 sc->sc_nodrq_addr = (vaddr_t)(SCSIBase + SBC_DMA_OFS_IIFX); 134 sc->sc_options &= ~(SBC_INTR | SBC_RESELECT); 135 break; 136 case MACH_MACPB500: 137 sc->sc_regs = (struct sbc_regs *)(SCSIBase + SBC_REG_OFS); 138 sc->sc_drq_addr = (vaddr_t)(SCSIBase + SBC_HSK_OFS); /*??*/ 139 sc->sc_nodrq_addr = (vaddr_t)(SCSIBase + SBC_DMA_OFS_PB500); 140 sc->sc_options &= ~(SBC_INTR | SBC_RESELECT); 141 break; 142 case MACH_MACPB210: 143 case MACH_MACPB230: 144 case MACH_MACPB250: 145 case MACH_MACPB270: 146 case MACH_MACPB280: 147 case MACH_MACPB280C: 148 if (ncr_sc->sc_dev.dv_unit == 1) { 149 sc->sc_regs = (struct sbc_regs *)(0xfee00000 + SBC_REG_OFS_DUO2); 150 sc->sc_drq_addr = (vaddr_t)(0xfee00000 + SBC_HSK_OFS_DUO2); 151 sc->sc_nodrq_addr = (vaddr_t)(0xfee00000 + SBC_DMA_OFS_DUO2); 152 break; 153 } 154 /*FALLTHROUGH*/ 155 default: 156 sc->sc_regs = (struct sbc_regs *)(SCSIBase + SBC_REG_OFS); 157 sc->sc_drq_addr = (vaddr_t)(SCSIBase + SBC_HSK_OFS); 158 sc->sc_nodrq_addr = (vaddr_t)(SCSIBase + SBC_DMA_OFS); 159 break; 160 } 161 162 /* 163 * Initialize fields used by the MI code 164 */ 165 ncr_sc->sci_r0 = &sc->sc_regs->sci_pr0.sci_reg; 166 ncr_sc->sci_r1 = &sc->sc_regs->sci_pr1.sci_reg; 167 ncr_sc->sci_r2 = &sc->sc_regs->sci_pr2.sci_reg; 168 ncr_sc->sci_r3 = &sc->sc_regs->sci_pr3.sci_reg; 169 ncr_sc->sci_r4 = &sc->sc_regs->sci_pr4.sci_reg; 170 ncr_sc->sci_r5 = &sc->sc_regs->sci_pr5.sci_reg; 171 ncr_sc->sci_r6 = &sc->sc_regs->sci_pr6.sci_reg; 172 ncr_sc->sci_r7 = &sc->sc_regs->sci_pr7.sci_reg; 173 174 ncr_sc->sc_rev = NCR_VARIANT_NCR5380; 175 176 /* 177 * MD function pointers used by the MI code. 178 */ 179 if (sc->sc_options & SBC_PDMA) { 180 ncr_sc->sc_pio_out = sbc_pdma_out; 181 ncr_sc->sc_pio_in = sbc_pdma_in; 182 } else { 183 ncr_sc->sc_pio_out = ncr5380_pio_out; 184 ncr_sc->sc_pio_in = ncr5380_pio_in; 185 } 186 ncr_sc->sc_dma_alloc = NULL; 187 ncr_sc->sc_dma_free = NULL; 188 ncr_sc->sc_dma_poll = NULL; 189 ncr_sc->sc_intr_on = NULL; 190 ncr_sc->sc_intr_off = NULL; 191 ncr_sc->sc_dma_setup = NULL; 192 ncr_sc->sc_dma_start = NULL; 193 ncr_sc->sc_dma_eop = NULL; 194 ncr_sc->sc_dma_stop = NULL; 195 ncr_sc->sc_flags = 0; 196 ncr_sc->sc_min_dma_len = MIN_DMA_LEN; 197 198 if (sc->sc_options & SBC_INTR) { 199 ncr_sc->sc_dma_alloc = sbc_dma_alloc; 200 ncr_sc->sc_dma_free = sbc_dma_free; 201 ncr_sc->sc_dma_poll = sbc_dma_poll; 202 ncr_sc->sc_dma_setup = sbc_dma_setup; 203 ncr_sc->sc_dma_start = sbc_dma_start; 204 ncr_sc->sc_dma_eop = sbc_dma_eop; 205 ncr_sc->sc_dma_stop = sbc_dma_stop; 206 via2_register_irq(VIA2_SCSIDRQ, sbc_drq_intr, ncr_sc); 207 } 208 209 via2_register_irq(VIA2_SCSIIRQ, sbc_irq_intr, ncr_sc); 210 sc->sc_clrintr = sbc_obio_clrintr; 211 212 if ((sc->sc_options & SBC_RESELECT) == 0) 213 ncr_sc->sc_no_disconnect = 0xff; 214 215 if (sc->sc_options) 216 printf(": options=%s", bitmask_snprintf(sc->sc_options, 217 SBC_OPTIONS_BITS, bits, sizeof(bits))); 218 printf("\n"); 219 220 if (sc->sc_options & (SBC_INTR|SBC_RESELECT)) { 221 /* Enable SCSI interrupts through VIA2 */ 222 sbc_intr_enable(ncr_sc); 223 } 224 225 #ifdef SBC_DEBUG 226 if (sbc_debug) 227 printf("%s: softc=%p regs=%p\n", ncr_sc->sc_dev.dv_xname, 228 sc, sc->sc_regs); 229 #endif 230 231 ncr_sc->sc_channel.chan_id = 7; 232 ncr_sc->sc_adapter.adapt_minphys = minphys; 233 234 /* 235 * Initialize the SCSI controller itself. 236 */ 237 ncr5380_attach(ncr_sc); 238 } 239 240 /* 241 * Interrupt support routines. 242 */ 243 void 244 sbc_intr_enable(ncr_sc) 245 struct ncr5380_softc *ncr_sc; 246 { 247 struct sbc_softc *sc = (struct sbc_softc *)ncr_sc; 248 int s, flags; 249 250 flags = V2IF_SCSIIRQ; 251 if (sc->sc_options & SBC_INTR) 252 flags |= V2IF_SCSIDRQ; 253 254 s = splhigh(); 255 if (VIA2 == VIA2OFF) 256 via2_reg(vIER) = 0x80 | flags; 257 else 258 via2_reg(rIER) = 0x80 | flags; 259 splx(s); 260 } 261 262 void 263 sbc_intr_disable(ncr_sc) 264 struct ncr5380_softc *ncr_sc; 265 { 266 struct sbc_softc *sc = (struct sbc_softc *)ncr_sc; 267 int s, flags; 268 269 flags = V2IF_SCSIIRQ; 270 if (sc->sc_options & SBC_INTR) 271 flags |= V2IF_SCSIDRQ; 272 273 s = splhigh(); 274 if (VIA2 == VIA2OFF) 275 via2_reg(vIER) = flags; 276 else 277 via2_reg(rIER) = flags; 278 splx(s); 279 } 280 281 void 282 sbc_obio_clrintr(ncr_sc) 283 struct ncr5380_softc *ncr_sc; 284 { 285 struct sbc_softc *sc = (struct sbc_softc *)ncr_sc; 286 int flags; 287 288 flags = V2IF_SCSIIRQ; 289 if (sc->sc_options & SBC_INTR) 290 flags |= V2IF_SCSIDRQ; 291 292 if (VIA2 == VIA2OFF) 293 via2_reg(vIFR) = 0x80 | flags; 294 else 295 via2_reg(rIFR) = 0x80 | flags; 296 } 297