1 /* $NetBSD: asc_tc.c,v 1.8 1997/10/31 06:29:59 jonathan Exp $ */ 2 3 /* 4 * Copyright 1996 The Board of Trustees of The Leland Stanford 5 * Junior University. All Rights Reserved. 6 * 7 * Permission to use, copy, modify, and distribute this 8 * software and its documentation for any purpose and without 9 * fee is hereby granted, provided that the above copyright 10 * notice appear in all copies. Stanford University 11 * makes no representations about the suitability of this 12 * software for any purpose. It is provided "as is" without 13 * express or implied warranty. 14 * 15 */ 16 17 #include <sys/param.h> 18 #include <sys/systm.h> 19 #include <sys/types.h> 20 #include <sys/device.h> 21 #include <dev/tc/tcvar.h> 22 #include <machine/autoconf.h> 23 #include <dev/tc/ioasicvar.h> 24 25 #include <pmax/dev/device.h> /* XXX */ 26 #include <pmax/dev/scsi.h> /* XXX */ 27 28 #include <pmax/dev/ascreg.h> /* XXX */ 29 #include <dev/tc/ascvar.h> 30 31 /*XXX*/ 32 33 34 /* 35 * Autoconfiguration data for config. 36 */ 37 int asc_tc_match __P((struct device *, struct cfdata *, void *)); 38 void asc_tc_attach __P((struct device *, struct device *, void *)); 39 40 struct cfattach asc_tc_ca = { 41 sizeof(struct asc_softc), asc_tc_match, asc_tc_attach 42 }; 43 44 /* 45 * DMA callbacks 46 */ 47 48 static int 49 tc_dma_start __P((struct asc_softc *asc, struct scsi_state *state, 50 caddr_t cp, int flag, int len, int off)); 51 52 static void 53 tc_dma_end __P((struct asc_softc *asc, struct scsi_state *state, 54 int flag)); 55 56 57 int 58 asc_tc_match(parent, match, aux) 59 struct device *parent; 60 struct cfdata *match; 61 void *aux; 62 { 63 struct tc_attach_args *t = aux; 64 void *ascaddr; 65 66 if (strncmp(t->ta_modname, "PMAZ-AA ", TC_ROM_LLEN)) 67 return (0); 68 69 ascaddr = (void*)t->ta_addr; 70 71 if (tc_badaddr(ascaddr + ASC_OFFSET_53C94)) 72 return (0); 73 74 return (1); 75 } 76 77 78 79 void 80 asc_tc_attach(parent, self, aux) 81 struct device *parent; 82 struct device *self; 83 void *aux; 84 { 85 register struct tc_attach_args *t = aux; 86 register asc_softc_t asc = (asc_softc_t) self; 87 u_char *buff; 88 int i, speed; 89 90 void *ascaddr; 91 int unit; 92 93 /* Use uncached address for chip registers. */ 94 ascaddr = (void*)MIPS_PHYS_TO_KSEG1(t->ta_addr); 95 unit = asc->sc_dev.dv_unit; 96 97 /* 98 * Initialize hw descriptor, cache some pointers 99 */ 100 asc->regs = (asc_regmap_t *)(ascaddr + ASC_OFFSET_53C94); 101 102 /* 103 * Set up machine dependencies. 104 * (1) how to do dma 105 * (2) timing based on turbochannel frequency 106 */ 107 108 /* 109 * Fall through for turbochannel option. 110 */ 111 asc->dmar = (volatile int *)(ascaddr + ASC_OFFSET_DMAR); 112 buff = (u_char *)(ascaddr + ASC_OFFSET_RAM); 113 114 /* 115 * Statically partition the DMA buffer between targets. 116 * This way we will eventually be able to attach/detach 117 * drives on-fly. And 18k/target is plenty for normal use. 118 */ 119 120 /* 121 * Give each target its own DMA buffer region. 122 * We may want to try ping ponging buffers later. 123 */ 124 for (i = 0; i < ASC_NCMD; i++) 125 asc->st[i].dmaBufAddr = buff + PER_TGT_DMA_SIZE * i; 126 127 asc->dma_start = tc_dma_start; 128 asc->dma_end = tc_dma_end; 129 130 /* 131 * Now for timing. The 3max has a 25Mhz tb whereas the 3min and 132 * maxine are 12.5Mhz. 133 */ 134 printf(" (bus speed: %s MHz) ", t->ta_busspeed? "25" : "12.5"); 135 136 switch (t->ta_busspeed) { 137 case TC_SPEED_25_MHZ: 138 speed = ASC_SPEED_25_MHZ; 139 break; 140 141 default: 142 printf(" (unknown TC speed, assuming 12.5MHz) "); 143 /* FALLTHROUGH*/ 144 case TC_SPEED_12_5_MHZ: 145 speed = ASC_SPEED_12_5_MHZ; 146 break; 147 }; 148 149 ascattach(asc, speed); 150 151 /* tie pseudo-slot to device */ 152 tc_intr_establish(parent, t->ta_cookie, TC_IPL_BIO, 153 asc_intr, asc); 154 } 155 156 157 /* 158 * DMA handling routines. For a turbochannel device, just set the dmar. 159 * For the I/O ASIC, handle the actual DMA interface. 160 */ 161 static int 162 tc_dma_start(asc, state, cp, flag, len, off) 163 asc_softc_t asc; 164 State *state; 165 caddr_t cp; 166 int flag; 167 int len; 168 int off; 169 { 170 171 if (len > PER_TGT_DMA_SIZE) 172 len = PER_TGT_DMA_SIZE; 173 if (flag == ASCDMA_WRITE) 174 bcopy(cp, state->dmaBufAddr + off, len); 175 if (flag == ASCDMA_WRITE) 176 *asc->dmar = ASC_DMAR_WRITE | ASC_DMA_ADDR(state->dmaBufAddr + off); 177 else 178 *asc->dmar = ASC_DMA_ADDR(state->dmaBufAddr + off); 179 return (len); 180 } 181 182 static void 183 tc_dma_end(asc, state, flag) 184 asc_softc_t asc; 185 State *state; 186 int flag; 187 { 188 if (flag == ASCDMA_READ) 189 bcopy(state->dmaBufAddr, state->buf, state->dmalen); 190 } 191