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