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