1 /* $NetBSD: asc_tc.c,v 1.9 1999/01/16 06:36:42 nisimura 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 65 if (strncmp(t->ta_modname, "PMAZ-AA ", TC_ROM_LLEN)) 66 return (0); 67 68 if (tc_badaddr(t->ta_addr + ASC_OFFSET_53C94)) 69 return (0); 70 71 return (1); 72 } 73 74 75 76 void 77 asc_tc_attach(parent, self, aux) 78 struct device *parent; 79 struct device *self; 80 void *aux; 81 { 82 register struct tc_attach_args *t = aux; 83 register asc_softc_t asc = (asc_softc_t) self; 84 u_char *buff; 85 int i, speed; 86 tc_addr_t ascaddr; 87 int unit; 88 89 /* Use uncached address for chip registers. */ 90 ascaddr = (tc_addr_t)MIPS_PHYS_TO_KSEG1(t->ta_addr); 91 unit = asc->sc_dev.dv_unit; 92 93 /* 94 * Initialize hw descriptor, cache some pointers 95 */ 96 asc->regs = (asc_regmap_t *)(ascaddr + ASC_OFFSET_53C94); 97 98 /* 99 * Set up machine dependencies. 100 * (1) how to do dma 101 * (2) timing based on turbochannel frequency 102 */ 103 104 /* 105 * Fall through for turbochannel option. 106 */ 107 asc->dmar = (volatile int *)(ascaddr + ASC_OFFSET_DMAR); 108 buff = (u_char *)(ascaddr + ASC_OFFSET_RAM); 109 110 /* 111 * Statically partition the DMA buffer between targets. 112 * This way we will eventually be able to attach/detach 113 * drives on-fly. And 18k/target is plenty for normal use. 114 */ 115 116 /* 117 * Give each target its own DMA buffer region. 118 * We may want to try ping ponging buffers later. 119 */ 120 for (i = 0; i < ASC_NCMD; i++) 121 asc->st[i].dmaBufAddr = buff + PER_TGT_DMA_SIZE * i; 122 123 asc->dma_start = tc_dma_start; 124 asc->dma_end = tc_dma_end; 125 126 /* 127 * Now for timing. The 3max has a 25Mhz tb whereas the 3min and 128 * maxine are 12.5Mhz. 129 */ 130 printf(" (bus speed: %s MHz) ", t->ta_busspeed? "25" : "12.5"); 131 132 switch (t->ta_busspeed) { 133 case TC_SPEED_25_MHZ: 134 speed = ASC_SPEED_25_MHZ; 135 break; 136 137 default: 138 printf(" (unknown TC speed, assuming 12.5MHz) "); 139 /* FALLTHROUGH*/ 140 case TC_SPEED_12_5_MHZ: 141 speed = ASC_SPEED_12_5_MHZ; 142 break; 143 }; 144 145 ascattach(asc, speed); 146 147 /* tie pseudo-slot to device */ 148 tc_intr_establish(parent, t->ta_cookie, TC_IPL_BIO, 149 asc_intr, asc); 150 } 151 152 153 /* 154 * DMA handling routines. For a turbochannel device, just set the dmar. 155 * For the I/O ASIC, handle the actual DMA interface. 156 */ 157 static int 158 tc_dma_start(asc, state, cp, flag, len, off) 159 asc_softc_t asc; 160 State *state; 161 caddr_t cp; 162 int flag; 163 int len; 164 int off; 165 { 166 167 if (len > PER_TGT_DMA_SIZE) 168 len = PER_TGT_DMA_SIZE; 169 if (flag == ASCDMA_WRITE) 170 bcopy(cp, state->dmaBufAddr + off, len); 171 if (flag == ASCDMA_WRITE) 172 *asc->dmar = ASC_DMAR_WRITE | ASC_DMA_ADDR(state->dmaBufAddr + off); 173 else 174 *asc->dmar = ASC_DMA_ADDR(state->dmaBufAddr + off); 175 return (len); 176 } 177 178 static void 179 tc_dma_end(asc, state, flag) 180 asc_softc_t asc; 181 State *state; 182 int flag; 183 { 184 if (flag == ASCDMA_READ) 185 bcopy(state->dmaBufAddr, state->buf, state->dmalen); 186 } 187