bha.c revision 1.31 1 1.31 thorpej /* $NetBSD: bha.c,v 1.31 1999/09/30 23:12:28 thorpej Exp $ */
2 1.1 mycroft
3 1.13 thorpej /*-
4 1.31 thorpej * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
5 1.13 thorpej * All rights reserved.
6 1.13 thorpej *
7 1.13 thorpej * This code is derived from software contributed to The NetBSD Foundation
8 1.25 mycroft * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
9 1.25 mycroft * Simulation Facility, NASA Ames Research Center.
10 1.13 thorpej *
11 1.13 thorpej * Redistribution and use in source and binary forms, with or without
12 1.13 thorpej * modification, are permitted provided that the following conditions
13 1.13 thorpej * are met:
14 1.13 thorpej * 1. Redistributions of source code must retain the above copyright
15 1.13 thorpej * notice, this list of conditions and the following disclaimer.
16 1.13 thorpej * 2. Redistributions in binary form must reproduce the above copyright
17 1.13 thorpej * notice, this list of conditions and the following disclaimer in the
18 1.13 thorpej * documentation and/or other materials provided with the distribution.
19 1.13 thorpej * 3. All advertising materials mentioning features or use of this software
20 1.13 thorpej * must display the following acknowledgement:
21 1.13 thorpej * This product includes software developed by the NetBSD
22 1.13 thorpej * Foundation, Inc. and its contributors.
23 1.13 thorpej * 4. Neither the name of The NetBSD Foundation nor the names of its
24 1.13 thorpej * contributors may be used to endorse or promote products derived
25 1.13 thorpej * from this software without specific prior written permission.
26 1.13 thorpej *
27 1.13 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 1.13 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 1.13 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 1.13 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 1.13 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.13 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.13 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.13 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.13 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.13 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.13 thorpej * POSSIBILITY OF SUCH DAMAGE.
38 1.1 mycroft */
39 1.1 mycroft
40 1.1 mycroft /*
41 1.1 mycroft * Originally written by Julian Elischer (julian (at) tfs.com)
42 1.1 mycroft * for TRW Financial Systems for use under the MACH(2.5) operating system.
43 1.1 mycroft *
44 1.1 mycroft * TRW Financial Systems, in accordance with their agreement with Carnegie
45 1.1 mycroft * Mellon University, makes this software available to CMU to distribute
46 1.1 mycroft * or use in any manner that they see fit as long as this message is kept with
47 1.1 mycroft * the software. For this reason TFS also grants any other persons or
48 1.1 mycroft * organisations permission to use or modify this software.
49 1.1 mycroft *
50 1.1 mycroft * TFS supplies this software to be publicly redistributed
51 1.1 mycroft * on the understanding that TFS is not responsible for the correct
52 1.1 mycroft * functioning of this software in any circumstances.
53 1.1 mycroft */
54 1.1 mycroft
55 1.31 thorpej #include "opt_ddb.h"
56 1.31 thorpej
57 1.1 mycroft #include <sys/types.h>
58 1.1 mycroft #include <sys/param.h>
59 1.1 mycroft #include <sys/systm.h>
60 1.1 mycroft #include <sys/kernel.h>
61 1.1 mycroft #include <sys/errno.h>
62 1.1 mycroft #include <sys/ioctl.h>
63 1.1 mycroft #include <sys/device.h>
64 1.1 mycroft #include <sys/malloc.h>
65 1.1 mycroft #include <sys/buf.h>
66 1.1 mycroft #include <sys/proc.h>
67 1.1 mycroft #include <sys/user.h>
68 1.1 mycroft
69 1.31 thorpej #include <vm/vm.h> /* for PAGE_SIZE */
70 1.31 thorpej
71 1.1 mycroft #include <machine/bus.h>
72 1.1 mycroft #include <machine/intr.h>
73 1.1 mycroft
74 1.14 bouyer #include <dev/scsipi/scsi_all.h>
75 1.14 bouyer #include <dev/scsipi/scsipi_all.h>
76 1.14 bouyer #include <dev/scsipi/scsiconf.h>
77 1.1 mycroft
78 1.1 mycroft #include <dev/ic/bhareg.h>
79 1.1 mycroft #include <dev/ic/bhavar.h>
80 1.1 mycroft
81 1.1 mycroft #ifndef DDB
82 1.1 mycroft #define Debugger() panic("should call debugger here (bha.c)")
83 1.1 mycroft #endif /* ! DDB */
84 1.1 mycroft
85 1.13 thorpej #define BHA_MAXXFER ((BHA_NSEG - 1) << PGSHIFT)
86 1.1 mycroft
87 1.1 mycroft #ifdef BHADEBUG
88 1.1 mycroft int bha_debug = 0;
89 1.1 mycroft #endif /* BHADEBUG */
90 1.1 mycroft
91 1.31 thorpej int bha_cmd __P((bus_space_tag_t, bus_space_handle_t, struct bha_softc *,
92 1.31 thorpej int, u_char *, int, u_char *));
93 1.31 thorpej
94 1.31 thorpej int bha_scsi_cmd __P((struct scsipi_xfer *));
95 1.31 thorpej void bha_minphys __P((struct buf *));
96 1.31 thorpej
97 1.31 thorpej void bha_done __P((struct bha_softc *, struct bha_ccb *));
98 1.31 thorpej int bha_poll __P((struct bha_softc *, struct scsipi_xfer *, int));
99 1.31 thorpej void bha_timeout __P((void *arg));
100 1.31 thorpej
101 1.31 thorpej int bha_info __P((struct bha_softc *));
102 1.31 thorpej int bha_init __P((struct bha_softc *));
103 1.31 thorpej
104 1.31 thorpej int bha_create_mailbox __P((struct bha_softc *));
105 1.31 thorpej void bha_collect_mbo __P((struct bha_softc *));
106 1.31 thorpej
107 1.31 thorpej void bha_queue_ccb __P((struct bha_softc *, struct bha_ccb *));
108 1.31 thorpej void bha_start_ccbs __P((struct bha_softc *));
109 1.31 thorpej void bha_finish_ccbs __P((struct bha_softc *));
110 1.31 thorpej
111 1.31 thorpej struct bha_ccb *bha_ccb_phys_kv __P((struct bha_softc *, u_long));
112 1.31 thorpej void bha_create_ccbs __P((struct bha_softc *, int));
113 1.31 thorpej int bha_init_ccb __P((struct bha_softc *, struct bha_ccb *));
114 1.1 mycroft struct bha_ccb *bha_get_ccb __P((struct bha_softc *, int));
115 1.31 thorpej void bha_free_ccb __P((struct bha_softc *, struct bha_ccb *));
116 1.1 mycroft
117 1.1 mycroft /* the below structure is so we have a default dev struct for out link struct */
118 1.14 bouyer struct scsipi_device bha_dev = {
119 1.1 mycroft NULL, /* Use default error handler */
120 1.1 mycroft NULL, /* have a queue, served by this */
121 1.1 mycroft NULL, /* have no async handler */
122 1.1 mycroft NULL, /* Use default 'done' routine */
123 1.1 mycroft };
124 1.1 mycroft
125 1.1 mycroft #define BHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
126 1.1 mycroft #define BHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
127 1.13 thorpej
128 1.1 mycroft /*
129 1.31 thorpej * Number of CCBs in an allocation group; must be computed at run-time.
130 1.1 mycroft */
131 1.31 thorpej int bha_ccbs_per_group;
132 1.31 thorpej
133 1.31 thorpej __inline struct bha_mbx_out *bha_nextmbo __P((struct bha_softc *,
134 1.31 thorpej struct bha_mbx_out *));
135 1.31 thorpej __inline struct bha_mbx_in *bha_nextmbi __P((struct bha_softc *,
136 1.31 thorpej struct bha_mbx_in *));
137 1.31 thorpej
138 1.31 thorpej __inline struct bha_mbx_out *
139 1.31 thorpej bha_nextmbo(sc, mbo)
140 1.1 mycroft struct bha_softc *sc;
141 1.31 thorpej struct bha_mbx_out *mbo;
142 1.1 mycroft {
143 1.1 mycroft
144 1.31 thorpej if (mbo == &sc->sc_mbo[sc->sc_mbox_count - 1])
145 1.31 thorpej return (&sc->sc_mbo[0]);
146 1.31 thorpej return (mbo + 1);
147 1.31 thorpej }
148 1.1 mycroft
149 1.31 thorpej __inline struct bha_mbx_in *
150 1.31 thorpej bha_nextmbi(sc, mbi)
151 1.31 thorpej struct bha_softc *sc;
152 1.31 thorpej struct bha_mbx_in *mbi;
153 1.31 thorpej {
154 1.9 mycroft
155 1.31 thorpej if (mbi == &sc->sc_mbi[sc->sc_mbox_count - 1])
156 1.31 thorpej return (&sc->sc_mbi[0]);
157 1.31 thorpej return (mbi + 1);
158 1.1 mycroft }
159 1.1 mycroft
160 1.1 mycroft /*
161 1.31 thorpej * bha_attach:
162 1.31 thorpej *
163 1.31 thorpej * Finish attaching a Buslogic controller, and configure children.
164 1.1 mycroft */
165 1.1 mycroft void
166 1.11 mycroft bha_attach(sc, bpd)
167 1.1 mycroft struct bha_softc *sc;
168 1.11 mycroft struct bha_probe_data *bpd;
169 1.1 mycroft {
170 1.31 thorpej int initial_ccbs;
171 1.31 thorpej
172 1.31 thorpej /*
173 1.31 thorpej * Initialize the number of CCBs per group.
174 1.31 thorpej */
175 1.31 thorpej if (bha_ccbs_per_group == 0)
176 1.31 thorpej bha_ccbs_per_group = BHA_CCBS_PER_GROUP;
177 1.31 thorpej
178 1.31 thorpej initial_ccbs = bha_info(sc);
179 1.31 thorpej if (initial_ccbs == 0) {
180 1.31 thorpej printf("%s: unable to get adapter info\n",
181 1.31 thorpej sc->sc_dev.dv_xname);
182 1.31 thorpej return;
183 1.31 thorpej }
184 1.1 mycroft
185 1.1 mycroft /*
186 1.27 thorpej * Fill in the adapter.
187 1.27 thorpej */
188 1.27 thorpej sc->sc_adapter.scsipi_cmd = bha_scsi_cmd;
189 1.31 thorpej sc->sc_adapter.scsipi_minphys = bha_minphys;
190 1.27 thorpej
191 1.27 thorpej /*
192 1.14 bouyer * fill in the prototype scsipi_link.
193 1.1 mycroft */
194 1.14 bouyer sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
195 1.1 mycroft sc->sc_link.adapter_softc = sc;
196 1.31 thorpej sc->sc_link.scsipi_scsi.adapter_target = sc->sc_scsi_id;
197 1.27 thorpej sc->sc_link.adapter = &sc->sc_adapter;
198 1.1 mycroft sc->sc_link.device = &bha_dev;
199 1.1 mycroft sc->sc_link.openings = 4;
200 1.31 thorpej sc->sc_link.scsipi_scsi.max_target =
201 1.31 thorpej (sc->sc_flags & BHAF_WIDE) ? 15 : 7;
202 1.31 thorpej sc->sc_link.scsipi_scsi.max_lun =
203 1.31 thorpej (sc->sc_flags & BHAF_WIDE_LUN) ? 31 : 7;
204 1.14 bouyer sc->sc_link.type = BUS_SCSI;
205 1.12 thorpej
206 1.13 thorpej TAILQ_INIT(&sc->sc_free_ccb);
207 1.13 thorpej TAILQ_INIT(&sc->sc_waiting_ccb);
208 1.31 thorpej TAILQ_INIT(&sc->sc_allocating_ccbs);
209 1.29 thorpej TAILQ_INIT(&sc->sc_queue);
210 1.13 thorpej
211 1.31 thorpej if (bha_create_mailbox(sc) != 0)
212 1.22 thorpej return;
213 1.1 mycroft
214 1.31 thorpej bha_create_ccbs(sc, initial_ccbs);
215 1.31 thorpej if (sc->sc_cur_ccbs < 2) {
216 1.31 thorpej printf("%s: not enough CCBs to run\n",
217 1.1 mycroft sc->sc_dev.dv_xname);
218 1.1 mycroft return;
219 1.1 mycroft }
220 1.1 mycroft
221 1.31 thorpej if (bha_init(sc) != 0)
222 1.31 thorpej return;
223 1.1 mycroft
224 1.31 thorpej (void) config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
225 1.1 mycroft }
226 1.1 mycroft
227 1.1 mycroft /*
228 1.31 thorpej * bha_intr:
229 1.31 thorpej *
230 1.31 thorpej * Interrupt service routine.
231 1.1 mycroft */
232 1.1 mycroft int
233 1.1 mycroft bha_intr(arg)
234 1.1 mycroft void *arg;
235 1.1 mycroft {
236 1.1 mycroft struct bha_softc *sc = arg;
237 1.4 thorpej bus_space_tag_t iot = sc->sc_iot;
238 1.4 thorpej bus_space_handle_t ioh = sc->sc_ioh;
239 1.1 mycroft u_char sts;
240 1.1 mycroft
241 1.1 mycroft #ifdef BHADEBUG
242 1.3 christos printf("%s: bha_intr ", sc->sc_dev.dv_xname);
243 1.1 mycroft #endif /* BHADEBUG */
244 1.1 mycroft
245 1.1 mycroft /*
246 1.1 mycroft * First acknowlege the interrupt, Then if it's not telling about
247 1.1 mycroft * a completed operation just return.
248 1.1 mycroft */
249 1.4 thorpej sts = bus_space_read_1(iot, ioh, BHA_INTR_PORT);
250 1.1 mycroft if ((sts & BHA_INTR_ANYINTR) == 0)
251 1.1 mycroft return (0);
252 1.4 thorpej bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_IRST);
253 1.1 mycroft
254 1.1 mycroft #ifdef BHADIAG
255 1.1 mycroft /* Make sure we clear CCB_SENDING before finishing a CCB. */
256 1.1 mycroft bha_collect_mbo(sc);
257 1.1 mycroft #endif
258 1.1 mycroft
259 1.1 mycroft /* Mail box out empty? */
260 1.1 mycroft if (sts & BHA_INTR_MBOA) {
261 1.1 mycroft struct bha_toggle toggle;
262 1.1 mycroft
263 1.1 mycroft toggle.cmd.opcode = BHA_MBO_INTR_EN;
264 1.1 mycroft toggle.cmd.enable = 0;
265 1.4 thorpej bha_cmd(iot, ioh, sc,
266 1.1 mycroft sizeof(toggle.cmd), (u_char *)&toggle.cmd,
267 1.1 mycroft 0, (u_char *)0);
268 1.1 mycroft bha_start_ccbs(sc);
269 1.1 mycroft }
270 1.1 mycroft
271 1.1 mycroft /* Mail box in full? */
272 1.1 mycroft if (sts & BHA_INTR_MBIF)
273 1.1 mycroft bha_finish_ccbs(sc);
274 1.1 mycroft
275 1.1 mycroft return (1);
276 1.1 mycroft }
277 1.1 mycroft
278 1.31 thorpej /*****************************************************************************
279 1.31 thorpej * SCSI interface routines
280 1.31 thorpej *****************************************************************************/
281 1.1 mycroft
282 1.1 mycroft /*
283 1.31 thorpej * bha_scsi_cmd:
284 1.31 thorpej *
285 1.31 thorpej * Start a SCSI operation.
286 1.1 mycroft */
287 1.31 thorpej int
288 1.31 thorpej bha_scsi_cmd(xs)
289 1.31 thorpej struct scsipi_xfer *xs;
290 1.31 thorpej {
291 1.31 thorpej struct scsipi_link *sc_link = xs->sc_link;
292 1.31 thorpej struct bha_softc *sc = sc_link->adapter_softc;
293 1.31 thorpej bus_dma_tag_t dmat = sc->sc_dmat;
294 1.1 mycroft struct bha_ccb *ccb;
295 1.31 thorpej int error, seg, flags, s;
296 1.31 thorpej int fromqueue = 0, dontqueue = 0;
297 1.1 mycroft
298 1.31 thorpej SC_DEBUG(sc_link, SDEV_DB2, ("bha_scsi_cmd\n"));
299 1.1 mycroft
300 1.31 thorpej s = splbio(); /* protect the queue */
301 1.1 mycroft
302 1.1 mycroft /*
303 1.31 thorpej * If we're running the queue from bha_done(), we've been
304 1.31 thorpej * called with the first queue entry as our argument.
305 1.1 mycroft */
306 1.31 thorpej if (xs == TAILQ_FIRST(&sc->sc_queue)) {
307 1.31 thorpej TAILQ_REMOVE(&sc->sc_queue, xs, adapter_q);
308 1.31 thorpej fromqueue = 1;
309 1.31 thorpej goto get_ccb;
310 1.31 thorpej }
311 1.31 thorpej
312 1.31 thorpej /* Polled requests can't be queued for later. */
313 1.31 thorpej dontqueue = xs->xs_control & XS_CTL_POLL;
314 1.1 mycroft
315 1.31 thorpej /*
316 1.31 thorpej * If there are jobs in the queue, run them first.
317 1.31 thorpej */
318 1.31 thorpej if (TAILQ_FIRST(&sc->sc_queue) != NULL) {
319 1.31 thorpej /*
320 1.31 thorpej * If we can't queue, we have to abort, since
321 1.31 thorpej * we have to preserve order.
322 1.31 thorpej */
323 1.31 thorpej if (dontqueue) {
324 1.31 thorpej splx(s);
325 1.31 thorpej xs->error = XS_DRIVER_STUFFUP;
326 1.31 thorpej return (TRY_AGAIN_LATER);
327 1.31 thorpej }
328 1.1 mycroft
329 1.31 thorpej /*
330 1.31 thorpej * Swap with the first queue entry.
331 1.31 thorpej */
332 1.31 thorpej TAILQ_INSERT_TAIL(&sc->sc_queue, xs, adapter_q);
333 1.31 thorpej xs = TAILQ_FIRST(&sc->sc_queue);
334 1.31 thorpej TAILQ_REMOVE(&sc->sc_queue, xs, adapter_q);
335 1.31 thorpej fromqueue = 1;
336 1.31 thorpej }
337 1.1 mycroft
338 1.31 thorpej get_ccb:
339 1.13 thorpej /*
340 1.31 thorpej * get a ccb to use. If the transfer
341 1.31 thorpej * is from a buf (possibly from interrupt time)
342 1.31 thorpej * then we can't allow it to sleep
343 1.13 thorpej */
344 1.31 thorpej flags = xs->xs_control;
345 1.31 thorpej if ((ccb = bha_get_ccb(sc, flags)) == NULL) {
346 1.31 thorpej /*
347 1.31 thorpej * If we can't queue, we lose.
348 1.31 thorpej */
349 1.31 thorpej if (dontqueue) {
350 1.31 thorpej splx(s);
351 1.31 thorpej xs->error = XS_DRIVER_STUFFUP;
352 1.31 thorpej return (TRY_AGAIN_LATER);
353 1.31 thorpej }
354 1.31 thorpej
355 1.31 thorpej /*
356 1.31 thorpej * Stuff ourselves into the queue, in front
357 1.31 thorpej * if we came off in the first place.
358 1.31 thorpej */
359 1.31 thorpej if (fromqueue)
360 1.31 thorpej TAILQ_INSERT_HEAD(&sc->sc_queue, xs, adapter_q);
361 1.31 thorpej else
362 1.31 thorpej TAILQ_INSERT_TAIL(&sc->sc_queue, xs, adapter_q);
363 1.31 thorpej splx(s);
364 1.31 thorpej return (SUCCESSFULLY_QUEUED);
365 1.16 thorpej }
366 1.13 thorpej
367 1.31 thorpej splx(s); /* done playing with the queue */
368 1.31 thorpej
369 1.31 thorpej ccb->xs = xs;
370 1.31 thorpej ccb->timeout = xs->timeout;
371 1.31 thorpej
372 1.1 mycroft /*
373 1.31 thorpej * Put all the arguments for the xfer in the ccb
374 1.1 mycroft */
375 1.31 thorpej if (flags & XS_CTL_RESET) {
376 1.31 thorpej ccb->opcode = BHA_RESET_CCB;
377 1.31 thorpej ccb->scsi_cmd_length = 0;
378 1.31 thorpej } else {
379 1.31 thorpej /* can't use S/G if zero length */
380 1.31 thorpej ccb->opcode = (xs->datalen ? BHA_INIT_SCAT_GATH_CCB
381 1.31 thorpej : BHA_INITIATOR_CCB);
382 1.31 thorpej bcopy(xs->cmd, &ccb->scsi_cmd,
383 1.31 thorpej ccb->scsi_cmd_length = xs->cmdlen);
384 1.31 thorpej }
385 1.1 mycroft
386 1.31 thorpej if (xs->datalen) {
387 1.31 thorpej /*
388 1.31 thorpej * Map the DMA transfer.
389 1.31 thorpej */
390 1.31 thorpej #ifdef TFS
391 1.31 thorpej if (flags & XS_CTL_DATA_UIO) {
392 1.31 thorpej error = bus_dmamap_load_uio(dmat,
393 1.31 thorpej ccb->dmamap_xfer, (struct uio *)xs->data,
394 1.31 thorpej (flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT :
395 1.31 thorpej BUS_DMA_WAITOK);
396 1.31 thorpej } else
397 1.31 thorpej #endif /* TFS */
398 1.31 thorpej {
399 1.31 thorpej error = bus_dmamap_load(dmat,
400 1.31 thorpej ccb->dmamap_xfer, xs->data, xs->datalen, NULL,
401 1.31 thorpej (flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT :
402 1.31 thorpej BUS_DMA_WAITOK);
403 1.31 thorpej }
404 1.13 thorpej
405 1.31 thorpej if (error) {
406 1.31 thorpej if (error == EFBIG) {
407 1.31 thorpej printf("%s: bha_scsi_cmd, more than %d"
408 1.31 thorpej " dma segments\n",
409 1.31 thorpej sc->sc_dev.dv_xname, BHA_NSEG);
410 1.31 thorpej } else {
411 1.31 thorpej printf("%s: bha_scsi_cmd, error %d loading"
412 1.31 thorpej " dma map\n",
413 1.31 thorpej sc->sc_dev.dv_xname, error);
414 1.31 thorpej }
415 1.31 thorpej goto bad;
416 1.16 thorpej }
417 1.13 thorpej
418 1.31 thorpej bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0,
419 1.31 thorpej ccb->dmamap_xfer->dm_mapsize,
420 1.31 thorpej (flags & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
421 1.31 thorpej BUS_DMASYNC_PREWRITE);
422 1.1 mycroft
423 1.31 thorpej /*
424 1.31 thorpej * Load the hardware scatter/gather map with the
425 1.31 thorpej * contents of the DMA map.
426 1.31 thorpej */
427 1.31 thorpej for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) {
428 1.31 thorpej ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr,
429 1.31 thorpej ccb->scat_gath[seg].seg_addr);
430 1.31 thorpej ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len,
431 1.31 thorpej ccb->scat_gath[seg].seg_len);
432 1.31 thorpej }
433 1.1 mycroft
434 1.31 thorpej ltophys(ccb->hashkey + offsetof(struct bha_ccb, scat_gath),
435 1.31 thorpej ccb->data_addr);
436 1.31 thorpej ltophys(ccb->dmamap_xfer->dm_nsegs *
437 1.31 thorpej sizeof(struct bha_scat_gath), ccb->data_length);
438 1.31 thorpej } else {
439 1.31 thorpej /*
440 1.31 thorpej * No data xfer, use non S/G values.
441 1.31 thorpej */
442 1.31 thorpej ltophys(0, ccb->data_addr);
443 1.31 thorpej ltophys(0, ccb->data_length);
444 1.1 mycroft }
445 1.1 mycroft
446 1.31 thorpej ccb->data_out = 0;
447 1.31 thorpej ccb->data_in = 0;
448 1.31 thorpej ccb->target = sc_link->scsipi_scsi.target;
449 1.31 thorpej ccb->lun = sc_link->scsipi_scsi.lun;
450 1.31 thorpej ltophys(ccb->hashkey + offsetof(struct bha_ccb, scsi_sense),
451 1.31 thorpej ccb->sense_ptr);
452 1.31 thorpej ccb->req_sense_length = sizeof(ccb->scsi_sense);
453 1.31 thorpej ccb->host_stat = 0x00;
454 1.31 thorpej ccb->target_stat = 0x00;
455 1.31 thorpej ccb->link_id = 0;
456 1.31 thorpej ltophys(0, ccb->link_addr);
457 1.31 thorpej
458 1.31 thorpej BHA_CCB_SYNC(sc, ccb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
459 1.1 mycroft
460 1.31 thorpej s = splbio();
461 1.31 thorpej bha_queue_ccb(sc, ccb);
462 1.1 mycroft splx(s);
463 1.1 mycroft
464 1.31 thorpej SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
465 1.31 thorpej if ((flags & XS_CTL_POLL) == 0)
466 1.31 thorpej return (SUCCESSFULLY_QUEUED);
467 1.1 mycroft
468 1.31 thorpej /*
469 1.31 thorpej * If we can't use interrupts, poll on completion
470 1.31 thorpej */
471 1.31 thorpej if (bha_poll(sc, xs, ccb->timeout)) {
472 1.31 thorpej bha_timeout(ccb);
473 1.31 thorpej if (bha_poll(sc, xs, ccb->timeout))
474 1.31 thorpej bha_timeout(ccb);
475 1.1 mycroft }
476 1.31 thorpej return (COMPLETE);
477 1.31 thorpej
478 1.31 thorpej bad:
479 1.31 thorpej xs->error = XS_DRIVER_STUFFUP;
480 1.31 thorpej bha_free_ccb(sc, ccb);
481 1.31 thorpej return (COMPLETE);
482 1.1 mycroft }
483 1.1 mycroft
484 1.1 mycroft /*
485 1.31 thorpej * bha_minphys:
486 1.31 thorpej *
487 1.31 thorpej * Limit a transfer to our maximum transfer size.
488 1.1 mycroft */
489 1.1 mycroft void
490 1.31 thorpej bha_minphys(bp)
491 1.31 thorpej struct buf *bp;
492 1.1 mycroft {
493 1.1 mycroft
494 1.31 thorpej if (bp->b_bcount > BHA_MAXXFER)
495 1.31 thorpej bp->b_bcount = BHA_MAXXFER;
496 1.31 thorpej minphys(bp);
497 1.1 mycroft }
498 1.1 mycroft
499 1.31 thorpej /*****************************************************************************
500 1.31 thorpej * SCSI job execution helper routines
501 1.31 thorpej *****************************************************************************/
502 1.31 thorpej
503 1.1 mycroft /*
504 1.31 thorpej * bha_done:
505 1.31 thorpej *
506 1.31 thorpej * A CCB has completed execution. Pass the status back to the
507 1.31 thorpej * upper layer.
508 1.1 mycroft */
509 1.1 mycroft void
510 1.31 thorpej bha_done(sc, ccb)
511 1.1 mycroft struct bha_softc *sc;
512 1.31 thorpej struct bha_ccb *ccb;
513 1.1 mycroft {
514 1.31 thorpej bus_dma_tag_t dmat = sc->sc_dmat;
515 1.31 thorpej struct scsipi_xfer *xs = ccb->xs;
516 1.1 mycroft
517 1.31 thorpej SC_DEBUG(xs->sc_link, SDEV_DB2, ("bha_done\n"));
518 1.1 mycroft
519 1.1 mycroft #ifdef BHADIAG
520 1.31 thorpej if (ccb->flags & CCB_SENDING) {
521 1.31 thorpej printf("%s: exiting ccb still in transit!\n",
522 1.31 thorpej sc->sc_dev.dv_xname);
523 1.31 thorpej Debugger();
524 1.31 thorpej return;
525 1.31 thorpej }
526 1.1 mycroft #endif
527 1.31 thorpej if ((ccb->flags & CCB_ALLOC) == 0) {
528 1.31 thorpej printf("%s: exiting ccb not allocated!\n",
529 1.31 thorpej sc->sc_dev.dv_xname);
530 1.31 thorpej Debugger();
531 1.31 thorpej return;
532 1.31 thorpej }
533 1.1 mycroft
534 1.31 thorpej /*
535 1.31 thorpej * If we were a data transfer, unload the map that described
536 1.31 thorpej * the data buffer.
537 1.31 thorpej */
538 1.31 thorpej if (xs->datalen) {
539 1.31 thorpej bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0,
540 1.31 thorpej ccb->dmamap_xfer->dm_mapsize,
541 1.31 thorpej (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD :
542 1.31 thorpej BUS_DMASYNC_POSTWRITE);
543 1.31 thorpej bus_dmamap_unload(dmat, ccb->dmamap_xfer);
544 1.1 mycroft }
545 1.1 mycroft
546 1.31 thorpej if (xs->error == XS_NOERROR) {
547 1.31 thorpej if (ccb->host_stat != BHA_OK) {
548 1.31 thorpej switch (ccb->host_stat) {
549 1.31 thorpej case BHA_SEL_TIMEOUT: /* No response */
550 1.31 thorpej xs->error = XS_SELTIMEOUT;
551 1.31 thorpej break;
552 1.31 thorpej default: /* Other scsi protocol messes */
553 1.31 thorpej printf("%s: host_stat %x\n",
554 1.1 mycroft sc->sc_dev.dv_xname, ccb->host_stat);
555 1.1 mycroft xs->error = XS_DRIVER_STUFFUP;
556 1.1 mycroft break;
557 1.1 mycroft }
558 1.1 mycroft } else if (ccb->target_stat != SCSI_OK) {
559 1.1 mycroft switch (ccb->target_stat) {
560 1.1 mycroft case SCSI_CHECK:
561 1.31 thorpej memcpy(&xs->sense.scsi_sense,
562 1.31 thorpej &ccb->scsi_sense,
563 1.31 thorpej sizeof(xs->sense.scsi_sense));
564 1.1 mycroft xs->error = XS_SENSE;
565 1.1 mycroft break;
566 1.1 mycroft case SCSI_BUSY:
567 1.1 mycroft xs->error = XS_BUSY;
568 1.1 mycroft break;
569 1.1 mycroft default:
570 1.3 christos printf("%s: target_stat %x\n",
571 1.1 mycroft sc->sc_dev.dv_xname, ccb->target_stat);
572 1.1 mycroft xs->error = XS_DRIVER_STUFFUP;
573 1.1 mycroft break;
574 1.1 mycroft }
575 1.1 mycroft } else
576 1.1 mycroft xs->resid = 0;
577 1.1 mycroft }
578 1.31 thorpej
579 1.1 mycroft bha_free_ccb(sc, ccb);
580 1.31 thorpej
581 1.31 thorpej xs->xs_status |= XS_STS_DONE;
582 1.14 bouyer scsipi_done(xs);
583 1.17 thorpej
584 1.17 thorpej /*
585 1.17 thorpej * If there are queue entries in the software queue, try to
586 1.17 thorpej * run the first one. We should be more or less guaranteed
587 1.17 thorpej * to succeed, since we just freed a CCB.
588 1.17 thorpej *
589 1.17 thorpej * NOTE: bha_scsi_cmd() relies on our calling it with
590 1.17 thorpej * the first entry in the queue.
591 1.17 thorpej */
592 1.29 thorpej if ((xs = TAILQ_FIRST(&sc->sc_queue)) != NULL)
593 1.17 thorpej (void) bha_scsi_cmd(xs);
594 1.1 mycroft }
595 1.1 mycroft
596 1.1 mycroft /*
597 1.31 thorpej * bha_poll:
598 1.31 thorpej *
599 1.31 thorpej * Poll for completion of the specified job.
600 1.31 thorpej */
601 1.31 thorpej int
602 1.31 thorpej bha_poll(sc, xs, count)
603 1.31 thorpej struct bha_softc *sc;
604 1.31 thorpej struct scsipi_xfer *xs;
605 1.31 thorpej int count;
606 1.31 thorpej {
607 1.31 thorpej bus_space_tag_t iot = sc->sc_iot;
608 1.31 thorpej bus_space_handle_t ioh = sc->sc_ioh;
609 1.31 thorpej
610 1.31 thorpej /* timeouts are in msec, so we loop in 1000 usec cycles */
611 1.31 thorpej while (count) {
612 1.31 thorpej /*
613 1.31 thorpej * If we had interrupts enabled, would we
614 1.31 thorpej * have got an interrupt?
615 1.31 thorpej */
616 1.31 thorpej if (bus_space_read_1(iot, ioh, BHA_INTR_PORT) &
617 1.31 thorpej BHA_INTR_ANYINTR)
618 1.31 thorpej bha_intr(sc);
619 1.31 thorpej if (xs->xs_status & XS_STS_DONE)
620 1.31 thorpej return (0);
621 1.31 thorpej delay(1000); /* only happens in boot so ok */
622 1.31 thorpej count--;
623 1.31 thorpej }
624 1.31 thorpej return (1);
625 1.31 thorpej }
626 1.31 thorpej
627 1.31 thorpej /*
628 1.31 thorpej * bha_timeout:
629 1.31 thorpej *
630 1.31 thorpej * CCB timeout handler.
631 1.31 thorpej */
632 1.31 thorpej void
633 1.31 thorpej bha_timeout(arg)
634 1.31 thorpej void *arg;
635 1.31 thorpej {
636 1.31 thorpej struct bha_ccb *ccb = arg;
637 1.31 thorpej struct scsipi_xfer *xs = ccb->xs;
638 1.31 thorpej struct scsipi_link *sc_link = xs->sc_link;
639 1.31 thorpej struct bha_softc *sc = sc_link->adapter_softc;
640 1.31 thorpej int s;
641 1.31 thorpej
642 1.31 thorpej scsi_print_addr(sc_link);
643 1.31 thorpej printf("timed out");
644 1.31 thorpej
645 1.31 thorpej s = splbio();
646 1.31 thorpej
647 1.31 thorpej #ifdef BHADIAG
648 1.31 thorpej /*
649 1.31 thorpej * If the ccb's mbx is not free, then the board has gone Far East?
650 1.31 thorpej */
651 1.31 thorpej bha_collect_mbo(sc);
652 1.31 thorpej if (ccb->flags & CCB_SENDING) {
653 1.31 thorpej printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
654 1.31 thorpej Debugger();
655 1.31 thorpej }
656 1.31 thorpej #endif
657 1.31 thorpej
658 1.31 thorpej /*
659 1.31 thorpej * If it has been through before, then
660 1.31 thorpej * a previous abort has failed, don't
661 1.31 thorpej * try abort again
662 1.31 thorpej */
663 1.31 thorpej if (ccb->flags & CCB_ABORT) {
664 1.31 thorpej /* abort timed out */
665 1.31 thorpej printf(" AGAIN\n");
666 1.31 thorpej /* XXX Must reset! */
667 1.31 thorpej } else {
668 1.31 thorpej /* abort the operation that has timed out */
669 1.31 thorpej printf("\n");
670 1.31 thorpej ccb->xs->error = XS_TIMEOUT;
671 1.31 thorpej ccb->timeout = BHA_ABORT_TIMEOUT;
672 1.31 thorpej ccb->flags |= CCB_ABORT;
673 1.31 thorpej bha_queue_ccb(sc, ccb);
674 1.31 thorpej }
675 1.31 thorpej
676 1.31 thorpej splx(s);
677 1.31 thorpej }
678 1.31 thorpej
679 1.31 thorpej /*****************************************************************************
680 1.31 thorpej * Misc. subroutines.
681 1.31 thorpej *****************************************************************************/
682 1.31 thorpej
683 1.31 thorpej /*
684 1.31 thorpej * bha_cmd:
685 1.31 thorpej *
686 1.31 thorpej * Send a command to the Buglogic controller.
687 1.1 mycroft */
688 1.1 mycroft int
689 1.31 thorpej bha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
690 1.4 thorpej bus_space_tag_t iot;
691 1.4 thorpej bus_space_handle_t ioh;
692 1.31 thorpej struct bha_softc *sc;
693 1.31 thorpej int icnt, ocnt;
694 1.31 thorpej u_char *ibuf, *obuf;
695 1.1 mycroft {
696 1.31 thorpej const char *name;
697 1.31 thorpej register int i;
698 1.31 thorpej int wait;
699 1.1 mycroft u_char sts;
700 1.31 thorpej u_char opcode = ibuf[0];
701 1.1 mycroft
702 1.31 thorpej if (sc != NULL)
703 1.31 thorpej name = sc->sc_dev.dv_xname;
704 1.31 thorpej else
705 1.31 thorpej name = "(bha probe)";
706 1.5 jonathan
707 1.1 mycroft /*
708 1.31 thorpej * Calculate a reasonable timeout for the command.
709 1.1 mycroft */
710 1.31 thorpej switch (opcode) {
711 1.31 thorpej case BHA_INQUIRE_DEVICES:
712 1.31 thorpej case BHA_INQUIRE_DEVICES_2:
713 1.31 thorpej wait = 90 * 20000;
714 1.31 thorpej break;
715 1.31 thorpej default:
716 1.31 thorpej wait = 1 * 20000;
717 1.31 thorpej break;
718 1.1 mycroft }
719 1.1 mycroft
720 1.1 mycroft /*
721 1.31 thorpej * Wait for the adapter to go idle, unless it's one of
722 1.31 thorpej * the commands which don't need this
723 1.5 jonathan */
724 1.31 thorpej if (opcode != BHA_MBO_INTR_EN) {
725 1.31 thorpej for (i = 20000; i; i--) { /* 1 sec? */
726 1.31 thorpej sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
727 1.31 thorpej if (sts & BHA_STAT_IDLE)
728 1.31 thorpej break;
729 1.31 thorpej delay(50);
730 1.31 thorpej }
731 1.31 thorpej if (!i) {
732 1.31 thorpej printf("%s: bha_cmd, host not idle(0x%x)\n",
733 1.31 thorpej name, sts);
734 1.31 thorpej return (1);
735 1.31 thorpej }
736 1.31 thorpej }
737 1.5 jonathan
738 1.5 jonathan /*
739 1.31 thorpej * Now that it is idle, if we expect output, preflush the
740 1.31 thorpej * queue feeding to us.
741 1.5 jonathan */
742 1.31 thorpej if (ocnt) {
743 1.31 thorpej while ((bus_space_read_1(iot, ioh, BHA_STAT_PORT)) &
744 1.31 thorpej BHA_STAT_DF)
745 1.31 thorpej bus_space_read_1(iot, ioh, BHA_DATA_PORT);
746 1.31 thorpej }
747 1.31 thorpej
748 1.31 thorpej /*
749 1.31 thorpej * Output the command and the number of arguments given
750 1.31 thorpej * for each byte, first check the port is empty.
751 1.31 thorpej */
752 1.31 thorpej while (icnt--) {
753 1.31 thorpej for (i = wait; i; i--) {
754 1.31 thorpej sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
755 1.31 thorpej if (!(sts & BHA_STAT_CDF))
756 1.31 thorpej break;
757 1.31 thorpej delay(50);
758 1.31 thorpej }
759 1.31 thorpej if (!i) {
760 1.31 thorpej if (opcode != BHA_INQUIRE_REVISION)
761 1.31 thorpej printf("%s: bha_cmd, cmd/data port full\n",
762 1.31 thorpej name);
763 1.31 thorpej goto bad;
764 1.31 thorpej }
765 1.31 thorpej bus_space_write_1(iot, ioh, BHA_CMD_PORT, *ibuf++);
766 1.31 thorpej }
767 1.31 thorpej
768 1.31 thorpej /*
769 1.31 thorpej * If we expect input, loop that many times, each time,
770 1.31 thorpej * looking for the data register to have valid data
771 1.31 thorpej */
772 1.31 thorpej while (ocnt--) {
773 1.31 thorpej for (i = wait; i; i--) {
774 1.31 thorpej sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
775 1.31 thorpej if (sts & BHA_STAT_DF)
776 1.31 thorpej break;
777 1.31 thorpej delay(50);
778 1.31 thorpej }
779 1.31 thorpej if (!i) {
780 1.31 thorpej if (opcode != BHA_INQUIRE_REVISION)
781 1.31 thorpej printf("%s: bha_cmd, cmd/data port empty %d\n",
782 1.31 thorpej name, ocnt);
783 1.31 thorpej goto bad;
784 1.31 thorpej }
785 1.31 thorpej *obuf++ = bus_space_read_1(iot, ioh, BHA_DATA_PORT);
786 1.31 thorpej }
787 1.31 thorpej
788 1.31 thorpej /*
789 1.31 thorpej * Wait for the board to report a finished instruction.
790 1.31 thorpej * We may get an extra interrupt for the HACC signal, but this is
791 1.31 thorpej * unimportant.
792 1.31 thorpej */
793 1.31 thorpej if (opcode != BHA_MBO_INTR_EN && opcode != BHA_MODIFY_IOPORT) {
794 1.31 thorpej for (i = 20000; i; i--) { /* 1 sec? */
795 1.31 thorpej sts = bus_space_read_1(iot, ioh, BHA_INTR_PORT);
796 1.31 thorpej /* XXX Need to save this in the interrupt handler? */
797 1.31 thorpej if (sts & BHA_INTR_HACC)
798 1.31 thorpej break;
799 1.31 thorpej delay(50);
800 1.31 thorpej }
801 1.31 thorpej if (!i) {
802 1.31 thorpej printf("%s: bha_cmd, host not finished(0x%x)\n",
803 1.31 thorpej name, sts);
804 1.31 thorpej return (1);
805 1.31 thorpej }
806 1.31 thorpej }
807 1.31 thorpej bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_IRST);
808 1.31 thorpej return (0);
809 1.31 thorpej
810 1.31 thorpej bad:
811 1.31 thorpej bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_SRST);
812 1.31 thorpej return (1);
813 1.31 thorpej }
814 1.31 thorpej
815 1.31 thorpej /*
816 1.31 thorpej * bha_find:
817 1.31 thorpej *
818 1.31 thorpej * Find the board and determine it's irq/drq.
819 1.31 thorpej */
820 1.31 thorpej int
821 1.31 thorpej bha_find(iot, ioh, sc)
822 1.31 thorpej bus_space_tag_t iot;
823 1.31 thorpej bus_space_handle_t ioh;
824 1.31 thorpej struct bha_probe_data *sc;
825 1.31 thorpej {
826 1.31 thorpej int i;
827 1.31 thorpej u_char sts;
828 1.31 thorpej struct bha_extended_inquire inquire;
829 1.31 thorpej struct bha_config config;
830 1.31 thorpej int irq, drq;
831 1.31 thorpej
832 1.31 thorpej /* Check something is at the ports we need to access */
833 1.31 thorpej sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
834 1.31 thorpej if (sts == 0xFF)
835 1.31 thorpej return (0);
836 1.31 thorpej
837 1.31 thorpej /*
838 1.31 thorpej * Reset board, If it doesn't respond, assume
839 1.31 thorpej * that it's not there.. good for the probe
840 1.31 thorpej */
841 1.31 thorpej
842 1.31 thorpej bus_space_write_1(iot, ioh, BHA_CTRL_PORT,
843 1.31 thorpej BHA_CTRL_HRST | BHA_CTRL_SRST);
844 1.31 thorpej
845 1.31 thorpej delay(100);
846 1.31 thorpej for (i = BHA_RESET_TIMEOUT; i; i--) {
847 1.31 thorpej sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
848 1.31 thorpej if (sts == (BHA_STAT_IDLE | BHA_STAT_INIT))
849 1.31 thorpej break;
850 1.31 thorpej delay(1000);
851 1.31 thorpej }
852 1.31 thorpej if (!i) {
853 1.31 thorpej #ifdef BHADEBUG
854 1.31 thorpej if (bha_debug)
855 1.31 thorpej printf("bha_find: No answer from buslogic board\n");
856 1.31 thorpej #endif /* BHADEBUG */
857 1.31 thorpej return (0);
858 1.31 thorpej }
859 1.31 thorpej
860 1.31 thorpej /*
861 1.31 thorpej * The BusLogic cards implement an Adaptec 1542 (aha)-compatible
862 1.31 thorpej * interface. The native bha interface is not compatible with
863 1.31 thorpej * an aha. 1542. We need to ensure that we never match an
864 1.31 thorpej * Adaptec 1542. We must also avoid sending Adaptec-compatible
865 1.31 thorpej * commands to a real bha, lest it go into 1542 emulation mode.
866 1.31 thorpej * (On an indirect bus like ISA, we should always probe for BusLogic
867 1.31 thorpej * interfaces before Adaptec interfaces).
868 1.31 thorpej */
869 1.31 thorpej
870 1.31 thorpej /*
871 1.31 thorpej * Make sure we don't match an AHA-1542A or AHA-1542B, by checking
872 1.31 thorpej * for an extended-geometry register. The 1542[AB] don't have one.
873 1.31 thorpej */
874 1.31 thorpej sts = bus_space_read_1(iot, ioh, BHA_EXTGEOM_PORT);
875 1.31 thorpej if (sts == 0xFF)
876 1.31 thorpej return (0);
877 1.5 jonathan
878 1.5 jonathan /*
879 1.1 mycroft * Check that we actually know how to use this board.
880 1.1 mycroft */
881 1.1 mycroft delay(1000);
882 1.1 mycroft inquire.cmd.opcode = BHA_INQUIRE_EXTENDED;
883 1.1 mycroft inquire.cmd.len = sizeof(inquire.reply);
884 1.11 mycroft i = bha_cmd(iot, ioh, (struct bha_softc *)0,
885 1.9 mycroft sizeof(inquire.cmd), (u_char *)&inquire.cmd,
886 1.9 mycroft sizeof(inquire.reply), (u_char *)&inquire.reply);
887 1.5 jonathan
888 1.5 jonathan /*
889 1.5 jonathan * Some 1542Cs (CP, perhaps not CF, may depend on firmware rev)
890 1.5 jonathan * have the extended-geometry register and also respond to
891 1.31 thorpej * BHA_INQUIRE_EXTENDED. Make sure we never match such cards,
892 1.5 jonathan * by checking the size of the reply is what a BusLogic card returns.
893 1.5 jonathan */
894 1.9 mycroft if (i) {
895 1.5 jonathan #ifdef BHADEBUG
896 1.5 jonathan printf("bha_find: board returned %d instead of %d to %s\n",
897 1.5 jonathan i, sizeof(inquire.reply), "INQUIRE_EXTENDED");
898 1.5 jonathan #endif
899 1.5 jonathan return (0);
900 1.5 jonathan }
901 1.5 jonathan
902 1.5 jonathan /* OK, we know we've found a buslogic adaptor. */
903 1.5 jonathan
904 1.1 mycroft switch (inquire.reply.bus_type) {
905 1.1 mycroft case BHA_BUS_TYPE_24BIT:
906 1.1 mycroft case BHA_BUS_TYPE_32BIT:
907 1.1 mycroft break;
908 1.1 mycroft case BHA_BUS_TYPE_MCA:
909 1.1 mycroft /* We don't grok MicroChannel (yet). */
910 1.1 mycroft return (0);
911 1.1 mycroft default:
912 1.4 thorpej printf("bha_find: illegal bus type %c\n",
913 1.4 thorpej inquire.reply.bus_type);
914 1.1 mycroft return (0);
915 1.1 mycroft }
916 1.1 mycroft
917 1.1 mycroft /*
918 1.1 mycroft * Assume we have a board at this stage setup dma channel from
919 1.1 mycroft * jumpers and save int level
920 1.1 mycroft */
921 1.1 mycroft delay(1000);
922 1.1 mycroft config.cmd.opcode = BHA_INQUIRE_CONFIG;
923 1.11 mycroft bha_cmd(iot, ioh, (struct bha_softc *)0,
924 1.1 mycroft sizeof(config.cmd), (u_char *)&config.cmd,
925 1.1 mycroft sizeof(config.reply), (u_char *)&config.reply);
926 1.1 mycroft switch (config.reply.chan) {
927 1.1 mycroft case EISADMA:
928 1.1 mycroft drq = -1;
929 1.1 mycroft break;
930 1.1 mycroft case CHAN0:
931 1.1 mycroft drq = 0;
932 1.1 mycroft break;
933 1.1 mycroft case CHAN5:
934 1.1 mycroft drq = 5;
935 1.1 mycroft break;
936 1.1 mycroft case CHAN6:
937 1.1 mycroft drq = 6;
938 1.1 mycroft break;
939 1.1 mycroft case CHAN7:
940 1.1 mycroft drq = 7;
941 1.1 mycroft break;
942 1.1 mycroft default:
943 1.4 thorpej printf("bha_find: illegal drq setting %x\n",
944 1.4 thorpej config.reply.chan);
945 1.1 mycroft return (0);
946 1.1 mycroft }
947 1.1 mycroft
948 1.1 mycroft switch (config.reply.intr) {
949 1.1 mycroft case INT9:
950 1.1 mycroft irq = 9;
951 1.1 mycroft break;
952 1.1 mycroft case INT10:
953 1.1 mycroft irq = 10;
954 1.1 mycroft break;
955 1.1 mycroft case INT11:
956 1.1 mycroft irq = 11;
957 1.1 mycroft break;
958 1.1 mycroft case INT12:
959 1.1 mycroft irq = 12;
960 1.1 mycroft break;
961 1.1 mycroft case INT14:
962 1.1 mycroft irq = 14;
963 1.1 mycroft break;
964 1.1 mycroft case INT15:
965 1.1 mycroft irq = 15;
966 1.1 mycroft break;
967 1.1 mycroft default:
968 1.4 thorpej printf("bha_find: illegal irq setting %x\n",
969 1.4 thorpej config.reply.intr);
970 1.1 mycroft return (0);
971 1.31 thorpej }
972 1.31 thorpej
973 1.31 thorpej /* if we want to fill in softc, do so now */
974 1.31 thorpej if (sc != NULL) {
975 1.31 thorpej sc->sc_irq = irq;
976 1.31 thorpej sc->sc_drq = drq;
977 1.31 thorpej }
978 1.31 thorpej
979 1.31 thorpej return (1);
980 1.31 thorpej }
981 1.31 thorpej
982 1.31 thorpej /*
983 1.31 thorpej * bha_disable_isacompat:
984 1.31 thorpej *
985 1.31 thorpej * Disable the ISA-compatiblity ioports on PCI bha devices,
986 1.31 thorpej * to ensure they're not autoconfigured a second time as an ISA bha.
987 1.31 thorpej */
988 1.31 thorpej int
989 1.31 thorpej bha_disable_isacompat(sc)
990 1.31 thorpej struct bha_softc *sc;
991 1.31 thorpej {
992 1.31 thorpej struct bha_isadisable isa_disable;
993 1.31 thorpej
994 1.31 thorpej isa_disable.cmd.opcode = BHA_MODIFY_IOPORT;
995 1.31 thorpej isa_disable.cmd.modifier = BHA_IOMODIFY_DISABLE1;
996 1.31 thorpej bha_cmd(sc->sc_iot, sc->sc_ioh, sc,
997 1.31 thorpej sizeof(isa_disable.cmd), (u_char*)&isa_disable.cmd,
998 1.31 thorpej 0, (u_char *)0);
999 1.31 thorpej return (0);
1000 1.31 thorpej }
1001 1.31 thorpej
1002 1.31 thorpej /*
1003 1.31 thorpej * bha_info:
1004 1.31 thorpej *
1005 1.31 thorpej * Get information about the board, and report it. We
1006 1.31 thorpej * return the initial number of CCBs, 0 if we failed.
1007 1.31 thorpej */
1008 1.31 thorpej int
1009 1.31 thorpej bha_info(sc)
1010 1.31 thorpej struct bha_softc *sc;
1011 1.31 thorpej {
1012 1.31 thorpej bus_space_tag_t iot = sc->sc_iot;
1013 1.31 thorpej bus_space_handle_t ioh = sc->sc_ioh;
1014 1.31 thorpej struct bha_extended_inquire inquire;
1015 1.31 thorpej struct bha_config config;
1016 1.31 thorpej struct bha_devices devices;
1017 1.31 thorpej struct bha_setup setup;
1018 1.31 thorpej struct bha_model model;
1019 1.31 thorpej struct bha_revision revision;
1020 1.31 thorpej struct bha_digit digit;
1021 1.31 thorpej int i, j, initial_ccbs, rlen;
1022 1.31 thorpej char *p;
1023 1.31 thorpej
1024 1.31 thorpej /*
1025 1.31 thorpej * Fetch the extended inquire information.
1026 1.31 thorpej */
1027 1.31 thorpej inquire.cmd.opcode = BHA_INQUIRE_EXTENDED;
1028 1.31 thorpej inquire.cmd.len = sizeof(inquire.reply);
1029 1.31 thorpej bha_cmd(iot, ioh, sc,
1030 1.31 thorpej sizeof(inquire.cmd), (u_char *)&inquire.cmd,
1031 1.31 thorpej sizeof(inquire.reply), (u_char *)&inquire.reply);
1032 1.31 thorpej
1033 1.31 thorpej /*
1034 1.31 thorpej * Fetch the configuration information.
1035 1.31 thorpej */
1036 1.31 thorpej config.cmd.opcode = BHA_INQUIRE_CONFIG;
1037 1.31 thorpej bha_cmd(iot, ioh, sc,
1038 1.31 thorpej sizeof(config.cmd), (u_char *)&config.cmd,
1039 1.31 thorpej sizeof(config.reply), (u_char *)&config.reply);
1040 1.31 thorpej
1041 1.31 thorpej sc->sc_scsi_id = config.reply.scsi_dev;
1042 1.31 thorpej
1043 1.31 thorpej /*
1044 1.31 thorpej * Get the firmware revision.
1045 1.31 thorpej */
1046 1.31 thorpej p = sc->sc_firmware;
1047 1.31 thorpej revision.cmd.opcode = BHA_INQUIRE_REVISION;
1048 1.31 thorpej bha_cmd(iot, ioh, sc,
1049 1.31 thorpej sizeof(revision.cmd), (u_char *)&revision.cmd,
1050 1.31 thorpej sizeof(revision.reply), (u_char *)&revision.reply);
1051 1.31 thorpej *p++ = revision.reply.firm_revision;
1052 1.31 thorpej *p++ = '.';
1053 1.31 thorpej *p++ = revision.reply.firm_version;
1054 1.31 thorpej digit.cmd.opcode = BHA_INQUIRE_REVISION_3;
1055 1.31 thorpej bha_cmd(iot, ioh, sc,
1056 1.31 thorpej sizeof(digit.cmd), (u_char *)&digit.cmd,
1057 1.31 thorpej sizeof(digit.reply), (u_char *)&digit.reply);
1058 1.31 thorpej *p++ = digit.reply.digit;
1059 1.31 thorpej if (revision.reply.firm_revision >= '3' ||
1060 1.31 thorpej (revision.reply.firm_revision == '3' &&
1061 1.31 thorpej revision.reply.firm_version >= '3')) {
1062 1.31 thorpej digit.cmd.opcode = BHA_INQUIRE_REVISION_4;
1063 1.31 thorpej bha_cmd(iot, ioh, sc,
1064 1.31 thorpej sizeof(digit.cmd), (u_char *)&digit.cmd,
1065 1.31 thorpej sizeof(digit.reply), (u_char *)&digit.reply);
1066 1.31 thorpej *p++ = digit.reply.digit;
1067 1.31 thorpej }
1068 1.31 thorpej while (p > sc->sc_firmware && (p[-1] == ' ' || p[-1] == '\0'))
1069 1.31 thorpej p--;
1070 1.31 thorpej *p = '\0';
1071 1.31 thorpej
1072 1.31 thorpej /*
1073 1.31 thorpej * Get the model number.
1074 1.31 thorpej *
1075 1.31 thorpej * Some boards do not handle the Inquire Board Model Number
1076 1.31 thorpej * command correctly, or don't give correct information.
1077 1.31 thorpej *
1078 1.31 thorpej * So, we use the Firmware Revision and Extended Setup
1079 1.31 thorpej * information to fixup the model number in these cases.
1080 1.31 thorpej *
1081 1.31 thorpej * The firmware version indicates:
1082 1.31 thorpej *
1083 1.31 thorpej * 5.xx BusLogic "W" Series Hose Adapters
1084 1.31 thorpej * BT-948/958/958D
1085 1.31 thorpej *
1086 1.31 thorpej * 4.xx BusLogic "C" Series Host Adapters
1087 1.31 thorpej * BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
1088 1.31 thorpej *
1089 1.31 thorpej * 3.xx BusLogic "S" Series Host Adapters
1090 1.31 thorpej * BT-747S/747D/757S/757D/445S/545S/542D
1091 1.31 thorpej * BT-542B/742A (revision H)
1092 1.31 thorpej *
1093 1.31 thorpej * 2.xx BusLogic "A" Series Host Adapters
1094 1.31 thorpej * BT-542B/742A (revision G and below)
1095 1.31 thorpej *
1096 1.31 thorpej * 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
1097 1.31 thorpej */
1098 1.31 thorpej if (inquire.reply.bus_type == BHA_BUS_TYPE_24BIT &&
1099 1.31 thorpej sc->sc_firmware[0] < '3')
1100 1.31 thorpej sprintf(sc->sc_model, "542B");
1101 1.31 thorpej else if (inquire.reply.bus_type == BHA_BUS_TYPE_32BIT &&
1102 1.31 thorpej sc->sc_firmware[0] == '2' &&
1103 1.31 thorpej (sc->sc_firmware[2] == '1' ||
1104 1.31 thorpej (sc->sc_firmware[2] == '2' && sc->sc_firmware[3] == '0')))
1105 1.31 thorpej sprintf(sc->sc_model, "742A");
1106 1.31 thorpej else if (inquire.reply.bus_type == BHA_BUS_TYPE_32BIT &&
1107 1.31 thorpej sc->sc_firmware[0] == '0')
1108 1.31 thorpej sprintf(sc->sc_model, "747A");
1109 1.31 thorpej else {
1110 1.31 thorpej p = sc->sc_model;
1111 1.31 thorpej model.cmd.opcode = BHA_INQUIRE_MODEL;
1112 1.31 thorpej model.cmd.len = sizeof(model.reply);
1113 1.31 thorpej bha_cmd(iot, ioh, sc,
1114 1.31 thorpej sizeof(model.cmd), (u_char *)&model.cmd,
1115 1.31 thorpej sizeof(model.reply), (u_char *)&model.reply);
1116 1.31 thorpej *p++ = model.reply.id[0];
1117 1.31 thorpej *p++ = model.reply.id[1];
1118 1.31 thorpej *p++ = model.reply.id[2];
1119 1.31 thorpej *p++ = model.reply.id[3];
1120 1.31 thorpej while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
1121 1.31 thorpej p--;
1122 1.31 thorpej *p++ = model.reply.version[0];
1123 1.31 thorpej *p++ = model.reply.version[1];
1124 1.31 thorpej while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
1125 1.31 thorpej p--;
1126 1.31 thorpej *p = '\0';
1127 1.31 thorpej }
1128 1.31 thorpej
1129 1.31 thorpej /* Enable round-robin scheme - appeared at firmware rev. 3.31. */
1130 1.31 thorpej if (strcmp(sc->sc_firmware, "3.31") >= 0)
1131 1.31 thorpej sc->sc_flags |= BHAF_STRICT_ROUND_ROBIN;
1132 1.31 thorpej
1133 1.31 thorpej /*
1134 1.31 thorpej * Determine some characteristics about our bus.
1135 1.31 thorpej */
1136 1.31 thorpej if (inquire.reply.scsi_flags & BHA_SCSI_WIDE)
1137 1.31 thorpej sc->sc_flags |= BHAF_WIDE;
1138 1.31 thorpej if (inquire.reply.scsi_flags & BHA_SCSI_DIFFERENTIAL)
1139 1.31 thorpej sc->sc_flags |= BHAF_DIFFERENTIAL;
1140 1.31 thorpej if (inquire.reply.scsi_flags & BHA_SCSI_ULTRA)
1141 1.31 thorpej sc->sc_flags |= BHAF_ULTRA;
1142 1.31 thorpej
1143 1.31 thorpej /*
1144 1.31 thorpej * Determine some characterists of the board.
1145 1.31 thorpej */
1146 1.31 thorpej sc->sc_max_dmaseg = inquire.reply.sg_limit;
1147 1.31 thorpej
1148 1.31 thorpej /*
1149 1.31 thorpej * Determine the maximum CCB cound and whether or not
1150 1.31 thorpej * tagged queueing is available on this host adapter.
1151 1.31 thorpej *
1152 1.31 thorpej * Tagged queueing works on:
1153 1.31 thorpej *
1154 1.31 thorpej * "W" Series adapters
1155 1.31 thorpej * "C" Series adapters with firmware >= 4.22
1156 1.31 thorpej * "S" Series adapters with firmware >= 3.35
1157 1.31 thorpej *
1158 1.31 thorpej * The internal CCB counts are:
1159 1.31 thorpej *
1160 1.31 thorpej * 192 BT-948/958/958D
1161 1.31 thorpej * 100 BT-946C/956C/956CD/747C/757C/757CD/445C
1162 1.31 thorpej * 50 BT-545C/540CF
1163 1.31 thorpej * 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
1164 1.31 thorpej */
1165 1.31 thorpej switch (sc->sc_firmware[0]) {
1166 1.31 thorpej case '5':
1167 1.31 thorpej sc->sc_hw_ccbs = 192;
1168 1.31 thorpej sc->sc_flags |= BHAF_TAGGED_QUEUEING;
1169 1.31 thorpej break;
1170 1.31 thorpej
1171 1.31 thorpej case '4':
1172 1.31 thorpej if (sc->sc_model[0] == '5')
1173 1.31 thorpej sc->sc_hw_ccbs = 50;
1174 1.31 thorpej else
1175 1.31 thorpej sc->sc_hw_ccbs = 100;
1176 1.31 thorpej if (strcmp(sc->sc_firmware, "4.22") >= 0)
1177 1.31 thorpej sc->sc_flags |= BHAF_TAGGED_QUEUEING;
1178 1.31 thorpej break;
1179 1.31 thorpej
1180 1.31 thorpej case '3':
1181 1.31 thorpej if (strcmp(sc->sc_firmware, "3.35") >= 0)
1182 1.31 thorpej sc->sc_flags |= BHAF_TAGGED_QUEUEING;
1183 1.31 thorpej /* FALLTHROUGH */
1184 1.31 thorpej
1185 1.31 thorpej default:
1186 1.31 thorpej sc->sc_hw_ccbs = 30;
1187 1.31 thorpej }
1188 1.31 thorpej
1189 1.31 thorpej /*
1190 1.31 thorpej * Set the mailbox size to be just larger than the internal
1191 1.31 thorpej * CCB count.
1192 1.31 thorpej *
1193 1.31 thorpej * XXX We should consider making this a large number on
1194 1.31 thorpej * boards with strict round-robin mode, as it would allow
1195 1.31 thorpej * us to expand the openings available to the upper layer.
1196 1.31 thorpej * The CCB count is what the host adapter can process
1197 1.31 thorpej * concurrently, but we can queue up to 255 in the mailbox
1198 1.31 thorpej * regardless.
1199 1.31 thorpej */
1200 1.31 thorpej if (sc->sc_flags & BHAF_STRICT_ROUND_ROBIN) {
1201 1.31 thorpej #if 0
1202 1.31 thorpej sc->sc_mbox_count = 255;
1203 1.31 thorpej #else
1204 1.31 thorpej sc->sc_mbox_count = sc->sc_hw_ccbs + 8;
1205 1.31 thorpej #endif
1206 1.31 thorpej } else {
1207 1.31 thorpej /*
1208 1.31 thorpej * Only 32 in this case; non-strict round-robin must
1209 1.31 thorpej * scan the entire mailbox for new commands, which
1210 1.31 thorpej * is not very efficient.
1211 1.31 thorpej */
1212 1.31 thorpej sc->sc_mbox_count = 32;
1213 1.31 thorpej }
1214 1.31 thorpej
1215 1.31 thorpej /*
1216 1.31 thorpej * The maximum number of CCBs we allow is the number we can
1217 1.31 thorpej * enqueue.
1218 1.31 thorpej */
1219 1.31 thorpej sc->sc_max_ccbs = sc->sc_mbox_count;
1220 1.31 thorpej
1221 1.31 thorpej /*
1222 1.31 thorpej * Obtain setup information.
1223 1.31 thorpej */
1224 1.31 thorpej rlen = sizeof(setup.reply) +
1225 1.31 thorpej ((sc->sc_flags & BHAF_WIDE) ? sizeof(setup.reply_w) : 0);
1226 1.31 thorpej setup.cmd.opcode = BHA_INQUIRE_SETUP;
1227 1.31 thorpej setup.cmd.len = rlen;
1228 1.31 thorpej bha_cmd(iot, ioh, sc,
1229 1.31 thorpej sizeof(setup.cmd), (u_char *)&setup.cmd,
1230 1.31 thorpej rlen, (u_char *)&setup.reply);
1231 1.31 thorpej
1232 1.31 thorpej printf("%s: model BT-%s, firmware %s\n", sc->sc_dev.dv_xname,
1233 1.31 thorpej sc->sc_model, sc->sc_firmware);
1234 1.31 thorpej
1235 1.31 thorpej printf("%s: %d H/W CCBs", sc->sc_dev.dv_xname, sc->sc_hw_ccbs);
1236 1.31 thorpej if (setup.reply.sync_neg)
1237 1.31 thorpej printf(", sync");
1238 1.31 thorpej if (setup.reply.parity)
1239 1.31 thorpej printf(", parity");
1240 1.31 thorpej if (sc->sc_flags & BHAF_TAGGED_QUEUEING)
1241 1.31 thorpej printf(", tagged queueing");
1242 1.31 thorpej if (sc->sc_flags & BHAF_WIDE_LUN)
1243 1.31 thorpej printf(", wide LUN support");
1244 1.31 thorpej printf("\n");
1245 1.31 thorpej
1246 1.31 thorpej /*
1247 1.31 thorpej * Poll targets 0 - 7.
1248 1.31 thorpej */
1249 1.31 thorpej devices.cmd.opcode = BHA_INQUIRE_DEVICES;
1250 1.31 thorpej bha_cmd(iot, ioh, sc,
1251 1.31 thorpej sizeof(devices.cmd), (u_char *)&devices.cmd,
1252 1.31 thorpej sizeof(devices.reply), (u_char *)&devices.reply);
1253 1.31 thorpej
1254 1.31 thorpej /* Count installed units. */
1255 1.31 thorpej initial_ccbs = 0;
1256 1.31 thorpej for (i = 0; i < 8; i++) {
1257 1.31 thorpej for (j = 0; j < 8; j++) {
1258 1.31 thorpej if (((devices.reply.lun_map[i] >> j) & 1) == 1)
1259 1.31 thorpej initial_ccbs++;
1260 1.31 thorpej }
1261 1.31 thorpej }
1262 1.31 thorpej
1263 1.31 thorpej /*
1264 1.31 thorpej * Poll targets 8 - 15 if we have a wide bus.
1265 1.31 thorpej */
1266 1.31 thorpej if (sc->sc_flags & BHAF_WIDE) {
1267 1.31 thorpej devices.cmd.opcode = BHA_INQUIRE_DEVICES_2;
1268 1.31 thorpej bha_cmd(iot, ioh, sc,
1269 1.31 thorpej sizeof(devices.cmd), (u_char *)&devices.cmd,
1270 1.31 thorpej sizeof(devices.reply), (u_char *)&devices.reply);
1271 1.31 thorpej
1272 1.31 thorpej for (i = 0; i < 8; i++) {
1273 1.31 thorpej for (j = 0; j < 8; j++) {
1274 1.31 thorpej if (((devices.reply.lun_map[i] >> j) & 1) == 1)
1275 1.31 thorpej initial_ccbs++;
1276 1.31 thorpej }
1277 1.31 thorpej }
1278 1.31 thorpej }
1279 1.31 thorpej
1280 1.31 thorpej /*
1281 1.31 thorpej * Double the initial CCB count, for good measure.
1282 1.31 thorpej */
1283 1.31 thorpej initial_ccbs *= 2;
1284 1.31 thorpej
1285 1.31 thorpej /*
1286 1.31 thorpej * Sanity check the initial CCB count; don't create more than
1287 1.31 thorpej * we can enqueue (sc_max_ccbs), and make sure there are some
1288 1.31 thorpej * at all.
1289 1.31 thorpej */
1290 1.31 thorpej if (initial_ccbs > sc->sc_max_ccbs)
1291 1.31 thorpej initial_ccbs = sc->sc_max_ccbs;
1292 1.31 thorpej if (initial_ccbs == 0)
1293 1.31 thorpej initial_ccbs = 2;
1294 1.31 thorpej
1295 1.31 thorpej return (initial_ccbs);
1296 1.31 thorpej }
1297 1.31 thorpej
1298 1.31 thorpej /*
1299 1.31 thorpej * bha_init:
1300 1.31 thorpej *
1301 1.31 thorpej * Initialize the board.
1302 1.31 thorpej */
1303 1.31 thorpej int
1304 1.31 thorpej bha_init(sc)
1305 1.31 thorpej struct bha_softc *sc;
1306 1.31 thorpej {
1307 1.31 thorpej struct bha_toggle toggle;
1308 1.31 thorpej struct bha_mailbox mailbox;
1309 1.31 thorpej struct bha_mbx_out *mbo;
1310 1.31 thorpej struct bha_mbx_in *mbi;
1311 1.31 thorpej int i;
1312 1.31 thorpej
1313 1.31 thorpej /*
1314 1.31 thorpej * Set up the mailbox. We always run the mailbox in round-robin.
1315 1.31 thorpej */
1316 1.31 thorpej for (i = 0; i < sc->sc_mbox_count; i++) {
1317 1.31 thorpej mbo = &sc->sc_mbo[i];
1318 1.31 thorpej mbi = &sc->sc_mbi[i];
1319 1.31 thorpej
1320 1.31 thorpej mbo->cmd = BHA_MBO_FREE;
1321 1.31 thorpej BHA_MBO_SYNC(sc, mbo, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1322 1.31 thorpej
1323 1.31 thorpej mbi->comp_stat = BHA_MBI_FREE;
1324 1.31 thorpej BHA_MBI_SYNC(sc, mbi, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1325 1.31 thorpej }
1326 1.31 thorpej
1327 1.31 thorpej sc->sc_cmbo = sc->sc_tmbo = &sc->sc_mbo[0];
1328 1.31 thorpej sc->sc_tmbi = &sc->sc_mbi[0];
1329 1.31 thorpej
1330 1.31 thorpej sc->sc_mbofull = 0;
1331 1.31 thorpej
1332 1.31 thorpej /*
1333 1.31 thorpej * If the board supports strict round-robin, enable that.
1334 1.31 thorpej */
1335 1.31 thorpej if (sc->sc_flags & BHAF_STRICT_ROUND_ROBIN) {
1336 1.31 thorpej toggle.cmd.opcode = BHA_ROUND_ROBIN;
1337 1.31 thorpej toggle.cmd.enable = 1;
1338 1.31 thorpej bha_cmd(sc->sc_iot, sc->sc_ioh, sc,
1339 1.31 thorpej sizeof(toggle.cmd), (u_char *)&toggle.cmd,
1340 1.31 thorpej 0, NULL);
1341 1.31 thorpej }
1342 1.31 thorpej
1343 1.31 thorpej /*
1344 1.31 thorpej * Give the mailbox to the board.
1345 1.31 thorpej */
1346 1.31 thorpej mailbox.cmd.opcode = BHA_MBX_INIT_EXTENDED;
1347 1.31 thorpej mailbox.cmd.nmbx = sc->sc_mbox_count;
1348 1.31 thorpej ltophys(sc->sc_dmamap_mbox->dm_segs[0].ds_addr, mailbox.cmd.addr);
1349 1.31 thorpej bha_cmd(sc->sc_iot, sc->sc_ioh, sc,
1350 1.31 thorpej sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
1351 1.31 thorpej 0, (u_char *)0);
1352 1.31 thorpej
1353 1.31 thorpej return (0);
1354 1.31 thorpej }
1355 1.31 thorpej
1356 1.31 thorpej /*****************************************************************************
1357 1.31 thorpej * CCB execution engine
1358 1.31 thorpej *****************************************************************************/
1359 1.31 thorpej
1360 1.31 thorpej /*
1361 1.31 thorpej * bha_queue_ccb:
1362 1.31 thorpej *
1363 1.31 thorpej * Queue a CCB to be sent to the controller, and send it if possible.
1364 1.31 thorpej */
1365 1.31 thorpej void
1366 1.31 thorpej bha_queue_ccb(sc, ccb)
1367 1.31 thorpej struct bha_softc *sc;
1368 1.31 thorpej struct bha_ccb *ccb;
1369 1.31 thorpej {
1370 1.31 thorpej
1371 1.31 thorpej TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
1372 1.31 thorpej bha_start_ccbs(sc);
1373 1.31 thorpej }
1374 1.31 thorpej
1375 1.31 thorpej /*
1376 1.31 thorpej * bha_start_ccbs:
1377 1.31 thorpej *
1378 1.31 thorpej * Send as many CCBs as we have empty mailboxes for.
1379 1.31 thorpej */
1380 1.31 thorpej void
1381 1.31 thorpej bha_start_ccbs(sc)
1382 1.31 thorpej struct bha_softc *sc;
1383 1.31 thorpej {
1384 1.31 thorpej bus_space_tag_t iot = sc->sc_iot;
1385 1.31 thorpej bus_space_handle_t ioh = sc->sc_ioh;
1386 1.31 thorpej struct bha_ccb_group *bcg;
1387 1.31 thorpej struct bha_mbx_out *mbo;
1388 1.31 thorpej struct bha_ccb *ccb;
1389 1.31 thorpej
1390 1.31 thorpej mbo = sc->sc_tmbo;
1391 1.31 thorpej
1392 1.31 thorpej while ((ccb = TAILQ_FIRST(&sc->sc_waiting_ccb)) != NULL) {
1393 1.31 thorpej if (sc->sc_mbofull >= sc->sc_mbox_count) {
1394 1.31 thorpej #ifdef DIAGNOSTIC
1395 1.31 thorpej if (sc->sc_mbofull > sc->sc_mbox_count)
1396 1.31 thorpej panic("bha_start_ccbs: mbofull > mbox_count");
1397 1.31 thorpej #endif
1398 1.31 thorpej /*
1399 1.31 thorpej * No mailboxes available; attempt to collect ones
1400 1.31 thorpej * that have already been used.
1401 1.31 thorpej */
1402 1.31 thorpej bha_collect_mbo(sc);
1403 1.31 thorpej if (sc->sc_mbofull == sc->sc_mbox_count) {
1404 1.31 thorpej /*
1405 1.31 thorpej * Still no more available; have the
1406 1.31 thorpej * controller interrupt us when it
1407 1.31 thorpej * frees one.
1408 1.31 thorpej */
1409 1.31 thorpej struct bha_toggle toggle;
1410 1.31 thorpej
1411 1.31 thorpej toggle.cmd.opcode = BHA_MBO_INTR_EN;
1412 1.31 thorpej toggle.cmd.enable = 1;
1413 1.31 thorpej bha_cmd(iot, ioh, sc,
1414 1.31 thorpej sizeof(toggle.cmd), (u_char *)&toggle.cmd,
1415 1.31 thorpej 0, (u_char *)0);
1416 1.31 thorpej break;
1417 1.31 thorpej }
1418 1.31 thorpej }
1419 1.31 thorpej
1420 1.31 thorpej TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
1421 1.31 thorpej #ifdef BHADIAG
1422 1.31 thorpej ccb->flags |= CCB_SENDING;
1423 1.31 thorpej #endif
1424 1.31 thorpej
1425 1.31 thorpej /*
1426 1.31 thorpej * Put the CCB in the mailbox.
1427 1.31 thorpej */
1428 1.31 thorpej bcg = BHA_CCB_GROUP(ccb);
1429 1.31 thorpej ltophys(bcg->bcg_dmamap->dm_segs[0].ds_addr +
1430 1.31 thorpej BHA_CCB_OFFSET(ccb), mbo->ccb_addr);
1431 1.31 thorpej if (ccb->flags & CCB_ABORT)
1432 1.31 thorpej mbo->cmd = BHA_MBO_ABORT;
1433 1.31 thorpej else
1434 1.31 thorpej mbo->cmd = BHA_MBO_START;
1435 1.31 thorpej
1436 1.31 thorpej BHA_MBO_SYNC(sc, mbo,
1437 1.31 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1438 1.31 thorpej
1439 1.31 thorpej /* Tell the card to poll immediately. */
1440 1.31 thorpej bus_space_write_1(iot, ioh, BHA_CMD_PORT, BHA_START_SCSI);
1441 1.31 thorpej
1442 1.31 thorpej if ((ccb->xs->xs_control & XS_CTL_POLL) == 0)
1443 1.31 thorpej timeout(bha_timeout, ccb, (ccb->timeout * hz) / 1000);
1444 1.31 thorpej
1445 1.31 thorpej ++sc->sc_mbofull;
1446 1.31 thorpej mbo = bha_nextmbo(sc, mbo);
1447 1.31 thorpej }
1448 1.31 thorpej
1449 1.31 thorpej sc->sc_tmbo = mbo;
1450 1.31 thorpej }
1451 1.31 thorpej
1452 1.31 thorpej /*
1453 1.31 thorpej * bha_finish_ccbs:
1454 1.31 thorpej *
1455 1.31 thorpej * Finalize the execution of CCBs in our incoming mailbox.
1456 1.31 thorpej */
1457 1.31 thorpej void
1458 1.31 thorpej bha_finish_ccbs(sc)
1459 1.31 thorpej struct bha_softc *sc;
1460 1.31 thorpej {
1461 1.31 thorpej struct bha_mbx_in *mbi;
1462 1.31 thorpej struct bha_ccb *ccb;
1463 1.31 thorpej int i;
1464 1.31 thorpej
1465 1.31 thorpej mbi = sc->sc_tmbi;
1466 1.31 thorpej
1467 1.31 thorpej BHA_MBI_SYNC(sc, mbi, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1468 1.31 thorpej
1469 1.31 thorpej if (mbi->comp_stat == BHA_MBI_FREE) {
1470 1.31 thorpej for (i = 0; i < sc->sc_mbox_count; i++) {
1471 1.31 thorpej if (mbi->comp_stat != BHA_MBI_FREE) {
1472 1.31 thorpej printf("%s: mbi not in round-robin order\n",
1473 1.31 thorpej sc->sc_dev.dv_xname);
1474 1.31 thorpej goto again;
1475 1.31 thorpej }
1476 1.31 thorpej mbi = bha_nextmbi(sc, mbi);
1477 1.31 thorpej BHA_MBI_SYNC(sc, mbi,
1478 1.31 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1479 1.31 thorpej }
1480 1.31 thorpej #ifdef BHADIAGnot
1481 1.31 thorpej printf("%s: mbi interrupt with no full mailboxes\n",
1482 1.31 thorpej sc->sc_dev.dv_xname);
1483 1.31 thorpej #endif
1484 1.31 thorpej return;
1485 1.31 thorpej }
1486 1.31 thorpej
1487 1.31 thorpej again:
1488 1.31 thorpej do {
1489 1.31 thorpej ccb = bha_ccb_phys_kv(sc, phystol(mbi->ccb_addr));
1490 1.31 thorpej if (ccb == NULL) {
1491 1.31 thorpej printf("%s: bad mbi ccb pointer 0x%08x; skipping\n",
1492 1.31 thorpej sc->sc_dev.dv_xname, phystol(mbi->ccb_addr));
1493 1.31 thorpej goto next;
1494 1.31 thorpej }
1495 1.31 thorpej
1496 1.31 thorpej BHA_CCB_SYNC(sc, ccb,
1497 1.31 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1498 1.31 thorpej
1499 1.31 thorpej #ifdef BHADEBUG
1500 1.31 thorpej if (bha_debug) {
1501 1.31 thorpej struct scsi_generic *cmd = &ccb->scsi_cmd;
1502 1.31 thorpej printf("op=%x %x %x %x %x %x\n",
1503 1.31 thorpej cmd->opcode, cmd->bytes[0], cmd->bytes[1],
1504 1.31 thorpej cmd->bytes[2], cmd->bytes[3], cmd->bytes[4]);
1505 1.31 thorpej printf("comp_stat %x for mbi addr = 0x%p, ",
1506 1.31 thorpej mbi->comp_stat, mbi);
1507 1.31 thorpej printf("ccb addr = %p\n", ccb);
1508 1.31 thorpej }
1509 1.31 thorpej #endif /* BHADEBUG */
1510 1.31 thorpej
1511 1.31 thorpej switch (mbi->comp_stat) {
1512 1.31 thorpej case BHA_MBI_OK:
1513 1.31 thorpej case BHA_MBI_ERROR:
1514 1.31 thorpej if ((ccb->flags & CCB_ABORT) != 0) {
1515 1.31 thorpej /*
1516 1.31 thorpej * If we already started an abort, wait for it
1517 1.31 thorpej * to complete before clearing the CCB. We
1518 1.31 thorpej * could instead just clear CCB_SENDING, but
1519 1.31 thorpej * what if the mailbox was already received?
1520 1.31 thorpej * The worst that happens here is that we clear
1521 1.31 thorpej * the CCB a bit later than we need to. BFD.
1522 1.31 thorpej */
1523 1.31 thorpej goto next;
1524 1.31 thorpej }
1525 1.31 thorpej break;
1526 1.31 thorpej
1527 1.31 thorpej case BHA_MBI_ABORT:
1528 1.31 thorpej case BHA_MBI_UNKNOWN:
1529 1.31 thorpej /*
1530 1.31 thorpej * Even if the CCB wasn't found, we clear it anyway.
1531 1.31 thorpej * See preceeding comment.
1532 1.31 thorpej */
1533 1.31 thorpej break;
1534 1.1 mycroft
1535 1.31 thorpej default:
1536 1.31 thorpej printf("%s: bad mbi comp_stat %02x; skipping\n",
1537 1.31 thorpej sc->sc_dev.dv_xname, mbi->comp_stat);
1538 1.31 thorpej goto next;
1539 1.31 thorpej }
1540 1.1 mycroft
1541 1.31 thorpej untimeout(bha_timeout, ccb);
1542 1.31 thorpej bha_done(sc, ccb);
1543 1.5 jonathan
1544 1.31 thorpej next:
1545 1.31 thorpej mbi->comp_stat = BHA_MBI_FREE;
1546 1.31 thorpej BHA_CCB_SYNC(sc, ccb,
1547 1.31 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1548 1.5 jonathan
1549 1.31 thorpej mbi = bha_nextmbi(sc, mbi);
1550 1.31 thorpej BHA_MBI_SYNC(sc, mbi,
1551 1.31 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1552 1.31 thorpej } while (mbi->comp_stat != BHA_MBI_FREE);
1553 1.5 jonathan
1554 1.31 thorpej sc->sc_tmbi = mbi;
1555 1.5 jonathan }
1556 1.5 jonathan
1557 1.31 thorpej /*****************************************************************************
1558 1.31 thorpej * Mailbox management functions.
1559 1.31 thorpej *****************************************************************************/
1560 1.1 mycroft
1561 1.1 mycroft /*
1562 1.31 thorpej * bha_create_mailbox:
1563 1.31 thorpej *
1564 1.31 thorpej * Create the mailbox structures. Helper function for bha_attach().
1565 1.31 thorpej *
1566 1.31 thorpej * NOTE: The Buslogic hardware only gets one DMA address for the
1567 1.31 thorpej * mailbox! It expects:
1568 1.31 thorpej *
1569 1.31 thorpej * mailbox_out[mailbox_size]
1570 1.31 thorpej * mailbox_in[mailbox_size]
1571 1.1 mycroft */
1572 1.22 thorpej int
1573 1.31 thorpej bha_create_mailbox(sc)
1574 1.1 mycroft struct bha_softc *sc;
1575 1.1 mycroft {
1576 1.13 thorpej bus_dma_segment_t seg;
1577 1.31 thorpej size_t size;
1578 1.31 thorpej int error, rseg;
1579 1.1 mycroft
1580 1.31 thorpej size = (sizeof(struct bha_mbx_out) * sc->sc_mbox_count) +
1581 1.31 thorpej (sizeof(struct bha_mbx_in) * sc->sc_mbox_count);
1582 1.1 mycroft
1583 1.31 thorpej error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &seg,
1584 1.31 thorpej 1, &rseg, sc->sc_dmaflags);
1585 1.31 thorpej if (error) {
1586 1.31 thorpej printf("%s: unable to allocate mailboxes, error = %d\n",
1587 1.31 thorpej sc->sc_dev.dv_xname, error);
1588 1.31 thorpej goto bad_0;
1589 1.1 mycroft }
1590 1.1 mycroft
1591 1.31 thorpej error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
1592 1.31 thorpej (caddr_t *)&sc->sc_mbo, sc->sc_dmaflags | BUS_DMA_COHERENT);
1593 1.31 thorpej if (error) {
1594 1.31 thorpej printf("%s: unable to map mailboxes, error = %d\n",
1595 1.31 thorpej sc->sc_dev.dv_xname, error);
1596 1.31 thorpej goto bad_1;
1597 1.15 thorpej }
1598 1.15 thorpej
1599 1.31 thorpej memset(sc->sc_mbo, 0, size);
1600 1.15 thorpej
1601 1.31 thorpej error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
1602 1.31 thorpej sc->sc_dmaflags, &sc->sc_dmamap_mbox);
1603 1.31 thorpej if (error) {
1604 1.31 thorpej printf("%s: unable to create mailbox DMA map, error = %d\n",
1605 1.22 thorpej sc->sc_dev.dv_xname, error);
1606 1.31 thorpej goto bad_2;
1607 1.22 thorpej }
1608 1.13 thorpej
1609 1.31 thorpej error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_mbox,
1610 1.31 thorpej sc->sc_mbo, size, NULL, 0);
1611 1.31 thorpej if (error) {
1612 1.31 thorpej printf("%s: unable to load mailbox DMA map, error = %d\n",
1613 1.22 thorpej sc->sc_dev.dv_xname, error);
1614 1.31 thorpej goto bad_3;
1615 1.22 thorpej }
1616 1.13 thorpej
1617 1.31 thorpej sc->sc_mbi = (struct bha_mbx_in *)(sc->sc_mbo + sc->sc_mbox_count);
1618 1.13 thorpej
1619 1.31 thorpej return (0);
1620 1.1 mycroft
1621 1.31 thorpej bad_3:
1622 1.31 thorpej bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap_mbox);
1623 1.31 thorpej bad_2:
1624 1.31 thorpej bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_mbo, size);
1625 1.31 thorpej bad_1:
1626 1.31 thorpej bus_dmamem_free(sc->sc_dmat, &seg, rseg);
1627 1.31 thorpej bad_0:
1628 1.31 thorpej return (error);
1629 1.1 mycroft }
1630 1.1 mycroft
1631 1.31 thorpej /*
1632 1.31 thorpej * bha_collect_mbo:
1633 1.31 thorpej *
1634 1.31 thorpej * Garbage collect mailboxes that are no longer in use.
1635 1.31 thorpej */
1636 1.1 mycroft void
1637 1.31 thorpej bha_collect_mbo(sc)
1638 1.1 mycroft struct bha_softc *sc;
1639 1.1 mycroft {
1640 1.31 thorpej struct bha_mbx_out *mbo;
1641 1.31 thorpej #ifdef BHADIAG
1642 1.31 thorpej struct bha_ccb *ccb;
1643 1.31 thorpej #endif
1644 1.31 thorpej
1645 1.31 thorpej mbo = sc->sc_cmbo;
1646 1.31 thorpej
1647 1.31 thorpej while (sc->sc_mbofull > 0) {
1648 1.31 thorpej BHA_MBO_SYNC(sc, mbo,
1649 1.31 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1650 1.31 thorpej if (mbo->cmd != BHA_MBO_FREE)
1651 1.31 thorpej break;
1652 1.31 thorpej
1653 1.31 thorpej #ifdef BHADIAG
1654 1.31 thorpej ccb = bha_ccb_phys_kv(sc, phystol(mbo->ccb_addr));
1655 1.31 thorpej ccb->flags &= ~CCB_SENDING;
1656 1.31 thorpej #endif
1657 1.1 mycroft
1658 1.31 thorpej --sc->sc_mbofull;
1659 1.31 thorpej mbo = bha_nextmbo(sc, mbo);
1660 1.1 mycroft }
1661 1.1 mycroft
1662 1.31 thorpej sc->sc_cmbo = mbo;
1663 1.1 mycroft }
1664 1.1 mycroft
1665 1.31 thorpej /*****************************************************************************
1666 1.31 thorpej * CCB management functions
1667 1.31 thorpej *****************************************************************************/
1668 1.31 thorpej
1669 1.31 thorpej __inline void bha_reset_ccb __P((struct bha_ccb *));
1670 1.31 thorpej
1671 1.31 thorpej __inline void
1672 1.31 thorpej bha_reset_ccb(ccb)
1673 1.31 thorpej struct bha_ccb *ccb;
1674 1.1 mycroft {
1675 1.1 mycroft
1676 1.31 thorpej ccb->flags = 0;
1677 1.1 mycroft }
1678 1.1 mycroft
1679 1.1 mycroft /*
1680 1.31 thorpej * bha_create_ccbs:
1681 1.31 thorpej *
1682 1.31 thorpej * Create a set of CCBs.
1683 1.31 thorpej *
1684 1.31 thorpej * We determine the target CCB count, and then keep creating them
1685 1.31 thorpej * until we reach the target, or fail. CCBs that are allocated
1686 1.31 thorpej * but not "created" are left on the allocating list.
1687 1.1 mycroft */
1688 1.31 thorpej void
1689 1.31 thorpej bha_create_ccbs(sc, count)
1690 1.31 thorpej struct bha_softc *sc;
1691 1.31 thorpej int count;
1692 1.1 mycroft {
1693 1.31 thorpej struct bha_ccb_group *bcg;
1694 1.1 mycroft struct bha_ccb *ccb;
1695 1.31 thorpej bus_dma_segment_t seg;
1696 1.31 thorpej bus_dmamap_t ccbmap;
1697 1.31 thorpej int target, i, error, rseg;
1698 1.1 mycroft
1699 1.31 thorpej /*
1700 1.31 thorpej * If the current CCB count is already the max number we're
1701 1.31 thorpej * allowed to have, bail out now.
1702 1.31 thorpej */
1703 1.31 thorpej if (sc->sc_cur_ccbs == sc->sc_max_ccbs)
1704 1.31 thorpej return;
1705 1.17 thorpej
1706 1.17 thorpej /*
1707 1.31 thorpej * Compute our target count, and clamp it down to the max
1708 1.31 thorpej * number we're allowed to have.
1709 1.17 thorpej */
1710 1.31 thorpej target = sc->sc_cur_ccbs + count;
1711 1.31 thorpej if (target > sc->sc_max_ccbs)
1712 1.31 thorpej target = sc->sc_max_ccbs;
1713 1.17 thorpej
1714 1.17 thorpej /*
1715 1.31 thorpej * If there are CCBs on the allocating list, don't allocate a
1716 1.31 thorpej * CCB group yet.
1717 1.17 thorpej */
1718 1.31 thorpej if (TAILQ_FIRST(&sc->sc_allocating_ccbs) != NULL)
1719 1.31 thorpej goto have_allocating_ccbs;
1720 1.31 thorpej
1721 1.31 thorpej allocate_group:
1722 1.31 thorpej error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE,
1723 1.31 thorpej PAGE_SIZE, 0, &seg, 1, &rseg, sc->sc_dmaflags | BUS_DMA_NOWAIT);
1724 1.31 thorpej if (error) {
1725 1.31 thorpej printf("%s: unable to allocate CCB group, error = %d\n",
1726 1.31 thorpej sc->sc_dev.dv_xname, error);
1727 1.31 thorpej goto bad_0;
1728 1.31 thorpej }
1729 1.17 thorpej
1730 1.31 thorpej error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, PAGE_SIZE,
1731 1.31 thorpej (caddr_t *)&bcg,
1732 1.31 thorpej sc->sc_dmaflags | BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
1733 1.31 thorpej if (error) {
1734 1.31 thorpej printf("%s: unable to map CCB group, error = %d\n",
1735 1.31 thorpej sc->sc_dev.dv_xname, error);
1736 1.31 thorpej goto bad_1;
1737 1.17 thorpej }
1738 1.17 thorpej
1739 1.31 thorpej memset(bcg, 0, PAGE_SIZE);
1740 1.31 thorpej
1741 1.31 thorpej error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE,
1742 1.31 thorpej 1, PAGE_SIZE, 0, sc->sc_dmaflags | BUS_DMA_NOWAIT, &ccbmap);
1743 1.31 thorpej if (error) {
1744 1.31 thorpej printf("%s: unable to create CCB group DMA map, error = %d\n",
1745 1.31 thorpej sc->sc_dev.dv_xname, error);
1746 1.31 thorpej goto bad_2;
1747 1.31 thorpej }
1748 1.17 thorpej
1749 1.31 thorpej error = bus_dmamap_load(sc->sc_dmat, ccbmap, bcg, PAGE_SIZE, NULL,
1750 1.31 thorpej sc->sc_dmaflags | BUS_DMA_NOWAIT);
1751 1.31 thorpej if (error) {
1752 1.31 thorpej printf("%s: unable to load CCB group DMA map, error = %d\n",
1753 1.31 thorpej sc->sc_dev.dv_xname, error);
1754 1.31 thorpej goto bad_3;
1755 1.1 mycroft }
1756 1.17 thorpej
1757 1.31 thorpej bcg->bcg_dmamap = ccbmap;
1758 1.17 thorpej
1759 1.31 thorpej #ifdef DIAGNOSTIC
1760 1.31 thorpej if (BHA_CCB_GROUP(&bcg->bcg_ccbs[0]) !=
1761 1.31 thorpej BHA_CCB_GROUP(&bcg->bcg_ccbs[bha_ccbs_per_group - 1]))
1762 1.31 thorpej panic("bha_create_ccbs: CCB group size botch");
1763 1.31 thorpej #endif
1764 1.1 mycroft
1765 1.1 mycroft /*
1766 1.31 thorpej * Add all of the CCBs in this group to the allocating list.
1767 1.1 mycroft */
1768 1.31 thorpej for (i = 0; i < bha_ccbs_per_group; i++) {
1769 1.31 thorpej ccb = &bcg->bcg_ccbs[i];
1770 1.31 thorpej TAILQ_INSERT_TAIL(&sc->sc_allocating_ccbs, ccb, chain);
1771 1.1 mycroft }
1772 1.1 mycroft
1773 1.31 thorpej have_allocating_ccbs:
1774 1.31 thorpej /*
1775 1.31 thorpej * Loop over the allocating list until we reach our CCB target.
1776 1.31 thorpej * If we run out on the list, we'll allocate another group's
1777 1.31 thorpej * worth.
1778 1.31 thorpej */
1779 1.31 thorpej while (sc->sc_cur_ccbs < target) {
1780 1.31 thorpej ccb = TAILQ_FIRST(&sc->sc_allocating_ccbs);
1781 1.31 thorpej if (ccb == NULL)
1782 1.31 thorpej goto allocate_group;
1783 1.31 thorpej if (bha_init_ccb(sc, ccb) != 0) {
1784 1.31 thorpej /*
1785 1.31 thorpej * We were unable to initialize the CCB.
1786 1.31 thorpej * This is likely due to a resource shortage,
1787 1.31 thorpej * so bail out now.
1788 1.31 thorpej */
1789 1.31 thorpej return;
1790 1.1 mycroft }
1791 1.1 mycroft }
1792 1.1 mycroft
1793 1.31 thorpej /*
1794 1.31 thorpej * If we got here, we've reached our target!
1795 1.31 thorpej */
1796 1.31 thorpej return;
1797 1.22 thorpej
1798 1.31 thorpej bad_3:
1799 1.31 thorpej bus_dmamap_destroy(sc->sc_dmat, ccbmap);
1800 1.31 thorpej bad_2:
1801 1.31 thorpej bus_dmamem_unmap(sc->sc_dmat, (caddr_t)bcg, PAGE_SIZE);
1802 1.31 thorpej bad_1:
1803 1.31 thorpej bus_dmamem_free(sc->sc_dmat, &seg, rseg);
1804 1.31 thorpej bad_0:
1805 1.31 thorpej return;
1806 1.31 thorpej }
1807 1.1 mycroft
1808 1.31 thorpej /*
1809 1.31 thorpej * bha_init_ccb:
1810 1.31 thorpej *
1811 1.31 thorpej * Initialize a CCB; helper function for bha_create_ccbs().
1812 1.31 thorpej */
1813 1.31 thorpej int
1814 1.31 thorpej bha_init_ccb(sc, ccb)
1815 1.31 thorpej struct bha_softc *sc;
1816 1.31 thorpej struct bha_ccb *ccb;
1817 1.31 thorpej {
1818 1.31 thorpej struct bha_ccb_group *bcg = BHA_CCB_GROUP(ccb);
1819 1.31 thorpej int hashnum, error;
1820 1.1 mycroft
1821 1.1 mycroft /*
1822 1.31 thorpej * Create the DMA map for this CCB.
1823 1.31 thorpej *
1824 1.31 thorpej * XXX ALLOCNOW is a hack to prevent bounce buffer shortages
1825 1.31 thorpej * XXX in the ISA case. A better solution is needed.
1826 1.1 mycroft */
1827 1.31 thorpej error = bus_dmamap_create(sc->sc_dmat, BHA_MAXXFER, BHA_NSEG,
1828 1.31 thorpej BHA_MAXXFER, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW | sc->sc_dmaflags,
1829 1.31 thorpej &ccb->dmamap_xfer);
1830 1.31 thorpej if (error) {
1831 1.31 thorpej printf("%s: unable to create CCB DMA map, error = %d\n",
1832 1.31 thorpej sc->sc_dev.dv_xname, error);
1833 1.31 thorpej return (error);
1834 1.31 thorpej }
1835 1.31 thorpej
1836 1.31 thorpej TAILQ_REMOVE(&sc->sc_allocating_ccbs, ccb, chain);
1837 1.1 mycroft
1838 1.1 mycroft /*
1839 1.31 thorpej * Put the CCB into the phystokv hash table.
1840 1.1 mycroft */
1841 1.31 thorpej ccb->hashkey = bcg->bcg_dmamap->dm_segs[0].ds_addr +
1842 1.31 thorpej BHA_CCB_OFFSET(ccb);
1843 1.31 thorpej hashnum = CCB_HASH(ccb->hashkey);
1844 1.31 thorpej ccb->nexthash = sc->sc_ccbhash[hashnum];
1845 1.31 thorpej sc->sc_ccbhash[hashnum] = ccb;
1846 1.31 thorpej bha_reset_ccb(ccb);
1847 1.31 thorpej
1848 1.31 thorpej TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
1849 1.31 thorpej sc->sc_cur_ccbs++;
1850 1.1 mycroft
1851 1.31 thorpej return (0);
1852 1.1 mycroft }
1853 1.1 mycroft
1854 1.1 mycroft /*
1855 1.31 thorpej * bha_get_ccb:
1856 1.31 thorpej *
1857 1.31 thorpej * Get a CCB for the SCSI operation. If there are none left,
1858 1.31 thorpej * wait until one becomes available, if we can.
1859 1.1 mycroft */
1860 1.31 thorpej struct bha_ccb *
1861 1.31 thorpej bha_get_ccb(sc, flags)
1862 1.1 mycroft struct bha_softc *sc;
1863 1.31 thorpej int flags;
1864 1.1 mycroft {
1865 1.31 thorpej struct bha_ccb *ccb;
1866 1.31 thorpej int s;
1867 1.31 thorpej
1868 1.31 thorpej s = splbio();
1869 1.1 mycroft
1870 1.31 thorpej for (;;) {
1871 1.31 thorpej ccb = TAILQ_FIRST(&sc->sc_free_ccb);
1872 1.31 thorpej if (ccb) {
1873 1.31 thorpej TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
1874 1.31 thorpej break;
1875 1.31 thorpej }
1876 1.31 thorpej if ((flags & XS_CTL_NOSLEEP) != 0)
1877 1.31 thorpej goto out;
1878 1.31 thorpej tsleep(&sc->sc_free_ccb, PRIBIO, "bhaccb", 0);
1879 1.1 mycroft }
1880 1.31 thorpej
1881 1.31 thorpej ccb->flags |= CCB_ALLOC;
1882 1.31 thorpej
1883 1.31 thorpej out:
1884 1.31 thorpej splx(s);
1885 1.31 thorpej return (ccb);
1886 1.1 mycroft }
1887 1.1 mycroft
1888 1.31 thorpej /*
1889 1.31 thorpej * bha_free_ccb:
1890 1.31 thorpej *
1891 1.31 thorpej * Put a CCB back onto the free list.
1892 1.31 thorpej */
1893 1.1 mycroft void
1894 1.31 thorpej bha_free_ccb(sc, ccb)
1895 1.31 thorpej struct bha_softc *sc;
1896 1.31 thorpej struct bha_ccb *ccb;
1897 1.1 mycroft {
1898 1.1 mycroft int s;
1899 1.1 mycroft
1900 1.1 mycroft s = splbio();
1901 1.1 mycroft
1902 1.31 thorpej bha_reset_ccb(ccb);
1903 1.31 thorpej TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
1904 1.1 mycroft
1905 1.1 mycroft /*
1906 1.31 thorpej * If there were none, wake anybody waiting for one to come free,
1907 1.31 thorpej * starting with queued entries.
1908 1.1 mycroft */
1909 1.31 thorpej if (TAILQ_NEXT(ccb, chain) == NULL)
1910 1.31 thorpej wakeup(&sc->sc_free_ccb);
1911 1.1 mycroft
1912 1.1 mycroft splx(s);
1913 1.31 thorpej }
1914 1.31 thorpej
1915 1.31 thorpej /*
1916 1.31 thorpej * bha_ccb_phys_kv:
1917 1.31 thorpej *
1918 1.31 thorpej * Given a CCB DMA address, locate the CCB in kernel virtual space.
1919 1.31 thorpej */
1920 1.31 thorpej struct bha_ccb *
1921 1.31 thorpej bha_ccb_phys_kv(sc, ccb_phys)
1922 1.31 thorpej struct bha_softc *sc;
1923 1.31 thorpej bus_addr_t ccb_phys;
1924 1.31 thorpej {
1925 1.31 thorpej int hashnum = CCB_HASH(ccb_phys);
1926 1.31 thorpej struct bha_ccb *ccb = sc->sc_ccbhash[hashnum];
1927 1.31 thorpej
1928 1.31 thorpej while (ccb) {
1929 1.31 thorpej if (ccb->hashkey == ccb_phys)
1930 1.31 thorpej break;
1931 1.31 thorpej ccb = ccb->nexthash;
1932 1.31 thorpej }
1933 1.31 thorpej return (ccb);
1934 1.1 mycroft }
1935