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