dpt.c revision 1.32 1 1.32 provos /* $NetBSD: dpt.c,v 1.32 2002/09/27 15:37:16 provos Exp $ */
2 1.1 ad
3 1.1 ad /*-
4 1.29 bouyer * Copyright (c) 1997, 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
5 1.1 ad * All rights reserved.
6 1.1 ad *
7 1.1 ad * This code is derived from software contributed to The NetBSD Foundation
8 1.22 ad * by Andrew Doran, Charles M. Hannum and by Jason R. Thorpe of the Numerical
9 1.1 ad * Aerospace Simulation Facility, NASA Ames Research Center.
10 1.1 ad *
11 1.1 ad * Redistribution and use in source and binary forms, with or without
12 1.1 ad * modification, are permitted provided that the following conditions
13 1.1 ad * are met:
14 1.1 ad * 1. Redistributions of source code must retain the above copyright
15 1.1 ad * notice, this list of conditions and the following disclaimer.
16 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 ad * notice, this list of conditions and the following disclaimer in the
18 1.1 ad * documentation and/or other materials provided with the distribution.
19 1.1 ad * 3. All advertising materials mentioning features or use of this software
20 1.1 ad * must display the following acknowledgement:
21 1.1 ad * This product includes software developed by the NetBSD
22 1.1 ad * Foundation, Inc. and its contributors.
23 1.1 ad * 4. Neither the name of The NetBSD Foundation nor the names of its
24 1.1 ad * contributors may be used to endorse or promote products derived
25 1.1 ad * from this software without specific prior written permission.
26 1.1 ad *
27 1.1 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 1.1 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 1.1 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 1.1 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 1.1 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.1 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.1 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.1 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.1 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.1 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.1 ad * POSSIBILITY OF SUCH DAMAGE.
38 1.1 ad */
39 1.1 ad
40 1.1 ad /*
41 1.1 ad * Portions of this code fall under the following copyright:
42 1.1 ad *
43 1.1 ad * Originally written by Julian Elischer (julian (at) tfs.com)
44 1.1 ad * for TRW Financial Systems for use under the MACH(2.5) operating system.
45 1.1 ad *
46 1.1 ad * TRW Financial Systems, in accordance with their agreement with Carnegie
47 1.1 ad * Mellon University, makes this software available to CMU to distribute
48 1.1 ad * or use in any manner that they see fit as long as this message is kept with
49 1.1 ad * the software. For this reason TFS also grants any other persons or
50 1.1 ad * organisations permission to use or modify this software.
51 1.1 ad *
52 1.1 ad * TFS supplies this software to be publicly redistributed
53 1.1 ad * on the understanding that TFS is not responsible for the correct
54 1.1 ad * functioning of this software in any circumstances.
55 1.1 ad */
56 1.31 lukem
57 1.31 lukem #include <sys/cdefs.h>
58 1.32 provos __KERNEL_RCSID(0, "$NetBSD: dpt.c,v 1.32 2002/09/27 15:37:16 provos Exp $");
59 1.1 ad
60 1.1 ad #include <sys/param.h>
61 1.1 ad #include <sys/systm.h>
62 1.1 ad #include <sys/device.h>
63 1.1 ad #include <sys/queue.h>
64 1.1 ad #include <sys/buf.h>
65 1.13 ad #include <sys/endian.h>
66 1.1 ad
67 1.24 thorpej #include <uvm/uvm_extern.h>
68 1.24 thorpej
69 1.1 ad #include <machine/bus.h>
70 1.1 ad
71 1.1 ad #include <dev/scsipi/scsi_all.h>
72 1.1 ad #include <dev/scsipi/scsipi_all.h>
73 1.1 ad #include <dev/scsipi/scsiconf.h>
74 1.1 ad
75 1.1 ad #include <dev/ic/dptreg.h>
76 1.1 ad #include <dev/ic/dptvar.h>
77 1.1 ad
78 1.29 bouyer #define dpt_inb(x, o) \
79 1.29 bouyer bus_space_read_1((x)->sc_iot, (x)->sc_ioh, (o))
80 1.29 bouyer #define dpt_outb(x, o, d) \
81 1.29 bouyer bus_space_write_1((x)->sc_iot, (x)->sc_ioh, (o), (d))
82 1.29 bouyer
83 1.29 bouyer static const char * const dpt_cname[] = {
84 1.29 bouyer "3334", "SmartRAID IV",
85 1.29 bouyer "3332", "SmartRAID IV",
86 1.29 bouyer "2144", "SmartCache IV",
87 1.29 bouyer "2044", "SmartCache IV",
88 1.29 bouyer "2142", "SmartCache IV",
89 1.29 bouyer "2042", "SmartCache IV",
90 1.29 bouyer "2041", "SmartCache IV",
91 1.29 bouyer "3224", "SmartRAID III",
92 1.29 bouyer "3222", "SmartRAID III",
93 1.29 bouyer "3021", "SmartRAID III",
94 1.29 bouyer "2124", "SmartCache III",
95 1.29 bouyer "2024", "SmartCache III",
96 1.29 bouyer "2122", "SmartCache III",
97 1.29 bouyer "2022", "SmartCache III",
98 1.29 bouyer "2021", "SmartCache III",
99 1.29 bouyer "2012", "SmartCache Plus",
100 1.29 bouyer "2011", "SmartCache Plus",
101 1.29 bouyer NULL, "<unknown>",
102 1.1 ad };
103 1.1 ad
104 1.29 bouyer static void *dpt_sdh;
105 1.29 bouyer
106 1.29 bouyer static void dpt_ccb_abort(struct dpt_softc *, struct dpt_ccb *);
107 1.29 bouyer static void dpt_ccb_done(struct dpt_softc *, struct dpt_ccb *);
108 1.29 bouyer static int dpt_ccb_map(struct dpt_softc *, struct dpt_ccb *);
109 1.29 bouyer static int dpt_ccb_poll(struct dpt_softc *, struct dpt_ccb *);
110 1.29 bouyer static void dpt_ccb_unmap(struct dpt_softc *, struct dpt_ccb *);
111 1.29 bouyer static int dpt_cmd(struct dpt_softc *, struct dpt_ccb *, int, int);
112 1.29 bouyer static void dpt_hba_inquire(struct dpt_softc *, struct eata_inquiry_data **);
113 1.29 bouyer static void dpt_minphys(struct buf *);
114 1.29 bouyer static void dpt_scsipi_request(struct scsipi_channel *,
115 1.29 bouyer scsipi_adapter_req_t, void *);
116 1.29 bouyer static void dpt_shutdown(void *);
117 1.29 bouyer static int dpt_wait(struct dpt_softc *, u_int8_t, u_int8_t, int);
118 1.29 bouyer
119 1.29 bouyer static __inline__ struct dpt_ccb *dpt_ccb_alloc(struct dpt_softc *);
120 1.29 bouyer static __inline__ void dpt_ccb_free(struct dpt_softc *, struct dpt_ccb *);
121 1.29 bouyer
122 1.29 bouyer static __inline__ struct dpt_ccb *
123 1.29 bouyer dpt_ccb_alloc(struct dpt_softc *sc)
124 1.29 bouyer {
125 1.29 bouyer struct dpt_ccb *ccb;
126 1.29 bouyer int s;
127 1.29 bouyer
128 1.29 bouyer s = splbio();
129 1.29 bouyer ccb = SLIST_FIRST(&sc->sc_ccb_free);
130 1.29 bouyer SLIST_REMOVE_HEAD(&sc->sc_ccb_free, ccb_chain);
131 1.29 bouyer splx(s);
132 1.29 bouyer
133 1.29 bouyer return (ccb);
134 1.29 bouyer }
135 1.29 bouyer
136 1.29 bouyer static __inline__ void
137 1.29 bouyer dpt_ccb_free(struct dpt_softc *sc, struct dpt_ccb *ccb)
138 1.29 bouyer {
139 1.29 bouyer int s;
140 1.1 ad
141 1.29 bouyer ccb->ccb_flg = 0;
142 1.29 bouyer s = splbio();
143 1.29 bouyer SLIST_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_chain);
144 1.29 bouyer splx(s);
145 1.29 bouyer }
146 1.19 ad
147 1.1 ad /*
148 1.1 ad * Handle an interrupt from the HBA.
149 1.1 ad */
150 1.1 ad int
151 1.29 bouyer dpt_intr(void *cookie)
152 1.1 ad {
153 1.1 ad struct dpt_softc *sc;
154 1.1 ad struct dpt_ccb *ccb;
155 1.1 ad struct eata_sp *sp;
156 1.19 ad volatile int junk;
157 1.29 bouyer int forus;
158 1.1 ad
159 1.29 bouyer sc = cookie;
160 1.19 ad sp = sc->sc_stp;
161 1.29 bouyer forus = 0;
162 1.19 ad
163 1.7 ad for (;;) {
164 1.7 ad /*
165 1.7 ad * HBA might have interrupted while we were dealing with the
166 1.7 ad * last completed command, since we ACK before we deal; keep
167 1.19 ad * polling.
168 1.29 bouyer */
169 1.19 ad if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) == 0)
170 1.7 ad break;
171 1.29 bouyer forus = 1;
172 1.29 bouyer
173 1.19 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_stpoff,
174 1.1 ad sizeof(struct eata_sp), BUS_DMASYNC_POSTREAD);
175 1.1 ad
176 1.29 bouyer /* Might have looped before HBA can reset HBA_AUX_INTR. */
177 1.1 ad if (sp->sp_ccbid == -1) {
178 1.1 ad DELAY(50);
179 1.19 ad
180 1.1 ad if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) == 0)
181 1.1 ad return (0);
182 1.19 ad
183 1.19 ad printf("%s: no status\n", sc->sc_dv.dv_xname);
184 1.19 ad
185 1.1 ad /* Re-sync DMA map */
186 1.29 bouyer bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
187 1.19 ad sc->sc_stpoff, sizeof(struct eata_sp),
188 1.1 ad BUS_DMASYNC_POSTREAD);
189 1.1 ad }
190 1.1 ad
191 1.29 bouyer /* Make sure CCB ID from status packet is realistic. */
192 1.29 bouyer if ((u_int)sp->sp_ccbid >= sc->sc_nccbs) {
193 1.1 ad printf("%s: bogus status (returned CCB id %d)\n",
194 1.1 ad sc->sc_dv.dv_xname, sp->sp_ccbid);
195 1.1 ad
196 1.1 ad /* Ack the interrupt */
197 1.20 ad sp->sp_ccbid = -1;
198 1.19 ad junk = dpt_inb(sc, HA_STATUS);
199 1.29 bouyer continue;
200 1.1 ad }
201 1.29 bouyer
202 1.29 bouyer /* Sync up DMA map and cache cmd status. */
203 1.29 bouyer ccb = sc->sc_ccbs + sp->sp_ccbid;
204 1.29 bouyer
205 1.29 bouyer bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, CCB_OFF(sc, ccb),
206 1.29 bouyer sizeof(struct dpt_ccb), BUS_DMASYNC_POSTWRITE);
207 1.29 bouyer
208 1.29 bouyer ccb->ccb_hba_status = sp->sp_hba_status & 0x7f;
209 1.29 bouyer ccb->ccb_scsi_status = sp->sp_scsi_status;
210 1.29 bouyer
211 1.29 bouyer /*
212 1.29 bouyer * Ack the interrupt and process the CCB. If this
213 1.29 bouyer * is a private CCB it's up to dpt_ccb_poll() to
214 1.29 bouyer * notice.
215 1.29 bouyer */
216 1.29 bouyer sp->sp_ccbid = -1;
217 1.29 bouyer ccb->ccb_flg |= CCB_INTR;
218 1.29 bouyer junk = dpt_inb(sc, HA_STATUS);
219 1.29 bouyer if ((ccb->ccb_flg & CCB_PRIVATE) == 0)
220 1.29 bouyer dpt_ccb_done(sc, ccb);
221 1.1 ad }
222 1.1 ad
223 1.29 bouyer return (forus);
224 1.1 ad }
225 1.1 ad
226 1.1 ad /*
227 1.29 bouyer * Initialize and attach the HBA. This is the entry point from bus
228 1.1 ad * specific probe-and-attach code.
229 1.1 ad */
230 1.1 ad void
231 1.29 bouyer dpt_init(struct dpt_softc *sc, const char *intrstr)
232 1.1 ad {
233 1.29 bouyer struct scsipi_adapter *adapt;
234 1.29 bouyer struct scsipi_channel *chan;
235 1.1 ad struct eata_inquiry_data *ei;
236 1.29 bouyer int i, j, rv, rseg, maxchannel, maxtarget, mapsize;
237 1.1 ad bus_dma_segment_t seg;
238 1.4 ad struct eata_cfg *ec;
239 1.29 bouyer struct dpt_ccb *ccb;
240 1.1 ad char model[16];
241 1.29 bouyer
242 1.4 ad ec = &sc->sc_ec;
243 1.1 ad
244 1.29 bouyer /*
245 1.29 bouyer * Allocate the CCB/status packet/scratch DMA map and load.
246 1.29 bouyer */
247 1.19 ad sc->sc_nccbs =
248 1.19 ad min(be16toh(*(int16_t *)ec->ec_queuedepth), DPT_MAX_CCBS);
249 1.19 ad sc->sc_stpoff = sc->sc_nccbs * sizeof(struct dpt_ccb);
250 1.19 ad sc->sc_scroff = sc->sc_stpoff + sizeof(struct eata_sp);
251 1.29 bouyer mapsize = sc->sc_nccbs * sizeof(struct dpt_ccb) +
252 1.29 bouyer DPT_SCRATCH_SIZE + sizeof(struct eata_sp);
253 1.29 bouyer
254 1.29 bouyer if ((rv = bus_dmamem_alloc(sc->sc_dmat, mapsize,
255 1.24 thorpej PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
256 1.29 bouyer printf("%s: unable to allocate CCBs, rv = %d\n",
257 1.29 bouyer sc->sc_dv.dv_xname, rv);
258 1.1 ad return;
259 1.1 ad }
260 1.1 ad
261 1.29 bouyer if ((rv = bus_dmamem_map(sc->sc_dmat, &seg, rseg, mapsize,
262 1.1 ad (caddr_t *)&sc->sc_ccbs, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
263 1.29 bouyer printf("%s: unable to map CCBs, rv = %d\n",
264 1.29 bouyer sc->sc_dv.dv_xname, rv);
265 1.1 ad return;
266 1.1 ad }
267 1.1 ad
268 1.29 bouyer if ((rv = bus_dmamap_create(sc->sc_dmat, mapsize,
269 1.29 bouyer mapsize, 1, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
270 1.29 bouyer printf("%s: unable to create CCB DMA map, rv = %d\n",
271 1.29 bouyer sc->sc_dv.dv_xname, rv);
272 1.1 ad return;
273 1.1 ad }
274 1.1 ad
275 1.29 bouyer if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap,
276 1.29 bouyer sc->sc_ccbs, mapsize, NULL, BUS_DMA_NOWAIT)) != 0) {
277 1.29 bouyer printf("%s: unable to load CCB DMA map, rv = %d\n",
278 1.29 bouyer sc->sc_dv.dv_xname, rv);
279 1.1 ad return;
280 1.1 ad }
281 1.1 ad
282 1.19 ad sc->sc_stp = (struct eata_sp *)((caddr_t)sc->sc_ccbs + sc->sc_stpoff);
283 1.19 ad sc->sc_stppa = sc->sc_dmamap->dm_segs[0].ds_addr + sc->sc_stpoff;
284 1.1 ad sc->sc_scr = (caddr_t)sc->sc_ccbs + sc->sc_scroff;
285 1.19 ad sc->sc_scrpa = sc->sc_dmamap->dm_segs[0].ds_addr + sc->sc_scroff;
286 1.19 ad sc->sc_stp->sp_ccbid = -1;
287 1.4 ad
288 1.29 bouyer /*
289 1.29 bouyer * Create the CCBs.
290 1.29 bouyer */
291 1.29 bouyer SLIST_INIT(&sc->sc_ccb_free);
292 1.29 bouyer memset(sc->sc_ccbs, 0, sizeof(struct dpt_ccb) * sc->sc_nccbs);
293 1.29 bouyer
294 1.29 bouyer for (i = 0, ccb = sc->sc_ccbs; i < sc->sc_nccbs; i++, ccb++) {
295 1.29 bouyer rv = bus_dmamap_create(sc->sc_dmat, DPT_MAX_XFER,
296 1.29 bouyer DPT_SG_SIZE, DPT_MAX_XFER, 0,
297 1.29 bouyer BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
298 1.29 bouyer &ccb->ccb_dmamap_xfer);
299 1.29 bouyer if (rv) {
300 1.29 bouyer printf("%s: can't create ccb dmamap (%d)\n",
301 1.29 bouyer sc->sc_dv.dv_xname, rv);
302 1.29 bouyer break;
303 1.29 bouyer }
304 1.29 bouyer
305 1.29 bouyer ccb->ccb_id = i;
306 1.29 bouyer ccb->ccb_ccbpa = sc->sc_dmamap->dm_segs[0].ds_addr +
307 1.29 bouyer CCB_OFF(sc, ccb);
308 1.29 bouyer SLIST_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_chain);
309 1.29 bouyer }
310 1.1 ad
311 1.1 ad if (i == 0) {
312 1.1 ad printf("%s: unable to create CCBs\n", sc->sc_dv.dv_xname);
313 1.1 ad return;
314 1.1 ad } else if (i != sc->sc_nccbs) {
315 1.1 ad printf("%s: %d/%d CCBs created!\n", sc->sc_dv.dv_xname, i,
316 1.1 ad sc->sc_nccbs);
317 1.1 ad sc->sc_nccbs = i;
318 1.1 ad }
319 1.1 ad
320 1.29 bouyer /* Set shutdownhook before we start any device activity. */
321 1.23 ad if (dpt_sdh == NULL)
322 1.19 ad dpt_sdh = shutdownhook_establish(dpt_shutdown, NULL);
323 1.1 ad
324 1.29 bouyer /* Get the inquiry data from the HBA. */
325 1.1 ad dpt_hba_inquire(sc, &ei);
326 1.1 ad
327 1.1 ad /*
328 1.1 ad * dpt0 at pci0 dev 12 function 0: DPT SmartRAID III (PM3224A/9X-R)
329 1.1 ad * dpt0: interrupting at irq 10
330 1.1 ad * dpt0: 64 queued commands, 1 channel(s), adapter on ID(s) 7
331 1.1 ad */
332 1.1 ad for (i = 0; ei->ei_vendor[i] != ' ' && i < 8; i++)
333 1.1 ad ;
334 1.1 ad ei->ei_vendor[i] = '\0';
335 1.1 ad
336 1.1 ad for (i = 0; ei->ei_model[i] != ' ' && i < 7; i++)
337 1.1 ad model[i] = ei->ei_model[i];
338 1.25 cgd for (j = 0; ei->ei_suffix[j] != ' ' && j < 7; i++, j++)
339 1.25 cgd model[i] = ei->ei_model[i];
340 1.1 ad model[i] = '\0';
341 1.1 ad
342 1.29 bouyer /* Find the marketing name for the board. */
343 1.9 ad for (i = 0; dpt_cname[i] != NULL; i += 2)
344 1.29 bouyer if (memcmp(ei->ei_model + 2, dpt_cname[i], 4) == 0)
345 1.1 ad break;
346 1.29 bouyer
347 1.1 ad printf("%s %s (%s)\n", ei->ei_vendor, dpt_cname[i + 1], model);
348 1.1 ad
349 1.1 ad if (intrstr != NULL)
350 1.29 bouyer printf("%s: interrupting at %s\n", sc->sc_dv.dv_xname,
351 1.29 bouyer intrstr);
352 1.1 ad
353 1.19 ad maxchannel = (ec->ec_feat3 & EC_F3_MAX_CHANNEL_MASK) >>
354 1.19 ad EC_F3_MAX_CHANNEL_SHIFT;
355 1.19 ad maxtarget = (ec->ec_feat3 & EC_F3_MAX_TARGET_MASK) >>
356 1.19 ad EC_F3_MAX_TARGET_SHIFT;
357 1.19 ad
358 1.1 ad printf("%s: %d queued commands, %d channel(s), adapter on ID(s)",
359 1.19 ad sc->sc_dv.dv_xname, sc->sc_nccbs, maxchannel + 1);
360 1.1 ad
361 1.19 ad for (i = 0; i <= maxchannel; i++) {
362 1.19 ad sc->sc_hbaid[i] = ec->ec_hba[3 - i];
363 1.19 ad printf(" %d", sc->sc_hbaid[i]);
364 1.19 ad }
365 1.1 ad printf("\n");
366 1.1 ad
367 1.29 bouyer /*
368 1.29 bouyer * Reset the SCSI controller chip(s) and bus. XXX Do we need to do
369 1.29 bouyer * this for each bus?
370 1.29 bouyer */
371 1.29 bouyer if (dpt_cmd(sc, NULL, CP_IMMEDIATE, CPI_BUS_RESET))
372 1.4 ad panic("%s: dpt_cmd failed", sc->sc_dv.dv_xname);
373 1.29 bouyer
374 1.29 bouyer /* Fill in the scsipi_adapter. */
375 1.29 bouyer adapt = &sc->sc_adapt;
376 1.29 bouyer memset(adapt, 0, sizeof(*adapt));
377 1.29 bouyer adapt->adapt_dev = &sc->sc_dv;
378 1.29 bouyer adapt->adapt_nchannels = maxchannel + 1;
379 1.29 bouyer adapt->adapt_openings = sc->sc_nccbs;
380 1.29 bouyer adapt->adapt_max_periph = sc->sc_nccbs;
381 1.29 bouyer adapt->adapt_request = dpt_scsipi_request;
382 1.29 bouyer adapt->adapt_minphys = dpt_minphys;
383 1.1 ad
384 1.19 ad for (i = 0; i <= maxchannel; i++) {
385 1.29 bouyer /* Fill in the scsipi_channel. */
386 1.29 bouyer chan = &sc->sc_chans[i];
387 1.29 bouyer memset(chan, 0, sizeof(*chan));
388 1.29 bouyer chan->chan_adapter = adapt;
389 1.29 bouyer chan->chan_bustype = &scsi_bustype;
390 1.29 bouyer chan->chan_channel = i;
391 1.29 bouyer chan->chan_ntargets = maxtarget + 1;
392 1.29 bouyer chan->chan_nluns = ec->ec_maxlun + 1;
393 1.29 bouyer chan->chan_id = sc->sc_hbaid[i];
394 1.29 bouyer config_found(&sc->sc_dv, chan, scsiprint);
395 1.23 ad }
396 1.1 ad }
397 1.1 ad
398 1.1 ad /*
399 1.1 ad * Read the EATA configuration from the HBA and perform some sanity checks.
400 1.1 ad */
401 1.1 ad int
402 1.29 bouyer dpt_readcfg(struct dpt_softc *sc)
403 1.1 ad {
404 1.4 ad struct eata_cfg *ec;
405 1.1 ad int i, j, stat;
406 1.1 ad u_int16_t *p;
407 1.1 ad
408 1.4 ad ec = &sc->sc_ec;
409 1.4 ad
410 1.29 bouyer /* Older firmware may puke if we talk to it too soon after reset. */
411 1.4 ad dpt_outb(sc, HA_COMMAND, CP_RESET);
412 1.19 ad DELAY(750000);
413 1.4 ad
414 1.4 ad for (i = 1000; i; i--) {
415 1.4 ad if ((dpt_inb(sc, HA_STATUS) & HA_ST_READY) != 0)
416 1.4 ad break;
417 1.4 ad DELAY(2000);
418 1.4 ad }
419 1.29 bouyer
420 1.4 ad if (i == 0) {
421 1.17 ad printf("%s: HBA not ready after reset (hba status:%02x)\n",
422 1.4 ad sc->sc_dv.dv_xname, dpt_inb(sc, HA_STATUS));
423 1.4 ad return (-1);
424 1.4 ad }
425 1.4 ad
426 1.1 ad while((((stat = dpt_inb(sc, HA_STATUS))
427 1.19 ad != (HA_ST_READY|HA_ST_SEEK_COMPLETE))
428 1.19 ad && (stat != (HA_ST_READY|HA_ST_SEEK_COMPLETE|HA_ST_ERROR))
429 1.19 ad && (stat != (HA_ST_READY|HA_ST_SEEK_COMPLETE|HA_ST_ERROR|HA_ST_DRQ)))
430 1.29 bouyer || (dpt_wait(sc, HA_ST_BUSY, 0, 2000))) {
431 1.19 ad /* RAID drives still spinning up? */
432 1.29 bouyer if(dpt_inb(sc, HA_ERROR) != 'D' ||
433 1.29 bouyer dpt_inb(sc, HA_ERROR + 1) != 'P' ||
434 1.29 bouyer dpt_inb(sc, HA_ERROR + 2) != 'T') {
435 1.29 bouyer printf("%s: HBA not ready\n", sc->sc_dv.dv_xname);
436 1.19 ad return (-1);
437 1.2 ad }
438 1.19 ad }
439 1.1 ad
440 1.1 ad /*
441 1.29 bouyer * Issue the read-config command and wait for the data to appear.
442 1.29 bouyer *
443 1.29 bouyer * Apparently certian firmware revisions won't DMA later on if we
444 1.29 bouyer * request the config data using PIO, but it makes it a lot easier
445 1.29 bouyer * as no DMA setup is required.
446 1.1 ad */
447 1.1 ad dpt_outb(sc, HA_COMMAND, CP_PIO_GETCFG);
448 1.4 ad memset(ec, 0, sizeof(*ec));
449 1.4 ad i = ((int)&((struct eata_cfg *)0)->ec_cfglen +
450 1.4 ad sizeof(ec->ec_cfglen)) >> 1;
451 1.4 ad p = (u_int16_t *)ec;
452 1.4 ad
453 1.4 ad if (dpt_wait(sc, 0xFF, HA_ST_DATA_RDY, 2000)) {
454 1.29 bouyer printf("%s: cfg data didn't appear (hba status:%02x)\n",
455 1.9 ad sc->sc_dv.dv_xname, dpt_inb(sc, HA_STATUS));
456 1.29 bouyer return (-1);
457 1.29 bouyer }
458 1.1 ad
459 1.29 bouyer /* Begin reading. */
460 1.29 bouyer while (i--)
461 1.27 briggs *p++ = bus_space_read_stream_2(sc->sc_iot, sc->sc_ioh, HA_DATA);
462 1.1 ad
463 1.19 ad if ((i = ec->ec_cfglen) > (sizeof(struct eata_cfg)
464 1.19 ad - (int)(&(((struct eata_cfg *)0L)->ec_cfglen))
465 1.19 ad - sizeof(ec->ec_cfglen)))
466 1.19 ad i = sizeof(struct eata_cfg)
467 1.19 ad - (int)(&(((struct eata_cfg *)0L)->ec_cfglen))
468 1.19 ad - sizeof(ec->ec_cfglen);
469 1.19 ad
470 1.19 ad j = i + (int)(&(((struct eata_cfg *)0L)->ec_cfglen)) +
471 1.19 ad sizeof(ec->ec_cfglen);
472 1.19 ad i >>= 1;
473 1.1 ad
474 1.1 ad while (i--)
475 1.27 briggs *p++ = bus_space_read_stream_2(sc->sc_iot, sc->sc_ioh, HA_DATA);
476 1.29 bouyer
477 1.19 ad /* Flush until we have read 512 bytes. */
478 1.19 ad i = (512 - j + 1) >> 1;
479 1.1 ad while (i--)
480 1.29 bouyer bus_space_read_stream_2(sc->sc_iot, sc->sc_ioh, HA_DATA);
481 1.19 ad
482 1.29 bouyer /* Defaults for older firmware... */
483 1.4 ad if (p <= (u_short *)&ec->ec_hba[DPT_MAX_CHANNELS - 1])
484 1.4 ad ec->ec_hba[DPT_MAX_CHANNELS - 1] = 7;
485 1.1 ad
486 1.19 ad if ((dpt_inb(sc, HA_STATUS) & HA_ST_ERROR) != 0) {
487 1.19 ad printf("%s: HBA error\n", sc->sc_dv.dv_xname);
488 1.19 ad return (-1);
489 1.19 ad }
490 1.29 bouyer
491 1.15 ad if (memcmp(ec->ec_eatasig, "EATA", 4) != 0) {
492 1.29 bouyer printf("%s: EATA signature mismatch\n", sc->sc_dv.dv_xname);
493 1.1 ad return (-1);
494 1.1 ad }
495 1.29 bouyer
496 1.19 ad if ((ec->ec_feat0 & EC_F0_HBA_VALID) == 0) {
497 1.19 ad printf("%s: ec_hba field invalid\n", sc->sc_dv.dv_xname);
498 1.1 ad return (-1);
499 1.1 ad }
500 1.29 bouyer
501 1.19 ad if ((ec->ec_feat0 & EC_F0_DMA_SUPPORTED) == 0) {
502 1.29 bouyer printf("%s: DMA not supported\n", sc->sc_dv.dv_xname);
503 1.1 ad return (-1);
504 1.1 ad }
505 1.1 ad
506 1.1 ad return (0);
507 1.1 ad }
508 1.1 ad
509 1.1 ad /*
510 1.29 bouyer * Our `shutdownhook' to cleanly shut down the HBA. The HBA must flush all
511 1.29 bouyer * data from it's cache and mark array groups as clean.
512 1.29 bouyer *
513 1.29 bouyer * XXX This doesn't always work (i.e., the HBA may still be flushing after
514 1.29 bouyer * we tell root that it's safe to power off).
515 1.1 ad */
516 1.29 bouyer static void
517 1.29 bouyer dpt_shutdown(void *cookie)
518 1.1 ad {
519 1.29 bouyer extern struct cfdriver dpt_cd;
520 1.29 bouyer struct dpt_softc *sc;
521 1.29 bouyer int i;
522 1.29 bouyer
523 1.29 bouyer printf("shutting down dpt devices...");
524 1.29 bouyer
525 1.29 bouyer for (i = 0; i < dpt_cd.cd_ndevs; i++) {
526 1.29 bouyer if ((sc = device_lookup(&dpt_cd, i)) == NULL)
527 1.29 bouyer continue;
528 1.29 bouyer dpt_cmd(sc, NULL, CP_IMMEDIATE, CPI_POWEROFF_WARN);
529 1.29 bouyer }
530 1.1 ad
531 1.29 bouyer delay(10000*1000);
532 1.29 bouyer printf(" done\n");
533 1.1 ad }
534 1.1 ad
535 1.1 ad /*
536 1.29 bouyer * Send an EATA command to the HBA.
537 1.1 ad */
538 1.29 bouyer static int
539 1.29 bouyer dpt_cmd(struct dpt_softc *sc, struct dpt_ccb *ccb, int eatacmd, int icmd)
540 1.1 ad {
541 1.29 bouyer u_int32_t pa;
542 1.29 bouyer int i, s;
543 1.1 ad
544 1.1 ad s = splbio();
545 1.1 ad
546 1.29 bouyer for (i = 20000; i != 0; i--) {
547 1.29 bouyer if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_BUSY) == 0)
548 1.29 bouyer break;
549 1.29 bouyer DELAY(50);
550 1.29 bouyer }
551 1.29 bouyer if (i == 0) {
552 1.29 bouyer splx(s);
553 1.29 bouyer return (-1);
554 1.29 bouyer }
555 1.29 bouyer
556 1.29 bouyer pa = (ccb != NULL ? ccb->ccb_ccbpa : 0);
557 1.29 bouyer dpt_outb(sc, HA_DMA_BASE + 0, (pa ) & 0xff);
558 1.29 bouyer dpt_outb(sc, HA_DMA_BASE + 1, (pa >> 8) & 0xff);
559 1.29 bouyer dpt_outb(sc, HA_DMA_BASE + 2, (pa >> 16) & 0xff);
560 1.29 bouyer dpt_outb(sc, HA_DMA_BASE + 3, (pa >> 24) & 0xff);
561 1.29 bouyer
562 1.29 bouyer if (eatacmd == CP_IMMEDIATE)
563 1.29 bouyer dpt_outb(sc, HA_ICMD, icmd);
564 1.1 ad
565 1.29 bouyer dpt_outb(sc, HA_COMMAND, eatacmd);
566 1.1 ad
567 1.29 bouyer splx(s);
568 1.1 ad return (0);
569 1.1 ad }
570 1.1 ad
571 1.1 ad /*
572 1.29 bouyer * Wait for the HBA status register to reach a specific state.
573 1.1 ad */
574 1.29 bouyer static int
575 1.29 bouyer dpt_wait(struct dpt_softc *sc, u_int8_t mask, u_int8_t state, int ms)
576 1.1 ad {
577 1.1 ad
578 1.29 bouyer for (ms *= 10; ms != 0; ms--) {
579 1.29 bouyer if ((dpt_inb(sc, HA_STATUS) & mask) == state)
580 1.29 bouyer return (0);
581 1.29 bouyer DELAY(100);
582 1.1 ad }
583 1.1 ad
584 1.29 bouyer return (-1);
585 1.1 ad }
586 1.1 ad
587 1.1 ad /*
588 1.29 bouyer * Spin waiting for a command to finish. The timeout value from the CCB is
589 1.29 bouyer * used. The CCB must be marked with CCB_PRIVATE, otherwise it'll will get
590 1.29 bouyer * recycled before we get a look at it.
591 1.1 ad */
592 1.29 bouyer static int
593 1.29 bouyer dpt_ccb_poll(struct dpt_softc *sc, struct dpt_ccb *ccb)
594 1.1 ad {
595 1.29 bouyer int i, s;
596 1.29 bouyer
597 1.29 bouyer #ifdef DEBUG
598 1.29 bouyer if ((ccb->ccb_flg & CCB_PRIVATE) == 0)
599 1.32 provos panic("dpt_ccb_poll: called for non-CCB_PRIVATE request");
600 1.29 bouyer #endif
601 1.1 ad
602 1.1 ad s = splbio();
603 1.1 ad
604 1.29 bouyer if ((ccb->ccb_flg & CCB_INTR) != 0) {
605 1.29 bouyer splx(s);
606 1.29 bouyer return (0);
607 1.29 bouyer }
608 1.29 bouyer
609 1.29 bouyer for (i = ccb->ccb_timeout * 20; i != 0; i--) {
610 1.29 bouyer if ((dpt_inb(sc, HA_AUX_STATUS) & HA_AUX_INTR) != 0)
611 1.29 bouyer dpt_intr(sc);
612 1.29 bouyer if ((ccb->ccb_flg & CCB_INTR) != 0)
613 1.1 ad break;
614 1.29 bouyer DELAY(50);
615 1.1 ad }
616 1.1 ad
617 1.1 ad splx(s);
618 1.29 bouyer return (i == 0);
619 1.1 ad }
620 1.1 ad
621 1.1 ad /*
622 1.29 bouyer * We have a command which has been processed by the HBA, so now we look to
623 1.29 bouyer * see how the operation went. CCBs marked CCB_PRIVATE are not passed here
624 1.29 bouyer * by dpt_intr().
625 1.1 ad */
626 1.29 bouyer static void
627 1.29 bouyer dpt_ccb_done(struct dpt_softc *sc, struct dpt_ccb *ccb)
628 1.1 ad {
629 1.1 ad struct scsipi_xfer *xs;
630 1.29 bouyer
631 1.1 ad xs = ccb->ccb_xs;
632 1.1 ad
633 1.29 bouyer SC_DEBUG(xs->xs_periph, SCSIPI_DB2, ("dpt_ccb_done\n"));
634 1.1 ad
635 1.1 ad /*
636 1.1 ad * If we were a data transfer, unload the map that described the
637 1.1 ad * data buffer.
638 1.1 ad */
639 1.29 bouyer if (xs->datalen != 0)
640 1.29 bouyer dpt_ccb_unmap(sc, ccb);
641 1.1 ad
642 1.1 ad if (xs->error == XS_NOERROR) {
643 1.19 ad if (ccb->ccb_hba_status != SP_HBA_NO_ERROR) {
644 1.1 ad switch (ccb->ccb_hba_status) {
645 1.19 ad case SP_HBA_ERROR_SEL_TO:
646 1.1 ad xs->error = XS_SELTIMEOUT;
647 1.1 ad break;
648 1.19 ad case SP_HBA_ERROR_RESET:
649 1.1 ad xs->error = XS_RESET;
650 1.1 ad break;
651 1.29 bouyer default:
652 1.1 ad printf("%s: HBA status %x\n",
653 1.1 ad sc->sc_dv.dv_xname, ccb->ccb_hba_status);
654 1.1 ad xs->error = XS_DRIVER_STUFFUP;
655 1.29 bouyer break;
656 1.1 ad }
657 1.1 ad } else if (ccb->ccb_scsi_status != SCSI_OK) {
658 1.1 ad switch (ccb->ccb_scsi_status) {
659 1.1 ad case SCSI_CHECK:
660 1.29 bouyer memcpy(&xs->sense.scsi_sense, &ccb->ccb_sense,
661 1.29 bouyer sizeof(xs->sense.scsi_sense));
662 1.1 ad xs->error = XS_SENSE;
663 1.1 ad break;
664 1.1 ad case SCSI_BUSY:
665 1.29 bouyer case SCSI_QUEUE_FULL:
666 1.1 ad xs->error = XS_BUSY;
667 1.1 ad break;
668 1.1 ad default:
669 1.29 bouyer scsipi_printaddr(xs->xs_periph);
670 1.29 bouyer printf("SCSI status %x\n",
671 1.29 bouyer ccb->ccb_scsi_status);
672 1.1 ad xs->error = XS_DRIVER_STUFFUP;
673 1.29 bouyer break;
674 1.1 ad }
675 1.1 ad } else
676 1.1 ad xs->resid = 0;
677 1.29 bouyer
678 1.7 ad xs->status = ccb->ccb_scsi_status;
679 1.1 ad }
680 1.1 ad
681 1.29 bouyer /* Free up the CCB and mark the command as done. */
682 1.29 bouyer dpt_ccb_free(sc, ccb);
683 1.1 ad scsipi_done(xs);
684 1.1 ad }
685 1.1 ad
686 1.1 ad /*
687 1.29 bouyer * Specified CCB has timed out, abort it.
688 1.1 ad */
689 1.29 bouyer static void
690 1.29 bouyer dpt_ccb_abort(struct dpt_softc *sc, struct dpt_ccb *ccb)
691 1.29 bouyer {
692 1.29 bouyer struct scsipi_periph *periph;
693 1.1 ad struct scsipi_xfer *xs;
694 1.29 bouyer int s;
695 1.1 ad
696 1.29 bouyer xs = ccb->ccb_xs;
697 1.29 bouyer periph = xs->xs_periph;
698 1.1 ad
699 1.29 bouyer scsipi_printaddr(periph);
700 1.29 bouyer printf("timed out (status:%02x aux status:%02x)",
701 1.29 bouyer dpt_inb(sc, HA_STATUS), dpt_inb(sc, HA_AUX_STATUS));
702 1.1 ad
703 1.1 ad s = splbio();
704 1.1 ad
705 1.29 bouyer if ((ccb->ccb_flg & CCB_ABORT) != 0) {
706 1.29 bouyer /* Abort timed out, reset the HBA */
707 1.29 bouyer printf(" AGAIN, resetting HBA\n");
708 1.29 bouyer dpt_outb(sc, HA_COMMAND, CP_RESET);
709 1.29 bouyer DELAY(750000);
710 1.1 ad } else {
711 1.29 bouyer /* Abort the operation that has timed out */
712 1.29 bouyer printf("\n");
713 1.29 bouyer xs->error = XS_TIMEOUT;
714 1.29 bouyer ccb->ccb_timeout = DPT_ABORT_TIMEOUT;
715 1.29 bouyer ccb->ccb_flg |= CCB_ABORT;
716 1.29 bouyer /* Start the abort */
717 1.29 bouyer if (dpt_cmd(sc, ccb, CP_IMMEDIATE, CPI_SPEC_ABORT))
718 1.29 bouyer printf("%s: dpt_cmd failed\n", sc->sc_dv.dv_xname);
719 1.29 bouyer }
720 1.29 bouyer
721 1.29 bouyer splx(s);
722 1.29 bouyer }
723 1.1 ad
724 1.29 bouyer /*
725 1.29 bouyer * Map a data transfer.
726 1.29 bouyer */
727 1.29 bouyer static int
728 1.29 bouyer dpt_ccb_map(struct dpt_softc *sc, struct dpt_ccb *ccb)
729 1.29 bouyer {
730 1.29 bouyer struct scsipi_xfer *xs;
731 1.29 bouyer bus_dmamap_t xfer;
732 1.29 bouyer bus_dma_segment_t *ds;
733 1.29 bouyer struct eata_sg *sg;
734 1.29 bouyer struct eata_cp *cp;
735 1.29 bouyer int rv, i;
736 1.1 ad
737 1.29 bouyer xs = ccb->ccb_xs;
738 1.29 bouyer xfer = ccb->ccb_dmamap_xfer;
739 1.29 bouyer cp = &ccb->ccb_eata_cp;
740 1.1 ad
741 1.29 bouyer rv = bus_dmamap_load(sc->sc_dmat, xfer, xs->data, xs->datalen, NULL,
742 1.29 bouyer ((xs->xs_control & XS_CTL_NOSLEEP) != 0 ?
743 1.30 thorpej BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | BUS_DMA_STREAMING |
744 1.30 thorpej ((xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
745 1.29 bouyer
746 1.29 bouyer switch (rv) {
747 1.29 bouyer case 0:
748 1.29 bouyer break;
749 1.29 bouyer case ENOMEM:
750 1.29 bouyer case EAGAIN:
751 1.29 bouyer xs->error = XS_RESOURCE_SHORTAGE;
752 1.29 bouyer break;
753 1.29 bouyer default:
754 1.29 bouyer xs->error = XS_DRIVER_STUFFUP;
755 1.29 bouyer printf("%s: error %d loading map\n", sc->sc_dv.dv_xname, rv);
756 1.29 bouyer break;
757 1.29 bouyer }
758 1.1 ad
759 1.29 bouyer if (xs->error != XS_NOERROR) {
760 1.29 bouyer dpt_ccb_free(sc, ccb);
761 1.29 bouyer scsipi_done(xs);
762 1.29 bouyer return (-1);
763 1.1 ad }
764 1.1 ad
765 1.29 bouyer bus_dmamap_sync(sc->sc_dmat, xfer, 0, xfer->dm_mapsize,
766 1.29 bouyer (xs->xs_control & XS_CTL_DATA_IN) != 0 ? BUS_DMASYNC_PREREAD :
767 1.29 bouyer BUS_DMASYNC_PREWRITE);
768 1.29 bouyer
769 1.29 bouyer /* Don't bother using scatter/gather for just 1 seg */
770 1.29 bouyer if (xfer->dm_nsegs == 1) {
771 1.29 bouyer cp->cp_dataaddr = htobe32(xfer->dm_segs[0].ds_addr);
772 1.29 bouyer cp->cp_datalen = htobe32(xfer->dm_segs[0].ds_len);
773 1.29 bouyer } else {
774 1.29 bouyer /*
775 1.29 bouyer * Load the hardware scatter/gather map with
776 1.29 bouyer * the contents of the DMA map.
777 1.1 ad */
778 1.29 bouyer sg = ccb->ccb_sg;
779 1.29 bouyer ds = xfer->dm_segs;
780 1.29 bouyer for (i = 0; i < xfer->dm_nsegs; i++, sg++, ds++) {
781 1.29 bouyer sg->sg_addr = htobe32(ds->ds_addr);
782 1.29 bouyer sg->sg_len = htobe32(ds->ds_len);
783 1.29 bouyer }
784 1.29 bouyer cp->cp_dataaddr = htobe32(CCB_OFF(sc, ccb) +
785 1.29 bouyer sc->sc_dmamap->dm_segs[0].ds_addr +
786 1.29 bouyer offsetof(struct dpt_ccb, ccb_sg));
787 1.29 bouyer cp->cp_datalen = htobe32(i * sizeof(struct eata_sg));
788 1.29 bouyer cp->cp_ctl0 |= CP_C0_SCATTER;
789 1.1 ad }
790 1.1 ad
791 1.29 bouyer return (0);
792 1.29 bouyer }
793 1.29 bouyer
794 1.29 bouyer /*
795 1.29 bouyer * Unmap a transfer.
796 1.29 bouyer */
797 1.29 bouyer static void
798 1.29 bouyer dpt_ccb_unmap(struct dpt_softc *sc, struct dpt_ccb *ccb)
799 1.29 bouyer {
800 1.29 bouyer
801 1.29 bouyer bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0,
802 1.29 bouyer ccb->ccb_dmamap_xfer->dm_mapsize,
803 1.29 bouyer (ccb->ccb_eata_cp.cp_ctl0 & CP_C0_DATA_IN) != 0 ?
804 1.29 bouyer BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
805 1.29 bouyer bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap_xfer);
806 1.29 bouyer }
807 1.29 bouyer
808 1.29 bouyer /*
809 1.29 bouyer * Adjust the size of each I/O before it passes to the SCSI layer.
810 1.29 bouyer */
811 1.29 bouyer static void
812 1.29 bouyer dpt_minphys(struct buf *bp)
813 1.29 bouyer {
814 1.29 bouyer
815 1.29 bouyer if (bp->b_bcount > DPT_MAX_XFER)
816 1.29 bouyer bp->b_bcount = DPT_MAX_XFER;
817 1.29 bouyer minphys(bp);
818 1.29 bouyer }
819 1.29 bouyer
820 1.29 bouyer /*
821 1.29 bouyer * Start a SCSI command.
822 1.29 bouyer */
823 1.29 bouyer static void
824 1.29 bouyer dpt_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
825 1.29 bouyer void *arg)
826 1.29 bouyer {
827 1.29 bouyer struct dpt_softc *sc;
828 1.29 bouyer struct scsipi_xfer *xs;
829 1.29 bouyer int flags;
830 1.29 bouyer struct scsipi_periph *periph;
831 1.29 bouyer struct dpt_ccb *ccb;
832 1.29 bouyer struct eata_cp *cp;
833 1.29 bouyer
834 1.29 bouyer sc = (struct dpt_softc *)chan->chan_adapter->adapt_dev;
835 1.1 ad
836 1.29 bouyer switch (req) {
837 1.29 bouyer case ADAPTER_REQ_RUN_XFER:
838 1.29 bouyer xs = arg;
839 1.29 bouyer periph = xs->xs_periph;
840 1.29 bouyer flags = xs->xs_control;
841 1.1 ad
842 1.29 bouyer #ifdef DIAGNOSTIC
843 1.29 bouyer /* Cmds must be no more than 12 bytes for us. */
844 1.29 bouyer if (xs->cmdlen > 12) {
845 1.29 bouyer xs->error = XS_DRIVER_STUFFUP;
846 1.29 bouyer scsipi_done(xs);
847 1.29 bouyer break;
848 1.1 ad }
849 1.29 bouyer #endif
850 1.29 bouyer /*
851 1.29 bouyer * XXX We can't reset devices just yet. Apparently some
852 1.29 bouyer * older firmware revisions don't even support it.
853 1.29 bouyer */
854 1.29 bouyer if ((flags & XS_CTL_RESET) != 0) {
855 1.1 ad xs->error = XS_DRIVER_STUFFUP;
856 1.29 bouyer scsipi_done(xs);
857 1.29 bouyer break;
858 1.1 ad }
859 1.1 ad
860 1.29 bouyer /*
861 1.29 bouyer * Get a CCB and fill it.
862 1.29 bouyer */
863 1.29 bouyer ccb = dpt_ccb_alloc(sc);
864 1.29 bouyer ccb->ccb_xs = xs;
865 1.29 bouyer ccb->ccb_timeout = xs->timeout;
866 1.29 bouyer
867 1.29 bouyer cp = &ccb->ccb_eata_cp;
868 1.29 bouyer memcpy(&cp->cp_cdb_cmd, xs->cmd, xs->cmdlen);
869 1.29 bouyer cp->cp_ccbid = ccb->ccb_id;
870 1.29 bouyer cp->cp_senselen = sizeof(ccb->ccb_sense);
871 1.29 bouyer cp->cp_stataddr = htobe32(sc->sc_stppa);
872 1.29 bouyer cp->cp_ctl0 = CP_C0_AUTO_SENSE;
873 1.29 bouyer cp->cp_ctl1 = 0;
874 1.29 bouyer cp->cp_ctl2 = 0;
875 1.29 bouyer cp->cp_ctl3 = periph->periph_target << CP_C3_ID_SHIFT;
876 1.29 bouyer cp->cp_ctl3 |= chan->chan_channel << CP_C3_CHANNEL_SHIFT;
877 1.29 bouyer cp->cp_ctl4 = periph->periph_lun << CP_C4_LUN_SHIFT;
878 1.29 bouyer cp->cp_ctl4 |= CP_C4_DIS_PRI | CP_C4_IDENTIFY;
879 1.29 bouyer
880 1.29 bouyer if ((flags & XS_CTL_DATA_IN) != 0)
881 1.29 bouyer cp->cp_ctl0 |= CP_C0_DATA_IN;
882 1.29 bouyer if ((flags & XS_CTL_DATA_OUT) != 0)
883 1.29 bouyer cp->cp_ctl0 |= CP_C0_DATA_OUT;
884 1.29 bouyer if (sc->sc_hbaid[chan->chan_channel] == periph->periph_target)
885 1.29 bouyer cp->cp_ctl0 |= CP_C0_INTERPRET;
886 1.29 bouyer
887 1.29 bouyer /* Synchronous xfers musn't write-back through the cache. */
888 1.29 bouyer if (xs->bp != NULL)
889 1.29 bouyer if ((xs->bp->b_flags & (B_ASYNC | B_READ)) == 0)
890 1.29 bouyer cp->cp_ctl2 |= CP_C2_NO_CACHE;
891 1.29 bouyer
892 1.29 bouyer cp->cp_senseaddr =
893 1.29 bouyer htobe32(sc->sc_dmamap->dm_segs[0].ds_addr +
894 1.29 bouyer CCB_OFF(sc, ccb) + offsetof(struct dpt_ccb, ccb_sense));
895 1.1 ad
896 1.29 bouyer if (xs->datalen != 0) {
897 1.29 bouyer if (dpt_ccb_map(sc, ccb))
898 1.29 bouyer break;
899 1.9 ad } else {
900 1.29 bouyer cp->cp_dataaddr = 0;
901 1.29 bouyer cp->cp_datalen = 0;
902 1.1 ad }
903 1.1 ad
904 1.29 bouyer /* Sync up CCB and status packet. */
905 1.29 bouyer bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
906 1.29 bouyer CCB_OFF(sc, ccb), sizeof(struct dpt_ccb),
907 1.29 bouyer BUS_DMASYNC_PREWRITE);
908 1.29 bouyer bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_stpoff,
909 1.29 bouyer sizeof(struct eata_sp), BUS_DMASYNC_PREREAD);
910 1.1 ad
911 1.29 bouyer /*
912 1.29 bouyer * Start the command.
913 1.29 bouyer */
914 1.29 bouyer if ((xs->xs_control & XS_CTL_POLL) != 0)
915 1.29 bouyer ccb->ccb_flg |= CCB_PRIVATE;
916 1.1 ad
917 1.29 bouyer if (dpt_cmd(sc, ccb, CP_DMA_CMD, 0)) {
918 1.29 bouyer printf("%s: dpt_cmd failed\n", sc->sc_dv.dv_xname);
919 1.29 bouyer xs->error = XS_DRIVER_STUFFUP;
920 1.29 bouyer if (xs->datalen != 0)
921 1.29 bouyer dpt_ccb_unmap(sc, ccb);
922 1.29 bouyer dpt_ccb_free(sc, ccb);
923 1.29 bouyer break;
924 1.29 bouyer }
925 1.1 ad
926 1.29 bouyer if ((xs->xs_control & XS_CTL_POLL) == 0)
927 1.29 bouyer break;
928 1.1 ad
929 1.29 bouyer if (dpt_ccb_poll(sc, ccb)) {
930 1.29 bouyer dpt_ccb_abort(sc, ccb);
931 1.29 bouyer /* Wait for abort to complete... */
932 1.29 bouyer if (dpt_ccb_poll(sc, ccb))
933 1.29 bouyer dpt_ccb_abort(sc, ccb);
934 1.29 bouyer }
935 1.1 ad
936 1.29 bouyer dpt_ccb_done(sc, ccb);
937 1.29 bouyer break;
938 1.1 ad
939 1.29 bouyer case ADAPTER_REQ_GROW_RESOURCES:
940 1.29 bouyer /*
941 1.29 bouyer * Not supported, since we allocate the maximum number of
942 1.29 bouyer * CCBs up front.
943 1.29 bouyer */
944 1.29 bouyer break;
945 1.1 ad
946 1.29 bouyer case ADAPTER_REQ_SET_XFER_MODE:
947 1.29 bouyer /*
948 1.29 bouyer * This will be handled by the HBA itself, and we can't
949 1.29 bouyer * modify that (ditto for tagged queueing).
950 1.29 bouyer */
951 1.29 bouyer break;
952 1.1 ad }
953 1.1 ad }
954 1.1 ad
955 1.1 ad /*
956 1.1 ad * Get inquiry data from the adapter.
957 1.1 ad */
958 1.29 bouyer static void
959 1.29 bouyer dpt_hba_inquire(struct dpt_softc *sc, struct eata_inquiry_data **ei)
960 1.1 ad {
961 1.1 ad struct dpt_ccb *ccb;
962 1.1 ad struct eata_cp *cp;
963 1.29 bouyer
964 1.1 ad *ei = (struct eata_inquiry_data *)sc->sc_scr;
965 1.1 ad
966 1.1 ad /* Get a CCB and mark as private */
967 1.29 bouyer ccb = dpt_ccb_alloc(sc);
968 1.1 ad ccb->ccb_flg |= CCB_PRIVATE;
969 1.1 ad ccb->ccb_timeout = 200;
970 1.1 ad
971 1.29 bouyer /* Put all the arguments into the CCB. */
972 1.1 ad cp = &ccb->ccb_eata_cp;
973 1.1 ad cp->cp_ccbid = ccb->ccb_id;
974 1.1 ad cp->cp_senselen = sizeof(ccb->ccb_sense);
975 1.29 bouyer cp->cp_senseaddr = 0;
976 1.19 ad cp->cp_stataddr = htobe32(sc->sc_stppa);
977 1.13 ad cp->cp_dataaddr = htobe32(sc->sc_scrpa);
978 1.13 ad cp->cp_datalen = htobe32(sizeof(struct eata_inquiry_data));
979 1.19 ad cp->cp_ctl0 = CP_C0_DATA_IN | CP_C0_INTERPRET;
980 1.19 ad cp->cp_ctl1 = 0;
981 1.19 ad cp->cp_ctl2 = 0;
982 1.19 ad cp->cp_ctl3 = sc->sc_hbaid[0] << CP_C3_ID_SHIFT;
983 1.19 ad cp->cp_ctl4 = CP_C4_DIS_PRI | CP_C4_IDENTIFY;
984 1.19 ad
985 1.29 bouyer /* Put together the SCSI inquiry command. */
986 1.29 bouyer memset(&cp->cp_cdb_cmd, 0, 12);
987 1.19 ad cp->cp_cdb_cmd = INQUIRY;
988 1.19 ad cp->cp_cdb_len = sizeof(struct eata_inquiry_data);
989 1.1 ad
990 1.29 bouyer /* Sync up CCB, status packet and scratch area. */
991 1.19 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, CCB_OFF(sc, ccb),
992 1.1 ad sizeof(struct dpt_ccb), BUS_DMASYNC_PREWRITE);
993 1.19 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_stpoff,
994 1.1 ad sizeof(struct eata_sp), BUS_DMASYNC_PREREAD);
995 1.19 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_scroff,
996 1.1 ad sizeof(struct eata_inquiry_data), BUS_DMASYNC_PREREAD);
997 1.1 ad
998 1.29 bouyer /* Start the command and poll on completion. */
999 1.29 bouyer if (dpt_cmd(sc, ccb, CP_DMA_CMD, 0))
1000 1.4 ad panic("%s: dpt_cmd failed", sc->sc_dv.dv_xname);
1001 1.1 ad
1002 1.29 bouyer if (dpt_ccb_poll(sc, ccb))
1003 1.1 ad panic("%s: inquiry timed out", sc->sc_dv.dv_xname);
1004 1.1 ad
1005 1.19 ad if (ccb->ccb_hba_status != SP_HBA_NO_ERROR ||
1006 1.1 ad ccb->ccb_scsi_status != SCSI_OK)
1007 1.29 bouyer panic("%s: inquiry failed (hba:%02x scsi:%02x)",
1008 1.29 bouyer sc->sc_dv.dv_xname, ccb->ccb_hba_status,
1009 1.29 bouyer ccb->ccb_scsi_status);
1010 1.29 bouyer
1011 1.29 bouyer /* Sync up the DMA map and free CCB, returning. */
1012 1.19 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, sc->sc_scroff,
1013 1.1 ad sizeof(struct eata_inquiry_data), BUS_DMASYNC_POSTREAD);
1014 1.29 bouyer dpt_ccb_free(sc, ccb);
1015 1.1 ad }
1016