asc_tc.c revision 1.12 1 /* $NetBSD: asc_tc.c,v 1.12 2000/02/11 01:32:42 thorpej 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