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