Deleted Added
full compact
bt.c (40749) bt.c (41048)
1/*
2 * Generic driver for the BusLogic MultiMaster SCSI host adapters
3 * Product specific probe and attach routines can be found in:
4 * i386/isa/bt_isa.c BT-54X, BT-445 cards
5 * i386/eisa/bt_eisa.c BT-74x, BT-75x cards
6 * pci/bt_pci.c BT-946, BT-948, BT-956, BT-958 cards
7 *
8 * Copyright (c) 1998 Justin T. Gibbs.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification, immediately at the beginning of the file.
17 * 2. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
1/*
2 * Generic driver for the BusLogic MultiMaster SCSI host adapters
3 * Product specific probe and attach routines can be found in:
4 * i386/isa/bt_isa.c BT-54X, BT-445 cards
5 * i386/eisa/bt_eisa.c BT-74x, BT-75x cards
6 * pci/bt_pci.c BT-946, BT-948, BT-956, BT-958 cards
7 *
8 * Copyright (c) 1998 Justin T. Gibbs.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification, immediately at the beginning of the file.
17 * 2. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: bt.c,v 1.7 1998/10/15 23:46:28 gibbs Exp $
32 * $Id: bt.c,v 1.8 1998/10/30 02:06:44 gibbs Exp $
33 */
34
35 /*
36 * Special thanks to Leonard N. Zubkoff for writing such a complete and
37 * well documented Mylex/BusLogic MultiMaster driver for Linux. Support
38 * in this driver for the wide range of MultiMaster controllers and
39 * firmware revisions, with their otherwise undocumented quirks, would not
40 * have been possible without his efforts.
41 */
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/malloc.h>
46#include <sys/buf.h>
47#include <sys/kernel.h>
48#include <sys/sysctl.h>
49
50/*
51 * XXX It appears that BusLogic PCI adapters go out to lunch if you
52 * attempt to perform memory mapped I/O.
53 */
54#if 0
55#include "pci.h"
56#if NPCI > 0
57#include <machine/bus_memio.h>
58#endif
59#endif
60#include <machine/bus_pio.h>
61#include <machine/bus.h>
62#include <machine/clock.h>
63
64#include <cam/cam.h>
65#include <cam/cam_ccb.h>
66#include <cam/cam_sim.h>
67#include <cam/cam_xpt_sim.h>
68#include <cam/cam_debug.h>
69
70#include <cam/scsi/scsi_message.h>
71
72#include <vm/vm.h>
73#include <vm/pmap.h>
74
75#include <dev/buslogic/btreg.h>
76
77struct bt_softc *bt_softcs[NBT];
78
79/* MailBox Management functions */
80static __inline void btnextinbox(struct bt_softc *bt);
81static __inline void btnextoutbox(struct bt_softc *bt);
82
83static __inline void
84btnextinbox(struct bt_softc *bt)
85{
86 if (bt->cur_inbox == bt->last_inbox)
87 bt->cur_inbox = bt->in_boxes;
88 else
89 bt->cur_inbox++;
90}
91
92static __inline void
93btnextoutbox(struct bt_softc *bt)
94{
95 if (bt->cur_outbox == bt->last_outbox)
96 bt->cur_outbox = bt->out_boxes;
97 else
98 bt->cur_outbox++;
99}
100
101/* CCB Mangement functions */
102static __inline u_int32_t btccbvtop(struct bt_softc *bt,
103 struct bt_ccb *bccb);
104static __inline struct bt_ccb* btccbptov(struct bt_softc *bt,
105 u_int32_t ccb_addr);
106static __inline u_int32_t btsensepaddr(struct bt_softc *bt,
107 struct bt_ccb *bccb);
108static __inline struct scsi_sense_data* btsensevaddr(struct bt_softc *bt,
109 struct bt_ccb *bccb);
110
111static __inline u_int32_t
112btccbvtop(struct bt_softc *bt, struct bt_ccb *bccb)
113{
114 return (bt->bt_ccb_physbase
115 + (u_int32_t)((caddr_t)bccb - (caddr_t)bt->bt_ccb_array));
116}
117
118static __inline struct bt_ccb *
119btccbptov(struct bt_softc *bt, u_int32_t ccb_addr)
120{
121 return (bt->bt_ccb_array +
122 ((struct bt_ccb*)ccb_addr-(struct bt_ccb*)bt->bt_ccb_physbase));
123}
124
125static __inline u_int32_t
126btsensepaddr(struct bt_softc *bt, struct bt_ccb *bccb)
127{
128 u_int index;
129
130 index = (u_int)(bccb - bt->bt_ccb_array);
131 return (bt->sense_buffers_physbase
132 + (index * sizeof(struct scsi_sense_data)));
133}
134
135static __inline struct scsi_sense_data *
136btsensevaddr(struct bt_softc *bt, struct bt_ccb *bccb)
137{
138 u_int index;
139
140 index = (u_int)(bccb - bt->bt_ccb_array);
141 return (bt->sense_buffers + index);
142}
143
144static __inline struct bt_ccb* btgetccb(struct bt_softc *bt);
145static __inline void btfreeccb(struct bt_softc *bt,
146 struct bt_ccb *bccb);
147static void btallocccbs(struct bt_softc *bt);
148static bus_dmamap_callback_t btexecuteccb;
149static void btdone(struct bt_softc *bt, struct bt_ccb *bccb,
150 bt_mbi_comp_code_t comp_code);
151
152/* Host adapter command functions */
153static int btreset(struct bt_softc* bt, int hard_reset);
154
155/* Initialization functions */
156static int btinitmboxes(struct bt_softc *bt);
157static bus_dmamap_callback_t btmapmboxes;
158static bus_dmamap_callback_t btmapccbs;
159static bus_dmamap_callback_t btmapsgs;
160
161/* Transfer Negotiation Functions */
162static void btfetchtransinfo(struct bt_softc *bt,
163 struct ccb_trans_settings *cts);
164
165/* CAM SIM entry points */
166#define ccb_bccb_ptr spriv_ptr0
167#define ccb_bt_ptr spriv_ptr1
168static void btaction(struct cam_sim *sim, union ccb *ccb);
169static void btpoll(struct cam_sim *sim);
170
171/* Our timeout handler */
172timeout_t bttimeout;
173
174u_long bt_unit = 0;
175
176/*
177 * XXX
178 * Do our own re-probe protection until a configuration
179 * manager can do it for us. This ensures that we don't
180 * reprobe a card already found by the EISA or PCI probes.
181 */
182struct bt_isa_port bt_isa_ports[] =
183{
33 */
34
35 /*
36 * Special thanks to Leonard N. Zubkoff for writing such a complete and
37 * well documented Mylex/BusLogic MultiMaster driver for Linux. Support
38 * in this driver for the wide range of MultiMaster controllers and
39 * firmware revisions, with their otherwise undocumented quirks, would not
40 * have been possible without his efforts.
41 */
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/malloc.h>
46#include <sys/buf.h>
47#include <sys/kernel.h>
48#include <sys/sysctl.h>
49
50/*
51 * XXX It appears that BusLogic PCI adapters go out to lunch if you
52 * attempt to perform memory mapped I/O.
53 */
54#if 0
55#include "pci.h"
56#if NPCI > 0
57#include <machine/bus_memio.h>
58#endif
59#endif
60#include <machine/bus_pio.h>
61#include <machine/bus.h>
62#include <machine/clock.h>
63
64#include <cam/cam.h>
65#include <cam/cam_ccb.h>
66#include <cam/cam_sim.h>
67#include <cam/cam_xpt_sim.h>
68#include <cam/cam_debug.h>
69
70#include <cam/scsi/scsi_message.h>
71
72#include <vm/vm.h>
73#include <vm/pmap.h>
74
75#include <dev/buslogic/btreg.h>
76
77struct bt_softc *bt_softcs[NBT];
78
79/* MailBox Management functions */
80static __inline void btnextinbox(struct bt_softc *bt);
81static __inline void btnextoutbox(struct bt_softc *bt);
82
83static __inline void
84btnextinbox(struct bt_softc *bt)
85{
86 if (bt->cur_inbox == bt->last_inbox)
87 bt->cur_inbox = bt->in_boxes;
88 else
89 bt->cur_inbox++;
90}
91
92static __inline void
93btnextoutbox(struct bt_softc *bt)
94{
95 if (bt->cur_outbox == bt->last_outbox)
96 bt->cur_outbox = bt->out_boxes;
97 else
98 bt->cur_outbox++;
99}
100
101/* CCB Mangement functions */
102static __inline u_int32_t btccbvtop(struct bt_softc *bt,
103 struct bt_ccb *bccb);
104static __inline struct bt_ccb* btccbptov(struct bt_softc *bt,
105 u_int32_t ccb_addr);
106static __inline u_int32_t btsensepaddr(struct bt_softc *bt,
107 struct bt_ccb *bccb);
108static __inline struct scsi_sense_data* btsensevaddr(struct bt_softc *bt,
109 struct bt_ccb *bccb);
110
111static __inline u_int32_t
112btccbvtop(struct bt_softc *bt, struct bt_ccb *bccb)
113{
114 return (bt->bt_ccb_physbase
115 + (u_int32_t)((caddr_t)bccb - (caddr_t)bt->bt_ccb_array));
116}
117
118static __inline struct bt_ccb *
119btccbptov(struct bt_softc *bt, u_int32_t ccb_addr)
120{
121 return (bt->bt_ccb_array +
122 ((struct bt_ccb*)ccb_addr-(struct bt_ccb*)bt->bt_ccb_physbase));
123}
124
125static __inline u_int32_t
126btsensepaddr(struct bt_softc *bt, struct bt_ccb *bccb)
127{
128 u_int index;
129
130 index = (u_int)(bccb - bt->bt_ccb_array);
131 return (bt->sense_buffers_physbase
132 + (index * sizeof(struct scsi_sense_data)));
133}
134
135static __inline struct scsi_sense_data *
136btsensevaddr(struct bt_softc *bt, struct bt_ccb *bccb)
137{
138 u_int index;
139
140 index = (u_int)(bccb - bt->bt_ccb_array);
141 return (bt->sense_buffers + index);
142}
143
144static __inline struct bt_ccb* btgetccb(struct bt_softc *bt);
145static __inline void btfreeccb(struct bt_softc *bt,
146 struct bt_ccb *bccb);
147static void btallocccbs(struct bt_softc *bt);
148static bus_dmamap_callback_t btexecuteccb;
149static void btdone(struct bt_softc *bt, struct bt_ccb *bccb,
150 bt_mbi_comp_code_t comp_code);
151
152/* Host adapter command functions */
153static int btreset(struct bt_softc* bt, int hard_reset);
154
155/* Initialization functions */
156static int btinitmboxes(struct bt_softc *bt);
157static bus_dmamap_callback_t btmapmboxes;
158static bus_dmamap_callback_t btmapccbs;
159static bus_dmamap_callback_t btmapsgs;
160
161/* Transfer Negotiation Functions */
162static void btfetchtransinfo(struct bt_softc *bt,
163 struct ccb_trans_settings *cts);
164
165/* CAM SIM entry points */
166#define ccb_bccb_ptr spriv_ptr0
167#define ccb_bt_ptr spriv_ptr1
168static void btaction(struct cam_sim *sim, union ccb *ccb);
169static void btpoll(struct cam_sim *sim);
170
171/* Our timeout handler */
172timeout_t bttimeout;
173
174u_long bt_unit = 0;
175
176/*
177 * XXX
178 * Do our own re-probe protection until a configuration
179 * manager can do it for us. This ensures that we don't
180 * reprobe a card already found by the EISA or PCI probes.
181 */
182struct bt_isa_port bt_isa_ports[] =
183{
184 { 0x330, 0 },
185 { 0x334, 0 },
186 { 0x230, 0 },
187 { 0x234, 0 },
188 { 0x130, 0 },
189 { 0x134, 0 }
184 { 0x130, 0, 4 },
185 { 0x134, 0, 5 },
186 { 0x230, 0, 2 },
187 { 0x234, 0, 3 },
188 { 0x330, 0, 0 },
189 { 0x334, 0, 1 }
190};
191
190};
191
192/*
193 * I/O ports listed in the order enumerated by the
194 * card for certain op codes.
195 */
196u_int16_t bt_board_ports[] =
197{
198 0x330,
199 0x334,
200 0x230,
201 0x234,
202 0x130,
203 0x134
204};
205
192/* Exported functions */
193struct bt_softc *
194bt_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh)
195{
196 struct bt_softc *bt;
197
198 if (unit != BT_TEMP_UNIT) {
199 if (unit >= NBT) {
200 printf("bt: unit number (%d) too high\n", unit);
201 return NULL;
202 }
203
204 /*
205 * Allocate a storage area for us
206 */
207 if (bt_softcs[unit]) {
208 printf("bt%d: memory already allocated\n", unit);
209 return NULL;
210 }
211 }
212
213 bt = malloc(sizeof(struct bt_softc), M_DEVBUF, M_NOWAIT);
214 if (!bt) {
215 printf("bt%d: cannot malloc!\n", unit);
216 return NULL;
217 }
218 bzero(bt, sizeof(struct bt_softc));
219 SLIST_INIT(&bt->free_bt_ccbs);
220 LIST_INIT(&bt->pending_ccbs);
221 SLIST_INIT(&bt->sg_maps);
222 bt->unit = unit;
223 bt->tag = tag;
224 bt->bsh = bsh;
225
226 if (bt->unit != BT_TEMP_UNIT) {
227 bt_softcs[unit] = bt;
228 }
229 return (bt);
230}
231
232void
233bt_free(struct bt_softc *bt)
234{
235 switch (bt->init_level) {
236 default:
237 case 11:
238 bus_dmamap_unload(bt->sense_dmat, bt->sense_dmamap);
239 case 10:
240 bus_dmamem_free(bt->sense_dmat, bt->sense_buffers,
241 bt->sense_dmamap);
242 case 9:
243 bus_dma_tag_destroy(bt->sense_dmat);
244 case 8:
245 {
246 struct sg_map_node *sg_map;
247
248 while ((sg_map = SLIST_FIRST(&bt->sg_maps))!= NULL) {
249 SLIST_REMOVE_HEAD(&bt->sg_maps, links);
250 bus_dmamap_unload(bt->sg_dmat,
251 sg_map->sg_dmamap);
252 bus_dmamem_free(bt->sg_dmat, sg_map->sg_vaddr,
253 sg_map->sg_dmamap);
254 free(sg_map, M_DEVBUF);
255 }
256 bus_dma_tag_destroy(bt->sg_dmat);
257 }
258 case 7:
259 bus_dmamap_unload(bt->ccb_dmat, bt->ccb_dmamap);
260 case 6:
261 bus_dmamem_free(bt->ccb_dmat, bt->bt_ccb_array,
262 bt->ccb_dmamap);
263 bus_dmamap_destroy(bt->ccb_dmat, bt->ccb_dmamap);
264 case 5:
265 bus_dma_tag_destroy(bt->ccb_dmat);
266 case 4:
267 bus_dmamap_unload(bt->mailbox_dmat, bt->mailbox_dmamap);
268 case 3:
269 bus_dmamem_free(bt->mailbox_dmat, bt->in_boxes,
270 bt->mailbox_dmamap);
271 bus_dmamap_destroy(bt->mailbox_dmat, bt->mailbox_dmamap);
272 case 2:
273 bus_dma_tag_destroy(bt->buffer_dmat);
274 case 1:
275 bus_dma_tag_destroy(bt->mailbox_dmat);
276 case 0:
277 break;
278 }
279 if (bt->unit != BT_TEMP_UNIT) {
280 bt_softcs[bt->unit] = NULL;
281 }
282 free(bt, M_DEVBUF);
283}
284
285/*
286 * Probe the adapter and verify that the card is a BusLogic.
287 */
288int
289bt_probe(struct bt_softc* bt)
290{
291 esetup_info_data_t esetup_info;
292 u_int status;
293 u_int intstat;
294 u_int geometry;
295 int error;
296 u_int8_t param;
297
298 /*
299 * See if the three I/O ports look reasonable.
300 * Touch the minimal number of registers in the
301 * failure case.
302 */
303 status = bt_inb(bt, STATUS_REG);
304 if ((status == 0)
305 || (status & (DIAG_ACTIVE|CMD_REG_BUSY|
306 STATUS_REG_RSVD|CMD_INVALID)) != 0) {
307 if (bootverbose)
308 printf("%s: Failed Status Reg Test - %x\n", bt_name(bt),
309 status);
310 return (ENXIO);
311 }
312
313 intstat = bt_inb(bt, INTSTAT_REG);
314 if ((intstat & INTSTAT_REG_RSVD) != 0) {
315 printf("%s: Failed Intstat Reg Test\n", bt_name(bt));
316 return (ENXIO);
317 }
318
319 geometry = bt_inb(bt, GEOMETRY_REG);
320 if (geometry == 0xFF) {
321 if (bootverbose)
322 printf("%s: Failed Geometry Reg Test\n", bt_name(bt));
323 return (ENXIO);
324 }
325
326 /*
327 * Looking good so far. Final test is to reset the
328 * adapter and attempt to fetch the extended setup
329 * information. This should filter out all 1542 cards.
330 */
331 if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) {
332 if (bootverbose)
333 printf("%s: Failed Reset\n", bt_name(bt));
334 return (ENXIO);
335 }
336
337 param = sizeof(esetup_info);
338 error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, &param, /*parmlen*/1,
339 (u_int8_t*)&esetup_info, sizeof(esetup_info),
340 DEFAULT_CMD_TIMEOUT);
341 if (error != 0) {
342 return (ENXIO);
343 }
344
345 return (0);
346}
347
348/*
349 * Pull the boards setup information and record it in our softc.
350 */
351int
352bt_fetch_adapter_info(struct bt_softc *bt)
353{
354 board_id_data_t board_id;
355 esetup_info_data_t esetup_info;
356 config_data_t config_data;
357 int error;
358 u_int8_t length_param;
359
360 /* First record the firmware version */
361 error = bt_cmd(bt, BOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0,
362 (u_int8_t*)&board_id, sizeof(board_id),
363 DEFAULT_CMD_TIMEOUT);
364 if (error != 0) {
365 printf("%s: bt_fetch_adapter_info - Failed Get Board Info\n",
366 bt_name(bt));
367 return (error);
368 }
369 bt->firmware_ver[0] = board_id.firmware_rev_major;
370 bt->firmware_ver[1] = '.';
371 bt->firmware_ver[2] = board_id.firmware_rev_minor;
372 bt->firmware_ver[3] = '\0';
373
374 /*
375 * Depending on the firmware major and minor version,
376 * we may be able to fetch additional minor version info.
377 */
378 if (bt->firmware_ver[0] > '0') {
379
380 error = bt_cmd(bt, BOP_INQUIRE_FW_VER_3DIG, NULL, /*parmlen*/0,
381 (u_int8_t*)&bt->firmware_ver[3], 1,
382 DEFAULT_CMD_TIMEOUT);
383 if (error != 0) {
384 printf("%s: bt_fetch_adapter_info - Failed Get "
385 "Firmware 3rd Digit\n", bt_name(bt));
386 return (error);
387 }
388 if (bt->firmware_ver[3] == ' ')
389 bt->firmware_ver[3] = '\0';
390 bt->firmware_ver[4] = '\0';
391 }
392
393 if (strcmp(bt->firmware_ver, "3.3") >= 0) {
394
395 error = bt_cmd(bt, BOP_INQUIRE_FW_VER_4DIG, NULL, /*parmlen*/0,
396 (u_int8_t*)&bt->firmware_ver[4], 1,
397 DEFAULT_CMD_TIMEOUT);
398 if (error != 0) {
399 printf("%s: bt_fetch_adapter_info - Failed Get "
400 "Firmware 4th Digit\n", bt_name(bt));
401 return (error);
402 }
403 if (bt->firmware_ver[4] == ' ')
404 bt->firmware_ver[4] = '\0';
405 bt->firmware_ver[5] = '\0';
406 }
407
408 /*
409 * Some boards do not handle the "recently documented"
410 * Inquire Board Model Number command correctly or do not give
411 * exact information. Use the Firmware and Extended Setup
412 * information in these cases to come up with the right answer.
413 * The major firmware revision number indicates:
414 *
415 * 5.xx BusLogic "W" Series Host Adapters:
416 * BT-948/958/958D
417 * 4.xx BusLogic "C" Series Host Adapters:
418 * BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
419 * 3.xx BusLogic "S" Series Host Adapters:
420 * BT-747S/747D/757S/757D/445S/545S/542D
421 * BT-542B/742A (revision H)
422 * 2.xx BusLogic "A" Series Host Adapters:
423 * BT-542B/742A (revision G and below)
424 * 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
425 */
426 length_param = sizeof(esetup_info);
427 error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, &length_param, /*parmlen*/1,
428 (u_int8_t*)&esetup_info, sizeof(esetup_info),
429 DEFAULT_CMD_TIMEOUT);
430 if (error != 0) {
431 return (error);
432 }
433
434 bt->bios_addr = esetup_info.bios_addr << 12;
435
436 if (esetup_info.bus_type == 'A'
437 && bt->firmware_ver[0] == '2') {
438 strcpy(bt->model, "542B");
439 } else if (esetup_info.bus_type == 'E'
440 && (strncmp(bt->firmware_ver, "2.1", 3) == 0
441 || strncmp(bt->firmware_ver, "2.20", 4) == 0)) {
442 strcpy(bt->model, "742A");
443 } else if (esetup_info.bus_type == 'E'
444 && bt->firmware_ver[0] == '0') {
445 /* AMI FastDisk EISA Series 441 0.x */
446 strcpy(bt->model, "747A");
447 } else {
448 ha_model_data_t model_data;
449 int i;
450
451 length_param = sizeof(model_data);
452 error = bt_cmd(bt, BOP_INQUIRE_MODEL, &length_param, 1,
453 (u_int8_t*)&model_data, sizeof(model_data),
454 DEFAULT_CMD_TIMEOUT);
455 if (error != 0) {
456 printf("%s: bt_fetch_adapter_info - Failed Inquire "
457 "Model Number\n", bt_name(bt));
458 return (error);
459 }
460 for (i = 0; i < sizeof(model_data.ascii_model); i++) {
461 bt->model[i] = model_data.ascii_model[i];
462 if (bt->model[i] == ' ')
463 break;
464 }
465 bt->model[i] = '\0';
466 }
467
468 /* SG element limits */
469 bt->max_sg = esetup_info.max_sg;
470
471 /* Set feature flags */
472 bt->wide_bus = esetup_info.wide_bus;
473 bt->diff_bus = esetup_info.diff_bus;
474 bt->ultra_scsi = esetup_info.ultra_scsi;
475
476 if ((bt->firmware_ver[0] == '5')
477 || (bt->firmware_ver[0] == '4' && bt->wide_bus))
478 bt->extended_lun = TRUE;
479
480 bt->strict_rr = (strcmp(bt->firmware_ver, "3.31") >= 0);
481
482 bt->extended_trans =
483 ((bt_inb(bt, GEOMETRY_REG) & EXTENDED_TRANSLATION) != 0);
484
485 /*
486 * Determine max CCB count and whether tagged queuing is
487 * available based on controller type. Tagged queuing
488 * only works on 'W' series adapters, 'C' series adapters
489 * with firmware of rev 4.42 and higher, and 'S' series
490 * adapters with firmware of rev 3.35 and higher. The
491 * maximum CCB counts are as follows:
492 *
493 * 192 BT-948/958/958D
494 * 100 BT-946C/956C/956CD/747C/757C/757CD/445C
495 * 50 BT-545C/540CF
496 * 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
497 */
498 if (bt->firmware_ver[0] == '5') {
499 bt->max_ccbs = 192;
500 bt->tag_capable = TRUE;
501 } else if (bt->firmware_ver[0] == '4') {
502 if (bt->model[0] == '5')
503 bt->max_ccbs = 50;
504 else
505 bt->max_ccbs = 100;
506 bt->tag_capable = (strcmp(bt->firmware_ver, "4.22") >= 0);
507 } else {
508 bt->max_ccbs = 30;
509 if (bt->firmware_ver[0] == '3'
510 && (strcmp(bt->firmware_ver, "3.35") >= 0))
511 bt->tag_capable = TRUE;
512 else
513 bt->tag_capable = FALSE;
514 }
515
516 if (bt->tag_capable != FALSE)
517 bt->tags_permitted = ALL_TARGETS;
518
519 /* Determine Sync/Wide/Disc settings */
520 if (bt->firmware_ver[0] >= '4') {
521 auto_scsi_data_t auto_scsi_data;
522 fetch_lram_params_t fetch_lram_params;
523 int error;
524
525 /*
526 * These settings are stored in the
527 * AutoSCSI data in LRAM of 'W' and 'C'
528 * adapters.
529 */
530 fetch_lram_params.offset = AUTO_SCSI_BYTE_OFFSET;
531 fetch_lram_params.response_len = sizeof(auto_scsi_data);
532 error = bt_cmd(bt, BOP_FETCH_LRAM,
533 (u_int8_t*)&fetch_lram_params,
534 sizeof(fetch_lram_params),
535 (u_int8_t*)&auto_scsi_data,
536 sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT);
537
538 if (error != 0) {
539 printf("%s: bt_fetch_adapter_info - Failed "
540 "Get Auto SCSI Info\n", bt_name(bt));
541 return (error);
542 }
543
544 bt->disc_permitted = auto_scsi_data.low_disc_permitted
545 | (auto_scsi_data.high_disc_permitted << 8);
546 bt->sync_permitted = auto_scsi_data.low_sync_permitted
547 | (auto_scsi_data.high_sync_permitted << 8);
548 bt->fast_permitted = auto_scsi_data.low_fast_permitted
549 | (auto_scsi_data.high_fast_permitted << 8);
550 bt->ultra_permitted = auto_scsi_data.low_ultra_permitted
551 | (auto_scsi_data.high_ultra_permitted << 8);
552 bt->wide_permitted = auto_scsi_data.low_wide_permitted
553 | (auto_scsi_data.high_wide_permitted << 8);
554
555 if (bt->ultra_scsi == FALSE)
556 bt->ultra_permitted = 0;
557
558 if (bt->wide_bus == FALSE)
559 bt->wide_permitted = 0;
560 } else {
561 /*
562 * 'S' and 'A' series have this information in the setup
563 * information structure.
564 */
565 setup_data_t setup_info;
566
567 length_param = sizeof(setup_info);
568 error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, &length_param,
569 /*paramlen*/1, (u_int8_t*)&setup_info,
570 sizeof(setup_info), DEFAULT_CMD_TIMEOUT);
571
572 if (error != 0) {
573 printf("%s: bt_fetch_adapter_info - Failed "
574 "Get Setup Info\n", bt_name(bt));
575 return (error);
576 }
577
578 if (setup_info.initiate_sync != 0) {
579 bt->sync_permitted = ALL_TARGETS;
580
581 if (bt->model[0] == '7') {
582 if (esetup_info.sync_neg10MB != 0)
583 bt->fast_permitted = ALL_TARGETS;
584 if (strcmp(bt->model, "757") == 0)
585 bt->wide_permitted = ALL_TARGETS;
586 }
587 }
588 bt->disc_permitted = ALL_TARGETS;
589 }
590
591 /* We need as many mailboxes as we can have ccbs */
592 bt->num_boxes = bt->max_ccbs;
593
594 /* Determine our SCSI ID */
595
596 error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
597 (u_int8_t*)&config_data, sizeof(config_data),
598 DEFAULT_CMD_TIMEOUT);
599 if (error != 0) {
600 printf("%s: bt_fetch_adapter_info - Failed Get Config\n",
601 bt_name(bt));
602 return (error);
603 }
604 bt->scsi_id = config_data.scsi_id;
605
606 return (0);
607}
608
609/*
610 * Start the board, ready for normal operation
611 */
612int
613bt_init(struct bt_softc* bt)
614{
615 /* Announce the Adapter */
616 printf("%s: BT-%s FW Rev. %s ", bt_name(bt),
617 bt->model, bt->firmware_ver);
618
619 if (bt->ultra_scsi != 0)
620 printf("Ultra ");
621
622 if (bt->wide_bus != 0)
623 printf("Wide ");
624 else
625 printf("Narrow ");
626
627 if (bt->diff_bus != 0)
628 printf("Diff ");
629
630 printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", bt->scsi_id,
631 bt->max_ccbs);
632
633 /*
634 * Create our DMA tags. These tags define the kinds of device
635 * accessable memory allocations and memory mappings we will
636 * need to perform during normal operation.
637 *
638 * Unless we need to further restrict the allocation, we rely
639 * on the restrictions of the parent dmat, hence the common
640 * use of MAXADDR and MAXSIZE.
641 */
642
643 /* DMA tag for mapping buffers into device visible space. */
644 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,
645 /*lowaddr*/BUS_SPACE_MAXADDR,
646 /*highaddr*/BUS_SPACE_MAXADDR,
647 /*filter*/NULL, /*filterarg*/NULL,
648 /*maxsize*/MAXBSIZE, /*nsegments*/BT_NSEG,
649 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
650 /*flags*/BUS_DMA_ALLOCNOW,
651 &bt->buffer_dmat) != 0) {
652 goto error_exit;
653 }
654
655 bt->init_level++;
656 /* DMA tag for our mailboxes */
657 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,
658 /*lowaddr*/BUS_SPACE_MAXADDR,
659 /*highaddr*/BUS_SPACE_MAXADDR,
660 /*filter*/NULL, /*filterarg*/NULL,
661 bt->num_boxes * (sizeof(bt_mbox_in_t)
662 + sizeof(bt_mbox_out_t)),
663 /*nsegments*/1,
664 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
665 /*flags*/0, &bt->mailbox_dmat) != 0) {
666 goto error_exit;
667 }
668
669 bt->init_level++;
670
671 /* Allocation for our mailboxes */
672 if (bus_dmamem_alloc(bt->mailbox_dmat, (void **)&bt->out_boxes,
673 BUS_DMA_NOWAIT, &bt->mailbox_dmamap) != 0) {
674 goto error_exit;
675 }
676
677 bt->init_level++;
678
679 /* And permanently map them */
680 bus_dmamap_load(bt->mailbox_dmat, bt->mailbox_dmamap,
681 bt->out_boxes,
682 bt->num_boxes * (sizeof(bt_mbox_in_t)
683 + sizeof(bt_mbox_out_t)),
684 btmapmboxes, bt, /*flags*/0);
685
686 bt->init_level++;
687
688 bt->in_boxes = (bt_mbox_in_t *)&bt->out_boxes[bt->num_boxes];
689
690 btinitmboxes(bt);
691
692 /* DMA tag for our ccb structures */
693 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,
694 /*lowaddr*/BUS_SPACE_MAXADDR,
695 /*highaddr*/BUS_SPACE_MAXADDR,
696 /*filter*/NULL, /*filterarg*/NULL,
697 bt->max_ccbs * sizeof(struct bt_ccb),
698 /*nsegments*/1,
699 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
700 /*flags*/0, &bt->ccb_dmat) != 0) {
701 goto error_exit;
702 }
703
704 bt->init_level++;
705
706 /* Allocation for our ccbs */
707 if (bus_dmamem_alloc(bt->ccb_dmat, (void **)&bt->bt_ccb_array,
708 BUS_DMA_NOWAIT, &bt->ccb_dmamap) != 0) {
709 goto error_exit;
710 }
711
712 bt->init_level++;
713
714 /* And permanently map them */
715 bus_dmamap_load(bt->ccb_dmat, bt->ccb_dmamap,
716 bt->bt_ccb_array,
717 bt->max_ccbs * sizeof(struct bt_ccb),
718 btmapccbs, bt, /*flags*/0);
719
720 bt->init_level++;
721
722 /* DMA tag for our S/G structures. We allocate in page sized chunks */
723 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,
724 /*lowaddr*/BUS_SPACE_MAXADDR,
725 /*highaddr*/BUS_SPACE_MAXADDR,
726 /*filter*/NULL, /*filterarg*/NULL,
727 PAGE_SIZE, /*nsegments*/1,
728 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
729 /*flags*/0, &bt->sg_dmat) != 0) {
730 goto error_exit;
731 }
732
733 bt->init_level++;
734
735 /* Perform initial CCB allocation */
736 bzero(bt->bt_ccb_array, bt->max_ccbs * sizeof(struct bt_ccb));
737 btallocccbs(bt);
738
739 if (bt->num_ccbs == 0) {
740 printf("%s: bt_init - Unable to allocate initial ccbs\n",
741 bt_name(bt));
742 goto error_exit;
743 }
744
745 /*
746 * Note that we are going and return (to probe)
747 */
748 return 0;
749
750error_exit:
751
752 return (ENXIO);
753}
754
755int
756bt_attach(struct bt_softc *bt)
757{
758 int tagged_dev_openings;
759 struct cam_devq *devq;
760
761 /*
762 * We reserve 1 ccb for error recovery, so don't
763 * tell the XPT about it.
764 */
765 if (bt->tag_capable != 0)
766 tagged_dev_openings = bt->max_ccbs - 1;
767 else
768 tagged_dev_openings = 0;
769
770 /*
771 * Create the device queue for our SIM.
772 */
773 devq = cam_simq_alloc(bt->max_ccbs - 1);
774 if (devq == NULL)
775 return (ENOMEM);
776
777 /*
778 * Construct our SIM entry
779 */
780 bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, bt->unit,
781 2, tagged_dev_openings, devq);
782 if (bt->sim == NULL) {
783 cam_simq_free(devq);
784 return (ENOMEM);
785 }
786
787 if (xpt_bus_register(bt->sim, 0) != CAM_SUCCESS) {
788 cam_sim_free(bt->sim, /*free_devq*/TRUE);
789 return (ENXIO);
790 }
791
792 if (xpt_create_path(&bt->path, /*periph*/NULL,
793 cam_sim_path(bt->sim), CAM_TARGET_WILDCARD,
794 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
795 xpt_bus_deregister(cam_sim_path(bt->sim));
796 cam_sim_free(bt->sim, /*free_devq*/TRUE);
797 return (ENXIO);
798 }
799
800 return (0);
801}
802
803char *
804bt_name(struct bt_softc *bt)
805{
806 static char name[10];
807
808 sprintf(name, "bt%d", bt->unit);
809 return (name);
810}
811
812int
813bt_check_probed_iop(u_int ioport)
814{
815 u_int i;
816
206/* Exported functions */
207struct bt_softc *
208bt_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh)
209{
210 struct bt_softc *bt;
211
212 if (unit != BT_TEMP_UNIT) {
213 if (unit >= NBT) {
214 printf("bt: unit number (%d) too high\n", unit);
215 return NULL;
216 }
217
218 /*
219 * Allocate a storage area for us
220 */
221 if (bt_softcs[unit]) {
222 printf("bt%d: memory already allocated\n", unit);
223 return NULL;
224 }
225 }
226
227 bt = malloc(sizeof(struct bt_softc), M_DEVBUF, M_NOWAIT);
228 if (!bt) {
229 printf("bt%d: cannot malloc!\n", unit);
230 return NULL;
231 }
232 bzero(bt, sizeof(struct bt_softc));
233 SLIST_INIT(&bt->free_bt_ccbs);
234 LIST_INIT(&bt->pending_ccbs);
235 SLIST_INIT(&bt->sg_maps);
236 bt->unit = unit;
237 bt->tag = tag;
238 bt->bsh = bsh;
239
240 if (bt->unit != BT_TEMP_UNIT) {
241 bt_softcs[unit] = bt;
242 }
243 return (bt);
244}
245
246void
247bt_free(struct bt_softc *bt)
248{
249 switch (bt->init_level) {
250 default:
251 case 11:
252 bus_dmamap_unload(bt->sense_dmat, bt->sense_dmamap);
253 case 10:
254 bus_dmamem_free(bt->sense_dmat, bt->sense_buffers,
255 bt->sense_dmamap);
256 case 9:
257 bus_dma_tag_destroy(bt->sense_dmat);
258 case 8:
259 {
260 struct sg_map_node *sg_map;
261
262 while ((sg_map = SLIST_FIRST(&bt->sg_maps))!= NULL) {
263 SLIST_REMOVE_HEAD(&bt->sg_maps, links);
264 bus_dmamap_unload(bt->sg_dmat,
265 sg_map->sg_dmamap);
266 bus_dmamem_free(bt->sg_dmat, sg_map->sg_vaddr,
267 sg_map->sg_dmamap);
268 free(sg_map, M_DEVBUF);
269 }
270 bus_dma_tag_destroy(bt->sg_dmat);
271 }
272 case 7:
273 bus_dmamap_unload(bt->ccb_dmat, bt->ccb_dmamap);
274 case 6:
275 bus_dmamem_free(bt->ccb_dmat, bt->bt_ccb_array,
276 bt->ccb_dmamap);
277 bus_dmamap_destroy(bt->ccb_dmat, bt->ccb_dmamap);
278 case 5:
279 bus_dma_tag_destroy(bt->ccb_dmat);
280 case 4:
281 bus_dmamap_unload(bt->mailbox_dmat, bt->mailbox_dmamap);
282 case 3:
283 bus_dmamem_free(bt->mailbox_dmat, bt->in_boxes,
284 bt->mailbox_dmamap);
285 bus_dmamap_destroy(bt->mailbox_dmat, bt->mailbox_dmamap);
286 case 2:
287 bus_dma_tag_destroy(bt->buffer_dmat);
288 case 1:
289 bus_dma_tag_destroy(bt->mailbox_dmat);
290 case 0:
291 break;
292 }
293 if (bt->unit != BT_TEMP_UNIT) {
294 bt_softcs[bt->unit] = NULL;
295 }
296 free(bt, M_DEVBUF);
297}
298
299/*
300 * Probe the adapter and verify that the card is a BusLogic.
301 */
302int
303bt_probe(struct bt_softc* bt)
304{
305 esetup_info_data_t esetup_info;
306 u_int status;
307 u_int intstat;
308 u_int geometry;
309 int error;
310 u_int8_t param;
311
312 /*
313 * See if the three I/O ports look reasonable.
314 * Touch the minimal number of registers in the
315 * failure case.
316 */
317 status = bt_inb(bt, STATUS_REG);
318 if ((status == 0)
319 || (status & (DIAG_ACTIVE|CMD_REG_BUSY|
320 STATUS_REG_RSVD|CMD_INVALID)) != 0) {
321 if (bootverbose)
322 printf("%s: Failed Status Reg Test - %x\n", bt_name(bt),
323 status);
324 return (ENXIO);
325 }
326
327 intstat = bt_inb(bt, INTSTAT_REG);
328 if ((intstat & INTSTAT_REG_RSVD) != 0) {
329 printf("%s: Failed Intstat Reg Test\n", bt_name(bt));
330 return (ENXIO);
331 }
332
333 geometry = bt_inb(bt, GEOMETRY_REG);
334 if (geometry == 0xFF) {
335 if (bootverbose)
336 printf("%s: Failed Geometry Reg Test\n", bt_name(bt));
337 return (ENXIO);
338 }
339
340 /*
341 * Looking good so far. Final test is to reset the
342 * adapter and attempt to fetch the extended setup
343 * information. This should filter out all 1542 cards.
344 */
345 if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) {
346 if (bootverbose)
347 printf("%s: Failed Reset\n", bt_name(bt));
348 return (ENXIO);
349 }
350
351 param = sizeof(esetup_info);
352 error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, &param, /*parmlen*/1,
353 (u_int8_t*)&esetup_info, sizeof(esetup_info),
354 DEFAULT_CMD_TIMEOUT);
355 if (error != 0) {
356 return (ENXIO);
357 }
358
359 return (0);
360}
361
362/*
363 * Pull the boards setup information and record it in our softc.
364 */
365int
366bt_fetch_adapter_info(struct bt_softc *bt)
367{
368 board_id_data_t board_id;
369 esetup_info_data_t esetup_info;
370 config_data_t config_data;
371 int error;
372 u_int8_t length_param;
373
374 /* First record the firmware version */
375 error = bt_cmd(bt, BOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0,
376 (u_int8_t*)&board_id, sizeof(board_id),
377 DEFAULT_CMD_TIMEOUT);
378 if (error != 0) {
379 printf("%s: bt_fetch_adapter_info - Failed Get Board Info\n",
380 bt_name(bt));
381 return (error);
382 }
383 bt->firmware_ver[0] = board_id.firmware_rev_major;
384 bt->firmware_ver[1] = '.';
385 bt->firmware_ver[2] = board_id.firmware_rev_minor;
386 bt->firmware_ver[3] = '\0';
387
388 /*
389 * Depending on the firmware major and minor version,
390 * we may be able to fetch additional minor version info.
391 */
392 if (bt->firmware_ver[0] > '0') {
393
394 error = bt_cmd(bt, BOP_INQUIRE_FW_VER_3DIG, NULL, /*parmlen*/0,
395 (u_int8_t*)&bt->firmware_ver[3], 1,
396 DEFAULT_CMD_TIMEOUT);
397 if (error != 0) {
398 printf("%s: bt_fetch_adapter_info - Failed Get "
399 "Firmware 3rd Digit\n", bt_name(bt));
400 return (error);
401 }
402 if (bt->firmware_ver[3] == ' ')
403 bt->firmware_ver[3] = '\0';
404 bt->firmware_ver[4] = '\0';
405 }
406
407 if (strcmp(bt->firmware_ver, "3.3") >= 0) {
408
409 error = bt_cmd(bt, BOP_INQUIRE_FW_VER_4DIG, NULL, /*parmlen*/0,
410 (u_int8_t*)&bt->firmware_ver[4], 1,
411 DEFAULT_CMD_TIMEOUT);
412 if (error != 0) {
413 printf("%s: bt_fetch_adapter_info - Failed Get "
414 "Firmware 4th Digit\n", bt_name(bt));
415 return (error);
416 }
417 if (bt->firmware_ver[4] == ' ')
418 bt->firmware_ver[4] = '\0';
419 bt->firmware_ver[5] = '\0';
420 }
421
422 /*
423 * Some boards do not handle the "recently documented"
424 * Inquire Board Model Number command correctly or do not give
425 * exact information. Use the Firmware and Extended Setup
426 * information in these cases to come up with the right answer.
427 * The major firmware revision number indicates:
428 *
429 * 5.xx BusLogic "W" Series Host Adapters:
430 * BT-948/958/958D
431 * 4.xx BusLogic "C" Series Host Adapters:
432 * BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
433 * 3.xx BusLogic "S" Series Host Adapters:
434 * BT-747S/747D/757S/757D/445S/545S/542D
435 * BT-542B/742A (revision H)
436 * 2.xx BusLogic "A" Series Host Adapters:
437 * BT-542B/742A (revision G and below)
438 * 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
439 */
440 length_param = sizeof(esetup_info);
441 error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, &length_param, /*parmlen*/1,
442 (u_int8_t*)&esetup_info, sizeof(esetup_info),
443 DEFAULT_CMD_TIMEOUT);
444 if (error != 0) {
445 return (error);
446 }
447
448 bt->bios_addr = esetup_info.bios_addr << 12;
449
450 if (esetup_info.bus_type == 'A'
451 && bt->firmware_ver[0] == '2') {
452 strcpy(bt->model, "542B");
453 } else if (esetup_info.bus_type == 'E'
454 && (strncmp(bt->firmware_ver, "2.1", 3) == 0
455 || strncmp(bt->firmware_ver, "2.20", 4) == 0)) {
456 strcpy(bt->model, "742A");
457 } else if (esetup_info.bus_type == 'E'
458 && bt->firmware_ver[0] == '0') {
459 /* AMI FastDisk EISA Series 441 0.x */
460 strcpy(bt->model, "747A");
461 } else {
462 ha_model_data_t model_data;
463 int i;
464
465 length_param = sizeof(model_data);
466 error = bt_cmd(bt, BOP_INQUIRE_MODEL, &length_param, 1,
467 (u_int8_t*)&model_data, sizeof(model_data),
468 DEFAULT_CMD_TIMEOUT);
469 if (error != 0) {
470 printf("%s: bt_fetch_adapter_info - Failed Inquire "
471 "Model Number\n", bt_name(bt));
472 return (error);
473 }
474 for (i = 0; i < sizeof(model_data.ascii_model); i++) {
475 bt->model[i] = model_data.ascii_model[i];
476 if (bt->model[i] == ' ')
477 break;
478 }
479 bt->model[i] = '\0';
480 }
481
482 /* SG element limits */
483 bt->max_sg = esetup_info.max_sg;
484
485 /* Set feature flags */
486 bt->wide_bus = esetup_info.wide_bus;
487 bt->diff_bus = esetup_info.diff_bus;
488 bt->ultra_scsi = esetup_info.ultra_scsi;
489
490 if ((bt->firmware_ver[0] == '5')
491 || (bt->firmware_ver[0] == '4' && bt->wide_bus))
492 bt->extended_lun = TRUE;
493
494 bt->strict_rr = (strcmp(bt->firmware_ver, "3.31") >= 0);
495
496 bt->extended_trans =
497 ((bt_inb(bt, GEOMETRY_REG) & EXTENDED_TRANSLATION) != 0);
498
499 /*
500 * Determine max CCB count and whether tagged queuing is
501 * available based on controller type. Tagged queuing
502 * only works on 'W' series adapters, 'C' series adapters
503 * with firmware of rev 4.42 and higher, and 'S' series
504 * adapters with firmware of rev 3.35 and higher. The
505 * maximum CCB counts are as follows:
506 *
507 * 192 BT-948/958/958D
508 * 100 BT-946C/956C/956CD/747C/757C/757CD/445C
509 * 50 BT-545C/540CF
510 * 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
511 */
512 if (bt->firmware_ver[0] == '5') {
513 bt->max_ccbs = 192;
514 bt->tag_capable = TRUE;
515 } else if (bt->firmware_ver[0] == '4') {
516 if (bt->model[0] == '5')
517 bt->max_ccbs = 50;
518 else
519 bt->max_ccbs = 100;
520 bt->tag_capable = (strcmp(bt->firmware_ver, "4.22") >= 0);
521 } else {
522 bt->max_ccbs = 30;
523 if (bt->firmware_ver[0] == '3'
524 && (strcmp(bt->firmware_ver, "3.35") >= 0))
525 bt->tag_capable = TRUE;
526 else
527 bt->tag_capable = FALSE;
528 }
529
530 if (bt->tag_capable != FALSE)
531 bt->tags_permitted = ALL_TARGETS;
532
533 /* Determine Sync/Wide/Disc settings */
534 if (bt->firmware_ver[0] >= '4') {
535 auto_scsi_data_t auto_scsi_data;
536 fetch_lram_params_t fetch_lram_params;
537 int error;
538
539 /*
540 * These settings are stored in the
541 * AutoSCSI data in LRAM of 'W' and 'C'
542 * adapters.
543 */
544 fetch_lram_params.offset = AUTO_SCSI_BYTE_OFFSET;
545 fetch_lram_params.response_len = sizeof(auto_scsi_data);
546 error = bt_cmd(bt, BOP_FETCH_LRAM,
547 (u_int8_t*)&fetch_lram_params,
548 sizeof(fetch_lram_params),
549 (u_int8_t*)&auto_scsi_data,
550 sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT);
551
552 if (error != 0) {
553 printf("%s: bt_fetch_adapter_info - Failed "
554 "Get Auto SCSI Info\n", bt_name(bt));
555 return (error);
556 }
557
558 bt->disc_permitted = auto_scsi_data.low_disc_permitted
559 | (auto_scsi_data.high_disc_permitted << 8);
560 bt->sync_permitted = auto_scsi_data.low_sync_permitted
561 | (auto_scsi_data.high_sync_permitted << 8);
562 bt->fast_permitted = auto_scsi_data.low_fast_permitted
563 | (auto_scsi_data.high_fast_permitted << 8);
564 bt->ultra_permitted = auto_scsi_data.low_ultra_permitted
565 | (auto_scsi_data.high_ultra_permitted << 8);
566 bt->wide_permitted = auto_scsi_data.low_wide_permitted
567 | (auto_scsi_data.high_wide_permitted << 8);
568
569 if (bt->ultra_scsi == FALSE)
570 bt->ultra_permitted = 0;
571
572 if (bt->wide_bus == FALSE)
573 bt->wide_permitted = 0;
574 } else {
575 /*
576 * 'S' and 'A' series have this information in the setup
577 * information structure.
578 */
579 setup_data_t setup_info;
580
581 length_param = sizeof(setup_info);
582 error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, &length_param,
583 /*paramlen*/1, (u_int8_t*)&setup_info,
584 sizeof(setup_info), DEFAULT_CMD_TIMEOUT);
585
586 if (error != 0) {
587 printf("%s: bt_fetch_adapter_info - Failed "
588 "Get Setup Info\n", bt_name(bt));
589 return (error);
590 }
591
592 if (setup_info.initiate_sync != 0) {
593 bt->sync_permitted = ALL_TARGETS;
594
595 if (bt->model[0] == '7') {
596 if (esetup_info.sync_neg10MB != 0)
597 bt->fast_permitted = ALL_TARGETS;
598 if (strcmp(bt->model, "757") == 0)
599 bt->wide_permitted = ALL_TARGETS;
600 }
601 }
602 bt->disc_permitted = ALL_TARGETS;
603 }
604
605 /* We need as many mailboxes as we can have ccbs */
606 bt->num_boxes = bt->max_ccbs;
607
608 /* Determine our SCSI ID */
609
610 error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
611 (u_int8_t*)&config_data, sizeof(config_data),
612 DEFAULT_CMD_TIMEOUT);
613 if (error != 0) {
614 printf("%s: bt_fetch_adapter_info - Failed Get Config\n",
615 bt_name(bt));
616 return (error);
617 }
618 bt->scsi_id = config_data.scsi_id;
619
620 return (0);
621}
622
623/*
624 * Start the board, ready for normal operation
625 */
626int
627bt_init(struct bt_softc* bt)
628{
629 /* Announce the Adapter */
630 printf("%s: BT-%s FW Rev. %s ", bt_name(bt),
631 bt->model, bt->firmware_ver);
632
633 if (bt->ultra_scsi != 0)
634 printf("Ultra ");
635
636 if (bt->wide_bus != 0)
637 printf("Wide ");
638 else
639 printf("Narrow ");
640
641 if (bt->diff_bus != 0)
642 printf("Diff ");
643
644 printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", bt->scsi_id,
645 bt->max_ccbs);
646
647 /*
648 * Create our DMA tags. These tags define the kinds of device
649 * accessable memory allocations and memory mappings we will
650 * need to perform during normal operation.
651 *
652 * Unless we need to further restrict the allocation, we rely
653 * on the restrictions of the parent dmat, hence the common
654 * use of MAXADDR and MAXSIZE.
655 */
656
657 /* DMA tag for mapping buffers into device visible space. */
658 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,
659 /*lowaddr*/BUS_SPACE_MAXADDR,
660 /*highaddr*/BUS_SPACE_MAXADDR,
661 /*filter*/NULL, /*filterarg*/NULL,
662 /*maxsize*/MAXBSIZE, /*nsegments*/BT_NSEG,
663 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
664 /*flags*/BUS_DMA_ALLOCNOW,
665 &bt->buffer_dmat) != 0) {
666 goto error_exit;
667 }
668
669 bt->init_level++;
670 /* DMA tag for our mailboxes */
671 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,
672 /*lowaddr*/BUS_SPACE_MAXADDR,
673 /*highaddr*/BUS_SPACE_MAXADDR,
674 /*filter*/NULL, /*filterarg*/NULL,
675 bt->num_boxes * (sizeof(bt_mbox_in_t)
676 + sizeof(bt_mbox_out_t)),
677 /*nsegments*/1,
678 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
679 /*flags*/0, &bt->mailbox_dmat) != 0) {
680 goto error_exit;
681 }
682
683 bt->init_level++;
684
685 /* Allocation for our mailboxes */
686 if (bus_dmamem_alloc(bt->mailbox_dmat, (void **)&bt->out_boxes,
687 BUS_DMA_NOWAIT, &bt->mailbox_dmamap) != 0) {
688 goto error_exit;
689 }
690
691 bt->init_level++;
692
693 /* And permanently map them */
694 bus_dmamap_load(bt->mailbox_dmat, bt->mailbox_dmamap,
695 bt->out_boxes,
696 bt->num_boxes * (sizeof(bt_mbox_in_t)
697 + sizeof(bt_mbox_out_t)),
698 btmapmboxes, bt, /*flags*/0);
699
700 bt->init_level++;
701
702 bt->in_boxes = (bt_mbox_in_t *)&bt->out_boxes[bt->num_boxes];
703
704 btinitmboxes(bt);
705
706 /* DMA tag for our ccb structures */
707 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,
708 /*lowaddr*/BUS_SPACE_MAXADDR,
709 /*highaddr*/BUS_SPACE_MAXADDR,
710 /*filter*/NULL, /*filterarg*/NULL,
711 bt->max_ccbs * sizeof(struct bt_ccb),
712 /*nsegments*/1,
713 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
714 /*flags*/0, &bt->ccb_dmat) != 0) {
715 goto error_exit;
716 }
717
718 bt->init_level++;
719
720 /* Allocation for our ccbs */
721 if (bus_dmamem_alloc(bt->ccb_dmat, (void **)&bt->bt_ccb_array,
722 BUS_DMA_NOWAIT, &bt->ccb_dmamap) != 0) {
723 goto error_exit;
724 }
725
726 bt->init_level++;
727
728 /* And permanently map them */
729 bus_dmamap_load(bt->ccb_dmat, bt->ccb_dmamap,
730 bt->bt_ccb_array,
731 bt->max_ccbs * sizeof(struct bt_ccb),
732 btmapccbs, bt, /*flags*/0);
733
734 bt->init_level++;
735
736 /* DMA tag for our S/G structures. We allocate in page sized chunks */
737 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,
738 /*lowaddr*/BUS_SPACE_MAXADDR,
739 /*highaddr*/BUS_SPACE_MAXADDR,
740 /*filter*/NULL, /*filterarg*/NULL,
741 PAGE_SIZE, /*nsegments*/1,
742 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
743 /*flags*/0, &bt->sg_dmat) != 0) {
744 goto error_exit;
745 }
746
747 bt->init_level++;
748
749 /* Perform initial CCB allocation */
750 bzero(bt->bt_ccb_array, bt->max_ccbs * sizeof(struct bt_ccb));
751 btallocccbs(bt);
752
753 if (bt->num_ccbs == 0) {
754 printf("%s: bt_init - Unable to allocate initial ccbs\n",
755 bt_name(bt));
756 goto error_exit;
757 }
758
759 /*
760 * Note that we are going and return (to probe)
761 */
762 return 0;
763
764error_exit:
765
766 return (ENXIO);
767}
768
769int
770bt_attach(struct bt_softc *bt)
771{
772 int tagged_dev_openings;
773 struct cam_devq *devq;
774
775 /*
776 * We reserve 1 ccb for error recovery, so don't
777 * tell the XPT about it.
778 */
779 if (bt->tag_capable != 0)
780 tagged_dev_openings = bt->max_ccbs - 1;
781 else
782 tagged_dev_openings = 0;
783
784 /*
785 * Create the device queue for our SIM.
786 */
787 devq = cam_simq_alloc(bt->max_ccbs - 1);
788 if (devq == NULL)
789 return (ENOMEM);
790
791 /*
792 * Construct our SIM entry
793 */
794 bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, bt->unit,
795 2, tagged_dev_openings, devq);
796 if (bt->sim == NULL) {
797 cam_simq_free(devq);
798 return (ENOMEM);
799 }
800
801 if (xpt_bus_register(bt->sim, 0) != CAM_SUCCESS) {
802 cam_sim_free(bt->sim, /*free_devq*/TRUE);
803 return (ENXIO);
804 }
805
806 if (xpt_create_path(&bt->path, /*periph*/NULL,
807 cam_sim_path(bt->sim), CAM_TARGET_WILDCARD,
808 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
809 xpt_bus_deregister(cam_sim_path(bt->sim));
810 cam_sim_free(bt->sim, /*free_devq*/TRUE);
811 return (ENXIO);
812 }
813
814 return (0);
815}
816
817char *
818bt_name(struct bt_softc *bt)
819{
820 static char name[10];
821
822 sprintf(name, "bt%d", bt->unit);
823 return (name);
824}
825
826int
827bt_check_probed_iop(u_int ioport)
828{
829 u_int i;
830
817 for (i=0; i < BT_NUM_ISAPORTS; i++) {
831 for (i = 0; i < BT_NUM_ISAPORTS; i++) {
818 if (bt_isa_ports[i].addr == ioport) {
819 if (bt_isa_ports[i].probed != 0)
820 return (1);
821 else {
822 return (0);
823 }
824 }
825 }
826 return (1);
827}
828
832 if (bt_isa_ports[i].addr == ioport) {
833 if (bt_isa_ports[i].probed != 0)
834 return (1);
835 else {
836 return (0);
837 }
838 }
839 }
840 return (1);
841}
842
829u_int
830bt_fetch_isa_iop(isa_compat_io_t port)
831{
832 return (bt_isa_ports[port].addr);
833}
834
835void
836bt_mark_probed_bio(isa_compat_io_t port)
837{
838 if (port < BIO_DISABLED)
843void
844bt_mark_probed_bio(isa_compat_io_t port)
845{
846 if (port < BIO_DISABLED)
839 bt_isa_ports[port].probed = 1;
847 bt_mark_probed_iop(bt_board_ports[port]);
840}
841
842void
843bt_mark_probed_iop(u_int ioport)
844{
845 u_int i;
846
847 for (i = 0; i < BT_NUM_ISAPORTS; i++) {
848 if (ioport == bt_isa_ports[i].addr) {
849 bt_isa_ports[i].probed = 1;
850 break;
851 }
852 }
853}
854
848}
849
850void
851bt_mark_probed_iop(u_int ioport)
852{
853 u_int i;
854
855 for (i = 0; i < BT_NUM_ISAPORTS; i++) {
856 if (ioport == bt_isa_ports[i].addr) {
857 bt_isa_ports[i].probed = 1;
858 break;
859 }
860 }
861}
862
863void
864bt_find_probe_range(int ioport, int *port_index, int *max_port_index)
865{
866 if (ioport > 0) {
867 int i;
868
869 for (i = 0;i < BT_NUM_ISAPORTS; i++)
870 if (ioport <= bt_isa_ports[i].addr)
871 break;
872 if ((i >= BT_NUM_ISAPORTS)
873 || (ioport != bt_isa_ports[i].addr)) {
874 printf("
875bt_isa_probe: Invalid baseport of 0x%x specified.
876bt_isa_probe: Nearest valid baseport is 0x%x.
877bt_isa_probe: Failing probe.\n",
878 ioport,
879 (i < BT_NUM_ISAPORTS)
880 ? bt_isa_ports[i].addr
881 : bt_isa_ports[BT_NUM_ISAPORTS - 1].addr);
882 *port_index = *max_port_index = -1;
883 return;
884 }
885 *port_index = *max_port_index = bt_isa_ports[i].bio;
886 } else {
887 *port_index = 0;
888 *max_port_index = BT_NUM_ISAPORTS - 1;
889 }
890}
891
892int
893bt_iop_from_bio(isa_compat_io_t bio_index)
894{
895 if (bio_index >= 0 && bio_index < BT_NUM_ISAPORTS)
896 return (bt_board_ports[bio_index]);
897 return (-1);
898}
899
900
855static void
856btallocccbs(struct bt_softc *bt)
857{
858 struct bt_ccb *next_ccb;
859 struct sg_map_node *sg_map;
860 bus_addr_t physaddr;
861 bt_sg_t *segs;
862 int newcount;
863 int i;
864
865 next_ccb = &bt->bt_ccb_array[bt->num_ccbs];
866
867 sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
868
869 if (sg_map == NULL)
870 return;
871
872 /* Allocate S/G space for the next batch of CCBS */
873 if (bus_dmamem_alloc(bt->sg_dmat, (void **)&sg_map->sg_vaddr,
874 BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
875 free(sg_map, M_DEVBUF);
876 return;
877 }
878
879 SLIST_INSERT_HEAD(&bt->sg_maps, sg_map, links);
880
881 bus_dmamap_load(bt->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr,
882 PAGE_SIZE, btmapsgs, bt, /*flags*/0);
883
884 segs = sg_map->sg_vaddr;
885 physaddr = sg_map->sg_physaddr;
886
887 newcount = (PAGE_SIZE / (BT_NSEG * sizeof(bt_sg_t)));
888 for (i = 0; bt->num_ccbs < bt->max_ccbs && i < newcount; i++) {
889 int error;
890
891 next_ccb->sg_list = segs;
892 next_ccb->sg_list_phys = physaddr;
893 next_ccb->flags = BCCB_FREE;
894 error = bus_dmamap_create(bt->buffer_dmat, /*flags*/0,
895 &next_ccb->dmamap);
896 if (error != 0)
897 break;
898 SLIST_INSERT_HEAD(&bt->free_bt_ccbs, next_ccb, links);
899 segs += BT_NSEG;
900 physaddr += (BT_NSEG * sizeof(bt_sg_t));
901 next_ccb++;
902 bt->num_ccbs++;
903 }
904
905 /* Reserve a CCB for error recovery */
906 if (bt->recovery_bccb == NULL) {
907 bt->recovery_bccb = SLIST_FIRST(&bt->free_bt_ccbs);
908 SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);
909 }
910}
911
912static __inline void
913btfreeccb(struct bt_softc *bt, struct bt_ccb *bccb)
914{
915 int s;
916
917 s = splcam();
918 if ((bccb->flags & BCCB_ACTIVE) != 0)
919 LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le);
920 if (bt->resource_shortage != 0
921 && (bccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
922 bccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
923 bt->resource_shortage = FALSE;
924 }
925 bccb->flags = BCCB_FREE;
926 SLIST_INSERT_HEAD(&bt->free_bt_ccbs, bccb, links);
901static void
902btallocccbs(struct bt_softc *bt)
903{
904 struct bt_ccb *next_ccb;
905 struct sg_map_node *sg_map;
906 bus_addr_t physaddr;
907 bt_sg_t *segs;
908 int newcount;
909 int i;
910
911 next_ccb = &bt->bt_ccb_array[bt->num_ccbs];
912
913 sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
914
915 if (sg_map == NULL)
916 return;
917
918 /* Allocate S/G space for the next batch of CCBS */
919 if (bus_dmamem_alloc(bt->sg_dmat, (void **)&sg_map->sg_vaddr,
920 BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
921 free(sg_map, M_DEVBUF);
922 return;
923 }
924
925 SLIST_INSERT_HEAD(&bt->sg_maps, sg_map, links);
926
927 bus_dmamap_load(bt->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr,
928 PAGE_SIZE, btmapsgs, bt, /*flags*/0);
929
930 segs = sg_map->sg_vaddr;
931 physaddr = sg_map->sg_physaddr;
932
933 newcount = (PAGE_SIZE / (BT_NSEG * sizeof(bt_sg_t)));
934 for (i = 0; bt->num_ccbs < bt->max_ccbs && i < newcount; i++) {
935 int error;
936
937 next_ccb->sg_list = segs;
938 next_ccb->sg_list_phys = physaddr;
939 next_ccb->flags = BCCB_FREE;
940 error = bus_dmamap_create(bt->buffer_dmat, /*flags*/0,
941 &next_ccb->dmamap);
942 if (error != 0)
943 break;
944 SLIST_INSERT_HEAD(&bt->free_bt_ccbs, next_ccb, links);
945 segs += BT_NSEG;
946 physaddr += (BT_NSEG * sizeof(bt_sg_t));
947 next_ccb++;
948 bt->num_ccbs++;
949 }
950
951 /* Reserve a CCB for error recovery */
952 if (bt->recovery_bccb == NULL) {
953 bt->recovery_bccb = SLIST_FIRST(&bt->free_bt_ccbs);
954 SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);
955 }
956}
957
958static __inline void
959btfreeccb(struct bt_softc *bt, struct bt_ccb *bccb)
960{
961 int s;
962
963 s = splcam();
964 if ((bccb->flags & BCCB_ACTIVE) != 0)
965 LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le);
966 if (bt->resource_shortage != 0
967 && (bccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
968 bccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
969 bt->resource_shortage = FALSE;
970 }
971 bccb->flags = BCCB_FREE;
972 SLIST_INSERT_HEAD(&bt->free_bt_ccbs, bccb, links);
973 bt->active_ccbs--;
927 splx(s);
928}
929
930static __inline struct bt_ccb*
931btgetccb(struct bt_softc *bt)
932{
933 struct bt_ccb* bccb;
934 int s;
935
936 s = splcam();
937 if ((bccb = SLIST_FIRST(&bt->free_bt_ccbs)) != NULL) {
938 SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);
974 splx(s);
975}
976
977static __inline struct bt_ccb*
978btgetccb(struct bt_softc *bt)
979{
980 struct bt_ccb* bccb;
981 int s;
982
983 s = splcam();
984 if ((bccb = SLIST_FIRST(&bt->free_bt_ccbs)) != NULL) {
985 SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);
986 bt->active_ccbs++;
939 } else if (bt->num_ccbs < bt->max_ccbs) {
940 btallocccbs(bt);
941 bccb = SLIST_FIRST(&bt->free_bt_ccbs);
942 if (bccb == NULL)
943 printf("%s: Can't malloc BCCB\n", bt_name(bt));
987 } else if (bt->num_ccbs < bt->max_ccbs) {
988 btallocccbs(bt);
989 bccb = SLIST_FIRST(&bt->free_bt_ccbs);
990 if (bccb == NULL)
991 printf("%s: Can't malloc BCCB\n", bt_name(bt));
944 else
992 else {
945 SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);
993 SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);
994 bt->active_ccbs++;
995 }
946 }
947 splx(s);
948
949 return (bccb);
950}
951
952static void
953btaction(struct cam_sim *sim, union ccb *ccb)
954{
955 struct bt_softc *bt;
956
957 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("btaction\n"));
958
959 bt = (struct bt_softc *)cam_sim_softc(sim);
960
961 switch (ccb->ccb_h.func_code) {
962 /* Common cases first */
963 case XPT_SCSI_IO: /* Execute the requested I/O operation */
964 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
965 {
966 struct bt_ccb *bccb;
967 struct bt_hccb *hccb;
968 u_int16_t targ_mask;
969
970 /*
971 * get a bccb to use.
972 */
973 if ((bccb = btgetccb(bt)) == NULL) {
974 int s;
975
976 s = splcam();
977 bt->resource_shortage = TRUE;
978 splx(s);
979 xpt_freeze_simq(bt->sim, /*count*/1);
980 ccb->ccb_h.status = CAM_REQUEUE_REQ;
981 xpt_done(ccb);
982 return;
983 }
984
985 hccb = &bccb->hccb;
986
987 /*
988 * So we can find the BCCB when an abort is requested
989 */
990 bccb->ccb = ccb;
991 ccb->ccb_h.ccb_bccb_ptr = bccb;
992 ccb->ccb_h.ccb_bt_ptr = bt;
993
994 /*
995 * Put all the arguments for the xfer in the bccb
996 */
997 hccb->target_id = ccb->ccb_h.target_id;
998 hccb->target_lun = ccb->ccb_h.target_lun;
999 hccb->btstat = 0;
1000 hccb->sdstat = 0;
1001 targ_mask = (0x01 << hccb->target_id);
1002
1003 if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
1004 struct ccb_scsiio *csio;
1005 struct ccb_hdr *ccbh;
1006
1007 csio = &ccb->csio;
1008 ccbh = &csio->ccb_h;
1009 hccb->opcode = INITIATOR_CCB_WRESID;
1010 hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) != 0;
1011 hccb->dataout = (ccb->ccb_h.flags & CAM_DIR_OUT) != 0;
1012 hccb->cmd_len = csio->cdb_len;
1013 if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) {
1014 ccb->ccb_h.status = CAM_REQ_INVALID;
1015 btfreeccb(bt, bccb);
1016 xpt_done(ccb);
1017 return;
1018 }
1019 hccb->sense_len = csio->sense_len;
1020 if ((ccbh->flags & CAM_TAG_ACTION_VALID) != 0
1021 && ccb->csio.tag_action != CAM_TAG_ACTION_NONE) {
1022 hccb->tag_enable = TRUE;
1023 hccb->tag_type = (ccb->csio.tag_action & 0x3);
1024 } else {
1025 hccb->tag_enable = FALSE;
1026 hccb->tag_type = 0;
1027 }
1028 if ((ccbh->flags & CAM_CDB_POINTER) != 0) {
1029 if ((ccbh->flags & CAM_CDB_PHYS) == 0) {
1030 bcopy(csio->cdb_io.cdb_ptr,
1031 hccb->scsi_cdb, hccb->cmd_len);
1032 } else {
1033 /* I guess I could map it in... */
1034 ccbh->status = CAM_REQ_INVALID;
1035 btfreeccb(bt, bccb);
1036 xpt_done(ccb);
1037 return;
1038 }
1039 } else {
1040 bcopy(csio->cdb_io.cdb_bytes,
1041 hccb->scsi_cdb, hccb->cmd_len);
1042 }
1043 /* If need be, bounce our sense buffer */
1044 if (bt->sense_buffers != NULL) {
1045 hccb->sense_addr = btsensepaddr(bt, bccb);
1046 } else {
1047 hccb->sense_addr = vtophys(&csio->sense_data);
1048 }
1049 /*
1050 * If we have any data to send with this command,
1051 * map it into bus space.
1052 */
1053 /* Only use S/G if there is a transfer */
1054 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1055 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {
1056 /*
1057 * We've been given a pointer
1058 * to a single buffer.
1059 */
1060 if ((ccbh->flags & CAM_DATA_PHYS)==0) {
1061 int s;
1062 int error;
1063
1064 s = splsoftvm();
1065 error = bus_dmamap_load(
1066 bt->buffer_dmat,
1067 bccb->dmamap,
1068 csio->data_ptr,
1069 csio->dxfer_len,
1070 btexecuteccb,
1071 bccb,
1072 /*flags*/0);
1073 if (error == EINPROGRESS) {
1074 /*
1075 * So as to maintain
1076 * ordering, freeze the
1077 * controller queue
1078 * until our mapping is
1079 * returned.
1080 */
1081 xpt_freeze_simq(bt->sim,
1082 1);
1083 csio->ccb_h.status |=
1084 CAM_RELEASE_SIMQ;
1085 }
1086 splx(s);
1087 } else {
1088 struct bus_dma_segment seg;
1089
1090 /* Pointer to physical buffer */
1091 seg.ds_addr =
1092 (bus_addr_t)csio->data_ptr;
1093 seg.ds_len = csio->dxfer_len;
1094 btexecuteccb(bccb, &seg, 1, 0);
1095 }
1096 } else {
1097 struct bus_dma_segment *segs;
1098
1099 if ((ccbh->flags & CAM_DATA_PHYS) != 0)
1100 panic("btaction - Physical "
1101 "segment pointers "
1102 "unsupported");
1103
1104 if ((ccbh->flags&CAM_SG_LIST_PHYS)==0)
1105 panic("btaction - Virtual "
1106 "segment addresses "
1107 "unsupported");
1108
1109 /* Just use the segments provided */
1110 segs = (struct bus_dma_segment *)
1111 csio->data_ptr;
1112 btexecuteccb(bccb, segs,
1113 csio->sglist_cnt, 0);
1114 }
1115 } else {
1116 btexecuteccb(bccb, NULL, 0, 0);
1117 }
1118 } else {
1119 hccb->opcode = INITIATOR_BUS_DEV_RESET;
1120 /* No data transfer */
1121 hccb->datain = TRUE;
1122 hccb->dataout = TRUE;
1123 hccb->cmd_len = 0;
1124 hccb->sense_len = 0;
1125 hccb->tag_enable = FALSE;
1126 hccb->tag_type = 0;
1127 btexecuteccb(bccb, NULL, 0, 0);
1128 }
1129 break;
1130 }
1131 case XPT_EN_LUN: /* Enable LUN as a target */
1132 case XPT_TARGET_IO: /* Execute target I/O request */
1133 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
1134 case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/
1135 case XPT_ABORT: /* Abort the specified CCB */
1136 /* XXX Implement */
1137 ccb->ccb_h.status = CAM_REQ_INVALID;
1138 xpt_done(ccb);
1139 break;
1140 case XPT_SET_TRAN_SETTINGS:
1141 {
1142 /* XXX Implement */
1143 ccb->ccb_h.status = CAM_REQ_CMP;
1144 xpt_done(ccb);
1145 break;
1146 }
1147 case XPT_GET_TRAN_SETTINGS:
1148 /* Get default/user set transfer settings for the target */
1149 {
1150 struct ccb_trans_settings *cts;
1151 u_int target_mask;
1152
1153 cts = &ccb->cts;
1154 target_mask = 0x01 << ccb->ccb_h.target_id;
1155 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
1156 cts->flags = 0;
1157 if ((bt->disc_permitted & target_mask) != 0)
1158 cts->flags |= CCB_TRANS_DISC_ENB;
1159 if ((bt->tags_permitted & target_mask) != 0)
1160 cts->flags |= CCB_TRANS_TAG_ENB;
1161 if ((bt->wide_permitted & target_mask) != 0)
1162 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1163 else
1164 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1165 if ((bt->ultra_permitted & target_mask) != 0)
1166 cts->sync_period = 12;
1167 else if ((bt->fast_permitted & target_mask) != 0)
1168 cts->sync_period = 25;
1169 else if ((bt->sync_permitted & target_mask) != 0)
1170 cts->sync_period = 50;
1171 else
1172 cts->sync_period = 0;
1173
1174 if (cts->sync_period != 0)
1175 cts->sync_offset = 15;
1176
1177 cts->valid = CCB_TRANS_SYNC_RATE_VALID
1178 | CCB_TRANS_SYNC_OFFSET_VALID
1179 | CCB_TRANS_BUS_WIDTH_VALID
1180 | CCB_TRANS_DISC_VALID
1181 | CCB_TRANS_TQ_VALID;
1182 } else {
1183 btfetchtransinfo(bt, cts);
1184 }
1185
1186 ccb->ccb_h.status = CAM_REQ_CMP;
1187 xpt_done(ccb);
1188 break;
1189 }
1190 case XPT_CALC_GEOMETRY:
1191 {
1192 struct ccb_calc_geometry *ccg;
1193 u_int32_t size_mb;
1194 u_int32_t secs_per_cylinder;
1195
1196 ccg = &ccb->ccg;
1197 size_mb = ccg->volume_size
1198 / ((1024L * 1024L) / ccg->block_size);
1199
1200 if (size_mb >= 1024 && (bt->extended_trans != 0)) {
1201 if (size_mb >= 2048) {
1202 ccg->heads = 255;
1203 ccg->secs_per_track = 63;
1204 } else {
1205 ccg->heads = 128;
1206 ccg->secs_per_track = 32;
1207 }
1208 } else {
1209 ccg->heads = 64;
1210 ccg->secs_per_track = 32;
1211 }
1212 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1213 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1214 ccb->ccb_h.status = CAM_REQ_CMP;
1215 xpt_done(ccb);
1216 break;
1217 }
1218 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
1219 {
1220 btreset(bt, /*hardreset*/TRUE);
1221 ccb->ccb_h.status = CAM_REQ_CMP;
1222 xpt_done(ccb);
1223 break;
1224 }
1225 case XPT_TERM_IO: /* Terminate the I/O process */
1226 /* XXX Implement */
1227 ccb->ccb_h.status = CAM_REQ_INVALID;
1228 xpt_done(ccb);
1229 break;
1230 case XPT_PATH_INQ: /* Path routing inquiry */
1231 {
1232 struct ccb_pathinq *cpi = &ccb->cpi;
1233
1234 cpi->version_num = 1; /* XXX??? */
1235 cpi->hba_inquiry = PI_SDTR_ABLE;
1236 if (bt->tag_capable != 0)
1237 cpi->hba_inquiry |= PI_TAG_ABLE;
1238 if (bt->wide_bus != 0)
1239 cpi->hba_inquiry |= PI_WIDE_16;
1240 cpi->target_sprt = 0;
1241 cpi->hba_misc = 0;
1242 cpi->hba_eng_cnt = 0;
1243 cpi->max_target = bt->wide_bus ? 15 : 7;
1244 cpi->max_lun = 7;
1245 cpi->initiator_id = bt->scsi_id;
1246 cpi->bus_id = cam_sim_bus(sim);
1247 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1248 strncpy(cpi->hba_vid, "BusLogic", HBA_IDLEN);
1249 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1250 cpi->unit_number = cam_sim_unit(sim);
1251 cpi->ccb_h.status = CAM_REQ_CMP;
1252 xpt_done(ccb);
1253 break;
1254 }
1255 default:
1256 ccb->ccb_h.status = CAM_REQ_INVALID;
1257 xpt_done(ccb);
1258 break;
1259 }
1260}
1261
1262static void
1263btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
1264{
1265 struct bt_ccb *bccb;
1266 union ccb *ccb;
1267 struct bt_softc *bt;
1268 int s;
1269
1270 bccb = (struct bt_ccb *)arg;
1271 ccb = bccb->ccb;
1272 bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr;
1273
1274 if (error != 0) {
1275 if (error != EFBIG)
1276 printf("%s: Unexepected error 0x%x returned from "
1277 "bus_dmamap_load\n", bt_name(bt), error);
1278 if (ccb->ccb_h.status == CAM_REQ_INPROG) {
1279 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
1280 ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
1281 }
1282 btfreeccb(bt, bccb);
1283 xpt_done(ccb);
1284 return;
1285 }
1286
1287 if (nseg != 0) {
1288 bt_sg_t *sg;
1289 bus_dma_segment_t *end_seg;
1290 bus_dmasync_op_t op;
1291
1292 end_seg = dm_segs + nseg;
1293
1294 /* Copy the segments into our SG list */
1295 sg = bccb->sg_list;
1296 while (dm_segs < end_seg) {
1297 sg->len = dm_segs->ds_len;
1298 sg->addr = dm_segs->ds_addr;
1299 sg++;
1300 dm_segs++;
1301 }
1302
1303 if (nseg > 1) {
1304 bccb->hccb.opcode = INITIATOR_SG_CCB_WRESID;
1305 bccb->hccb.data_len = sizeof(bt_sg_t) * nseg;
1306 bccb->hccb.data_addr = bccb->sg_list_phys;
1307 } else {
1308 bccb->hccb.data_len = bccb->sg_list->len;
1309 bccb->hccb.data_addr = bccb->sg_list->addr;
1310 }
1311
1312 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1313 op = BUS_DMASYNC_PREREAD;
1314 else
1315 op = BUS_DMASYNC_PREWRITE;
1316
1317 bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op);
1318
1319 } else {
1320 bccb->hccb.opcode = INITIATOR_SG_CCB;
1321 bccb->hccb.data_len = 0;
1322 bccb->hccb.data_addr = 0;
1323 }
1324
1325 s = splcam();
1326
1327 /*
1328 * Last time we need to check if this CCB needs to
1329 * be aborted.
1330 */
1331 if (ccb->ccb_h.status != CAM_REQ_INPROG) {
1332 if (nseg != 0)
1333 bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);
1334 btfreeccb(bt, bccb);
1335 xpt_done(ccb);
1336 splx(s);
1337 return;
1338 }
1339
1340 bccb->flags = BCCB_ACTIVE;
1341 ccb->ccb_h.status |= CAM_SIM_QUEUED;
1342 LIST_INSERT_HEAD(&bt->pending_ccbs, &ccb->ccb_h, sim_links.le);
1343
1344 ccb->ccb_h.timeout_ch =
1345 timeout(bttimeout, (caddr_t)bccb,
1346 (ccb->ccb_h.timeout * hz) / 1000);
1347
1348 /* Tell the adapter about this command */
1349 bt->cur_outbox->ccb_addr = btccbvtop(bt, bccb);
996 }
997 splx(s);
998
999 return (bccb);
1000}
1001
1002static void
1003btaction(struct cam_sim *sim, union ccb *ccb)
1004{
1005 struct bt_softc *bt;
1006
1007 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("btaction\n"));
1008
1009 bt = (struct bt_softc *)cam_sim_softc(sim);
1010
1011 switch (ccb->ccb_h.func_code) {
1012 /* Common cases first */
1013 case XPT_SCSI_IO: /* Execute the requested I/O operation */
1014 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
1015 {
1016 struct bt_ccb *bccb;
1017 struct bt_hccb *hccb;
1018 u_int16_t targ_mask;
1019
1020 /*
1021 * get a bccb to use.
1022 */
1023 if ((bccb = btgetccb(bt)) == NULL) {
1024 int s;
1025
1026 s = splcam();
1027 bt->resource_shortage = TRUE;
1028 splx(s);
1029 xpt_freeze_simq(bt->sim, /*count*/1);
1030 ccb->ccb_h.status = CAM_REQUEUE_REQ;
1031 xpt_done(ccb);
1032 return;
1033 }
1034
1035 hccb = &bccb->hccb;
1036
1037 /*
1038 * So we can find the BCCB when an abort is requested
1039 */
1040 bccb->ccb = ccb;
1041 ccb->ccb_h.ccb_bccb_ptr = bccb;
1042 ccb->ccb_h.ccb_bt_ptr = bt;
1043
1044 /*
1045 * Put all the arguments for the xfer in the bccb
1046 */
1047 hccb->target_id = ccb->ccb_h.target_id;
1048 hccb->target_lun = ccb->ccb_h.target_lun;
1049 hccb->btstat = 0;
1050 hccb->sdstat = 0;
1051 targ_mask = (0x01 << hccb->target_id);
1052
1053 if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
1054 struct ccb_scsiio *csio;
1055 struct ccb_hdr *ccbh;
1056
1057 csio = &ccb->csio;
1058 ccbh = &csio->ccb_h;
1059 hccb->opcode = INITIATOR_CCB_WRESID;
1060 hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) != 0;
1061 hccb->dataout = (ccb->ccb_h.flags & CAM_DIR_OUT) != 0;
1062 hccb->cmd_len = csio->cdb_len;
1063 if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) {
1064 ccb->ccb_h.status = CAM_REQ_INVALID;
1065 btfreeccb(bt, bccb);
1066 xpt_done(ccb);
1067 return;
1068 }
1069 hccb->sense_len = csio->sense_len;
1070 if ((ccbh->flags & CAM_TAG_ACTION_VALID) != 0
1071 && ccb->csio.tag_action != CAM_TAG_ACTION_NONE) {
1072 hccb->tag_enable = TRUE;
1073 hccb->tag_type = (ccb->csio.tag_action & 0x3);
1074 } else {
1075 hccb->tag_enable = FALSE;
1076 hccb->tag_type = 0;
1077 }
1078 if ((ccbh->flags & CAM_CDB_POINTER) != 0) {
1079 if ((ccbh->flags & CAM_CDB_PHYS) == 0) {
1080 bcopy(csio->cdb_io.cdb_ptr,
1081 hccb->scsi_cdb, hccb->cmd_len);
1082 } else {
1083 /* I guess I could map it in... */
1084 ccbh->status = CAM_REQ_INVALID;
1085 btfreeccb(bt, bccb);
1086 xpt_done(ccb);
1087 return;
1088 }
1089 } else {
1090 bcopy(csio->cdb_io.cdb_bytes,
1091 hccb->scsi_cdb, hccb->cmd_len);
1092 }
1093 /* If need be, bounce our sense buffer */
1094 if (bt->sense_buffers != NULL) {
1095 hccb->sense_addr = btsensepaddr(bt, bccb);
1096 } else {
1097 hccb->sense_addr = vtophys(&csio->sense_data);
1098 }
1099 /*
1100 * If we have any data to send with this command,
1101 * map it into bus space.
1102 */
1103 /* Only use S/G if there is a transfer */
1104 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1105 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {
1106 /*
1107 * We've been given a pointer
1108 * to a single buffer.
1109 */
1110 if ((ccbh->flags & CAM_DATA_PHYS)==0) {
1111 int s;
1112 int error;
1113
1114 s = splsoftvm();
1115 error = bus_dmamap_load(
1116 bt->buffer_dmat,
1117 bccb->dmamap,
1118 csio->data_ptr,
1119 csio->dxfer_len,
1120 btexecuteccb,
1121 bccb,
1122 /*flags*/0);
1123 if (error == EINPROGRESS) {
1124 /*
1125 * So as to maintain
1126 * ordering, freeze the
1127 * controller queue
1128 * until our mapping is
1129 * returned.
1130 */
1131 xpt_freeze_simq(bt->sim,
1132 1);
1133 csio->ccb_h.status |=
1134 CAM_RELEASE_SIMQ;
1135 }
1136 splx(s);
1137 } else {
1138 struct bus_dma_segment seg;
1139
1140 /* Pointer to physical buffer */
1141 seg.ds_addr =
1142 (bus_addr_t)csio->data_ptr;
1143 seg.ds_len = csio->dxfer_len;
1144 btexecuteccb(bccb, &seg, 1, 0);
1145 }
1146 } else {
1147 struct bus_dma_segment *segs;
1148
1149 if ((ccbh->flags & CAM_DATA_PHYS) != 0)
1150 panic("btaction - Physical "
1151 "segment pointers "
1152 "unsupported");
1153
1154 if ((ccbh->flags&CAM_SG_LIST_PHYS)==0)
1155 panic("btaction - Virtual "
1156 "segment addresses "
1157 "unsupported");
1158
1159 /* Just use the segments provided */
1160 segs = (struct bus_dma_segment *)
1161 csio->data_ptr;
1162 btexecuteccb(bccb, segs,
1163 csio->sglist_cnt, 0);
1164 }
1165 } else {
1166 btexecuteccb(bccb, NULL, 0, 0);
1167 }
1168 } else {
1169 hccb->opcode = INITIATOR_BUS_DEV_RESET;
1170 /* No data transfer */
1171 hccb->datain = TRUE;
1172 hccb->dataout = TRUE;
1173 hccb->cmd_len = 0;
1174 hccb->sense_len = 0;
1175 hccb->tag_enable = FALSE;
1176 hccb->tag_type = 0;
1177 btexecuteccb(bccb, NULL, 0, 0);
1178 }
1179 break;
1180 }
1181 case XPT_EN_LUN: /* Enable LUN as a target */
1182 case XPT_TARGET_IO: /* Execute target I/O request */
1183 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
1184 case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/
1185 case XPT_ABORT: /* Abort the specified CCB */
1186 /* XXX Implement */
1187 ccb->ccb_h.status = CAM_REQ_INVALID;
1188 xpt_done(ccb);
1189 break;
1190 case XPT_SET_TRAN_SETTINGS:
1191 {
1192 /* XXX Implement */
1193 ccb->ccb_h.status = CAM_REQ_CMP;
1194 xpt_done(ccb);
1195 break;
1196 }
1197 case XPT_GET_TRAN_SETTINGS:
1198 /* Get default/user set transfer settings for the target */
1199 {
1200 struct ccb_trans_settings *cts;
1201 u_int target_mask;
1202
1203 cts = &ccb->cts;
1204 target_mask = 0x01 << ccb->ccb_h.target_id;
1205 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
1206 cts->flags = 0;
1207 if ((bt->disc_permitted & target_mask) != 0)
1208 cts->flags |= CCB_TRANS_DISC_ENB;
1209 if ((bt->tags_permitted & target_mask) != 0)
1210 cts->flags |= CCB_TRANS_TAG_ENB;
1211 if ((bt->wide_permitted & target_mask) != 0)
1212 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1213 else
1214 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1215 if ((bt->ultra_permitted & target_mask) != 0)
1216 cts->sync_period = 12;
1217 else if ((bt->fast_permitted & target_mask) != 0)
1218 cts->sync_period = 25;
1219 else if ((bt->sync_permitted & target_mask) != 0)
1220 cts->sync_period = 50;
1221 else
1222 cts->sync_period = 0;
1223
1224 if (cts->sync_period != 0)
1225 cts->sync_offset = 15;
1226
1227 cts->valid = CCB_TRANS_SYNC_RATE_VALID
1228 | CCB_TRANS_SYNC_OFFSET_VALID
1229 | CCB_TRANS_BUS_WIDTH_VALID
1230 | CCB_TRANS_DISC_VALID
1231 | CCB_TRANS_TQ_VALID;
1232 } else {
1233 btfetchtransinfo(bt, cts);
1234 }
1235
1236 ccb->ccb_h.status = CAM_REQ_CMP;
1237 xpt_done(ccb);
1238 break;
1239 }
1240 case XPT_CALC_GEOMETRY:
1241 {
1242 struct ccb_calc_geometry *ccg;
1243 u_int32_t size_mb;
1244 u_int32_t secs_per_cylinder;
1245
1246 ccg = &ccb->ccg;
1247 size_mb = ccg->volume_size
1248 / ((1024L * 1024L) / ccg->block_size);
1249
1250 if (size_mb >= 1024 && (bt->extended_trans != 0)) {
1251 if (size_mb >= 2048) {
1252 ccg->heads = 255;
1253 ccg->secs_per_track = 63;
1254 } else {
1255 ccg->heads = 128;
1256 ccg->secs_per_track = 32;
1257 }
1258 } else {
1259 ccg->heads = 64;
1260 ccg->secs_per_track = 32;
1261 }
1262 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1263 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1264 ccb->ccb_h.status = CAM_REQ_CMP;
1265 xpt_done(ccb);
1266 break;
1267 }
1268 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
1269 {
1270 btreset(bt, /*hardreset*/TRUE);
1271 ccb->ccb_h.status = CAM_REQ_CMP;
1272 xpt_done(ccb);
1273 break;
1274 }
1275 case XPT_TERM_IO: /* Terminate the I/O process */
1276 /* XXX Implement */
1277 ccb->ccb_h.status = CAM_REQ_INVALID;
1278 xpt_done(ccb);
1279 break;
1280 case XPT_PATH_INQ: /* Path routing inquiry */
1281 {
1282 struct ccb_pathinq *cpi = &ccb->cpi;
1283
1284 cpi->version_num = 1; /* XXX??? */
1285 cpi->hba_inquiry = PI_SDTR_ABLE;
1286 if (bt->tag_capable != 0)
1287 cpi->hba_inquiry |= PI_TAG_ABLE;
1288 if (bt->wide_bus != 0)
1289 cpi->hba_inquiry |= PI_WIDE_16;
1290 cpi->target_sprt = 0;
1291 cpi->hba_misc = 0;
1292 cpi->hba_eng_cnt = 0;
1293 cpi->max_target = bt->wide_bus ? 15 : 7;
1294 cpi->max_lun = 7;
1295 cpi->initiator_id = bt->scsi_id;
1296 cpi->bus_id = cam_sim_bus(sim);
1297 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1298 strncpy(cpi->hba_vid, "BusLogic", HBA_IDLEN);
1299 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1300 cpi->unit_number = cam_sim_unit(sim);
1301 cpi->ccb_h.status = CAM_REQ_CMP;
1302 xpt_done(ccb);
1303 break;
1304 }
1305 default:
1306 ccb->ccb_h.status = CAM_REQ_INVALID;
1307 xpt_done(ccb);
1308 break;
1309 }
1310}
1311
1312static void
1313btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
1314{
1315 struct bt_ccb *bccb;
1316 union ccb *ccb;
1317 struct bt_softc *bt;
1318 int s;
1319
1320 bccb = (struct bt_ccb *)arg;
1321 ccb = bccb->ccb;
1322 bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr;
1323
1324 if (error != 0) {
1325 if (error != EFBIG)
1326 printf("%s: Unexepected error 0x%x returned from "
1327 "bus_dmamap_load\n", bt_name(bt), error);
1328 if (ccb->ccb_h.status == CAM_REQ_INPROG) {
1329 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
1330 ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
1331 }
1332 btfreeccb(bt, bccb);
1333 xpt_done(ccb);
1334 return;
1335 }
1336
1337 if (nseg != 0) {
1338 bt_sg_t *sg;
1339 bus_dma_segment_t *end_seg;
1340 bus_dmasync_op_t op;
1341
1342 end_seg = dm_segs + nseg;
1343
1344 /* Copy the segments into our SG list */
1345 sg = bccb->sg_list;
1346 while (dm_segs < end_seg) {
1347 sg->len = dm_segs->ds_len;
1348 sg->addr = dm_segs->ds_addr;
1349 sg++;
1350 dm_segs++;
1351 }
1352
1353 if (nseg > 1) {
1354 bccb->hccb.opcode = INITIATOR_SG_CCB_WRESID;
1355 bccb->hccb.data_len = sizeof(bt_sg_t) * nseg;
1356 bccb->hccb.data_addr = bccb->sg_list_phys;
1357 } else {
1358 bccb->hccb.data_len = bccb->sg_list->len;
1359 bccb->hccb.data_addr = bccb->sg_list->addr;
1360 }
1361
1362 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1363 op = BUS_DMASYNC_PREREAD;
1364 else
1365 op = BUS_DMASYNC_PREWRITE;
1366
1367 bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op);
1368
1369 } else {
1370 bccb->hccb.opcode = INITIATOR_SG_CCB;
1371 bccb->hccb.data_len = 0;
1372 bccb->hccb.data_addr = 0;
1373 }
1374
1375 s = splcam();
1376
1377 /*
1378 * Last time we need to check if this CCB needs to
1379 * be aborted.
1380 */
1381 if (ccb->ccb_h.status != CAM_REQ_INPROG) {
1382 if (nseg != 0)
1383 bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);
1384 btfreeccb(bt, bccb);
1385 xpt_done(ccb);
1386 splx(s);
1387 return;
1388 }
1389
1390 bccb->flags = BCCB_ACTIVE;
1391 ccb->ccb_h.status |= CAM_SIM_QUEUED;
1392 LIST_INSERT_HEAD(&bt->pending_ccbs, &ccb->ccb_h, sim_links.le);
1393
1394 ccb->ccb_h.timeout_ch =
1395 timeout(bttimeout, (caddr_t)bccb,
1396 (ccb->ccb_h.timeout * hz) / 1000);
1397
1398 /* Tell the adapter about this command */
1399 bt->cur_outbox->ccb_addr = btccbvtop(bt, bccb);
1350 if (bt->cur_outbox->action_code != BMBO_FREE)
1351 panic("%s: Too few mailboxes or to many ccbs???", bt_name(bt));
1400 if (bt->cur_outbox->action_code != BMBO_FREE) {
1401 /*
1402 * We should never encounter a busy mailbox.
1403 * If we do, warn the user, and treat it as
1404 * a resource shortage. If the controller is
1405 * hung, one of the pending transactions will
1406 * timeout causing us to start recovery operations.
1407 */
1408 printf("%s: Encountered busy mailbox with %d out of %d "
1409 "commands active!!!", bt_name(bt), bt->active_ccbs,
1410 bt->max_ccbs);
1411 untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch);
1412 if (nseg != 0)
1413 bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);
1414 btfreeccb(bt, bccb);
1415 bt->resource_shortage = TRUE;
1416 xpt_freeze_simq(bt->sim, /*count*/1);
1417 ccb->ccb_h.status = CAM_REQUEUE_REQ;
1418 xpt_done(ccb);
1419 return;
1420 }
1352 bt->cur_outbox->action_code = BMBO_START;
1353 bt_outb(bt, COMMAND_REG, BOP_START_MBOX);
1354 btnextoutbox(bt);
1355 splx(s);
1356}
1357
1358void
1359bt_intr(void *arg)
1360{
1361 struct bt_softc *bt;
1362 u_int intstat;
1363
1364 bt = (struct bt_softc *)arg;
1365 while (((intstat = bt_inb(bt, INTSTAT_REG)) & INTR_PENDING) != 0) {
1366
1367 if ((intstat & CMD_COMPLETE) != 0) {
1368 bt->latched_status = bt_inb(bt, STATUS_REG);
1369 bt->command_cmp = TRUE;
1370 }
1371
1372 bt_outb(bt, CONTROL_REG, RESET_INTR);
1373
1374 if ((intstat & IMB_LOADED) != 0) {
1375 while (bt->cur_inbox->comp_code != BMBI_FREE) {
1376 btdone(bt,
1377 btccbptov(bt, bt->cur_inbox->ccb_addr),
1378 bt->cur_inbox->comp_code);
1379 bt->cur_inbox->comp_code = BMBI_FREE;
1380 btnextinbox(bt);
1381 }
1382 }
1383
1384 if ((intstat & SCSI_BUS_RESET) != 0) {
1385 btreset(bt, /*hardreset*/FALSE);
1386 }
1387 }
1388}
1389
1390static void
1391btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code)
1392{
1393 union ccb *ccb;
1394 struct ccb_scsiio *csio;
1395
1396 ccb = bccb->ccb;
1397 csio = &bccb->ccb->csio;
1398
1399 if ((bccb->flags & BCCB_ACTIVE) == 0) {
1400 printf("%s: btdone - Attempt to free non-active BCCB %p\n",
1401 bt_name(bt), (void *)bccb);
1402 return;
1403 }
1404
1405 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1406 bus_dmasync_op_t op;
1407
1408 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1409 op = BUS_DMASYNC_POSTREAD;
1410 else
1411 op = BUS_DMASYNC_POSTWRITE;
1412 bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op);
1413 bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);
1414 }
1415
1416 if (bccb == bt->recovery_bccb) {
1417 /*
1418 * The recovery BCCB does not have a CCB associated
1419 * with it, so short circuit the normal error handling.
1420 * We now traverse our list of pending CCBs and process
1421 * any that were terminated by the recovery CCBs action.
1422 * We also reinstate timeouts for all remaining, pending,
1423 * CCBs.
1424 */
1425 struct cam_path *path;
1426 struct ccb_hdr *ccb_h;
1427 cam_status error;
1428
1429 /* Notify all clients that a BDR occured */
1430 error = xpt_create_path(&path, /*periph*/NULL,
1431 cam_sim_path(bt->sim),
1432 bccb->hccb.target_id,
1433 CAM_LUN_WILDCARD);
1434
1435 if (error == CAM_REQ_CMP)
1436 xpt_async(AC_SENT_BDR, path, NULL);
1437
1438 ccb_h = LIST_FIRST(&bt->pending_ccbs);
1439 while (ccb_h != NULL) {
1440 struct bt_ccb *pending_bccb;
1441
1442 pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr;
1443 if (pending_bccb->hccb.target_id
1444 == bccb->hccb.target_id) {
1445 pending_bccb->hccb.btstat = BTSTAT_HA_BDR;
1446 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1447 btdone(bt, pending_bccb, BMBI_ERROR);
1448 } else {
1449 ccb_h->timeout_ch =
1450 timeout(bttimeout, (caddr_t)pending_bccb,
1451 (ccb_h->timeout * hz) / 1000);
1452 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1453 }
1454 }
1455 printf("%s: No longer in timeout\n", bt_name(bt));
1456 return;
1457 }
1458
1459 untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch);
1460
1461 switch (comp_code) {
1462 case BMBI_FREE:
1463 printf("%s: btdone - CCB completed with free status!\n",
1464 bt_name(bt));
1465 break;
1466 case BMBI_NOT_FOUND:
1467 printf("%s: btdone - CCB Abort failed to find CCB\n",
1468 bt_name(bt));
1469 break;
1470 case BMBI_ABORT:
1471 case BMBI_ERROR:
1421 bt->cur_outbox->action_code = BMBO_START;
1422 bt_outb(bt, COMMAND_REG, BOP_START_MBOX);
1423 btnextoutbox(bt);
1424 splx(s);
1425}
1426
1427void
1428bt_intr(void *arg)
1429{
1430 struct bt_softc *bt;
1431 u_int intstat;
1432
1433 bt = (struct bt_softc *)arg;
1434 while (((intstat = bt_inb(bt, INTSTAT_REG)) & INTR_PENDING) != 0) {
1435
1436 if ((intstat & CMD_COMPLETE) != 0) {
1437 bt->latched_status = bt_inb(bt, STATUS_REG);
1438 bt->command_cmp = TRUE;
1439 }
1440
1441 bt_outb(bt, CONTROL_REG, RESET_INTR);
1442
1443 if ((intstat & IMB_LOADED) != 0) {
1444 while (bt->cur_inbox->comp_code != BMBI_FREE) {
1445 btdone(bt,
1446 btccbptov(bt, bt->cur_inbox->ccb_addr),
1447 bt->cur_inbox->comp_code);
1448 bt->cur_inbox->comp_code = BMBI_FREE;
1449 btnextinbox(bt);
1450 }
1451 }
1452
1453 if ((intstat & SCSI_BUS_RESET) != 0) {
1454 btreset(bt, /*hardreset*/FALSE);
1455 }
1456 }
1457}
1458
1459static void
1460btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code)
1461{
1462 union ccb *ccb;
1463 struct ccb_scsiio *csio;
1464
1465 ccb = bccb->ccb;
1466 csio = &bccb->ccb->csio;
1467
1468 if ((bccb->flags & BCCB_ACTIVE) == 0) {
1469 printf("%s: btdone - Attempt to free non-active BCCB %p\n",
1470 bt_name(bt), (void *)bccb);
1471 return;
1472 }
1473
1474 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1475 bus_dmasync_op_t op;
1476
1477 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1478 op = BUS_DMASYNC_POSTREAD;
1479 else
1480 op = BUS_DMASYNC_POSTWRITE;
1481 bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op);
1482 bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);
1483 }
1484
1485 if (bccb == bt->recovery_bccb) {
1486 /*
1487 * The recovery BCCB does not have a CCB associated
1488 * with it, so short circuit the normal error handling.
1489 * We now traverse our list of pending CCBs and process
1490 * any that were terminated by the recovery CCBs action.
1491 * We also reinstate timeouts for all remaining, pending,
1492 * CCBs.
1493 */
1494 struct cam_path *path;
1495 struct ccb_hdr *ccb_h;
1496 cam_status error;
1497
1498 /* Notify all clients that a BDR occured */
1499 error = xpt_create_path(&path, /*periph*/NULL,
1500 cam_sim_path(bt->sim),
1501 bccb->hccb.target_id,
1502 CAM_LUN_WILDCARD);
1503
1504 if (error == CAM_REQ_CMP)
1505 xpt_async(AC_SENT_BDR, path, NULL);
1506
1507 ccb_h = LIST_FIRST(&bt->pending_ccbs);
1508 while (ccb_h != NULL) {
1509 struct bt_ccb *pending_bccb;
1510
1511 pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr;
1512 if (pending_bccb->hccb.target_id
1513 == bccb->hccb.target_id) {
1514 pending_bccb->hccb.btstat = BTSTAT_HA_BDR;
1515 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1516 btdone(bt, pending_bccb, BMBI_ERROR);
1517 } else {
1518 ccb_h->timeout_ch =
1519 timeout(bttimeout, (caddr_t)pending_bccb,
1520 (ccb_h->timeout * hz) / 1000);
1521 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
1522 }
1523 }
1524 printf("%s: No longer in timeout\n", bt_name(bt));
1525 return;
1526 }
1527
1528 untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch);
1529
1530 switch (comp_code) {
1531 case BMBI_FREE:
1532 printf("%s: btdone - CCB completed with free status!\n",
1533 bt_name(bt));
1534 break;
1535 case BMBI_NOT_FOUND:
1536 printf("%s: btdone - CCB Abort failed to find CCB\n",
1537 bt_name(bt));
1538 break;
1539 case BMBI_ABORT:
1540 case BMBI_ERROR:
1472#if 0
1473 printf("bt: ccb %x - error %x occured. btstat = %x, sdstat = %x\n",
1474 bccb, comp_code, bccb->hccb.btstat, bccb->hccb.sdstat);
1475#endif
1541 printf("bt: ccb %p - error %x occured. "
1542 "btstat = %x, sdstat = %x\n",
1543 (void *)bccb, comp_code, bccb->hccb.btstat,
1544 bccb->hccb.sdstat);
1476 /* An error occured */
1477 switch(bccb->hccb.btstat) {
1478 case BTSTAT_DATARUN_ERROR:
1545 /* An error occured */
1546 switch(bccb->hccb.btstat) {
1547 case BTSTAT_DATARUN_ERROR:
1479 if (bccb->hccb.data_len <= 0) {
1548 if (bccb->hccb.data_len == 0) {
1549 /*
1550 * At least firmware 4.22, does this
1551 * for a QUEUE FULL condition.
1552 */
1553 bccb->hccb.sdstat = SCSI_STATUS_QUEUE_FULL;
1554 } else if (bccb->hccb.data_len < 0) {
1480 csio->ccb_h.status = CAM_DATA_RUN_ERR;
1481 break;
1482 }
1483 /* FALLTHROUGH */
1484 case BTSTAT_NOERROR:
1485 case BTSTAT_LINKED_CMD_COMPLETE:
1486 case BTSTAT_LINKED_CMD_FLAG_COMPLETE:
1487 case BTSTAT_DATAUNDERUN_ERROR:
1488
1489 csio->scsi_status = bccb->hccb.sdstat;
1490 csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
1491 switch(csio->scsi_status) {
1492 case SCSI_STATUS_CHECK_COND:
1493 case SCSI_STATUS_CMD_TERMINATED:
1494 csio->ccb_h.status |= CAM_AUTOSNS_VALID;
1495 /* Bounce sense back if necessary */
1496 if (bt->sense_buffers != NULL) {
1497 csio->sense_data =
1498 *btsensevaddr(bt, bccb);
1499 }
1500 break;
1501 default:
1502 break;
1503 case SCSI_STATUS_OK:
1504 csio->ccb_h.status = CAM_REQ_CMP;
1505 break;
1506 }
1507 csio->resid = bccb->hccb.data_len;
1508 break;
1509 case BTSTAT_SELTIMEOUT:
1510 csio->ccb_h.status = CAM_SEL_TIMEOUT;
1511 break;
1512 case BTSTAT_UNEXPECTED_BUSFREE:
1513 csio->ccb_h.status = CAM_UNEXP_BUSFREE;
1514 break;
1515 case BTSTAT_INVALID_PHASE:
1516 csio->ccb_h.status = CAM_SEQUENCE_FAIL;
1517 break;
1518 case BTSTAT_INVALID_ACTION_CODE:
1519 panic("%s: Inavlid Action code", bt_name(bt));
1520 break;
1521 case BTSTAT_INVALID_OPCODE:
1522 panic("%s: Inavlid CCB Opcode code", bt_name(bt));
1523 break;
1524 case BTSTAT_LINKED_CCB_LUN_MISMATCH:
1525 /* We don't even support linked commands... */
1526 panic("%s: Linked CCB Lun Mismatch", bt_name(bt));
1527 break;
1528 case BTSTAT_INVALID_CCB_OR_SG_PARAM:
1529 panic("%s: Invalid CCB or SG list", bt_name(bt));
1530 break;
1531 case BTSTAT_AUTOSENSE_FAILED:
1532 csio->ccb_h.status = CAM_AUTOSENSE_FAIL;
1533 break;
1534 case BTSTAT_TAGGED_MSG_REJECTED:
1535 {
1536 struct ccb_trans_settings neg;
1537
1538 xpt_print_path(csio->ccb_h.path);
1539 printf("refuses tagged commands. Performing "
1540 "non-tagged I/O\n");
1541 neg.flags = 0;
1542 neg.valid = CCB_TRANS_TQ_VALID;
1543 xpt_setup_ccb(&neg.ccb_h, csio->ccb_h.path,
1544 /*priority*/1);
1545 xpt_async(AC_TRANSFER_NEG, csio->ccb_h.path, &neg);
1546 bt->tags_permitted &= ~(0x01 << csio->ccb_h.target_id);
1547 csio->ccb_h.status = CAM_MSG_REJECT_REC;
1548 break;
1549 }
1550 case BTSTAT_UNSUPPORTED_MSG_RECEIVED:
1551 /*
1552 * XXX You would think that this is
1553 * a recoverable error... Hmmm.
1554 */
1555 csio->ccb_h.status = CAM_REQ_CMP_ERR;
1556 break;
1557 case BTSTAT_HA_SOFTWARE_ERROR:
1558 case BTSTAT_HA_WATCHDOG_ERROR:
1559 case BTSTAT_HARDWARE_FAILURE:
1560 /* Hardware reset ??? Can we recover ??? */
1561 csio->ccb_h.status = CAM_NO_HBA;
1562 break;
1563 case BTSTAT_TARGET_IGNORED_ATN:
1564 case BTSTAT_OTHER_SCSI_BUS_RESET:
1565 case BTSTAT_HA_SCSI_BUS_RESET:
1566 if ((csio->ccb_h.status & CAM_STATUS_MASK)
1567 != CAM_CMD_TIMEOUT)
1568 csio->ccb_h.status = CAM_SCSI_BUS_RESET;
1569 break;
1570 case BTSTAT_HA_BDR:
1571 if ((bccb->flags & BCCB_DEVICE_RESET) == 0)
1572 csio->ccb_h.status = CAM_BDR_SENT;
1573 else
1574 csio->ccb_h.status = CAM_CMD_TIMEOUT;
1575 break;
1576 case BTSTAT_INVALID_RECONNECT:
1577 case BTSTAT_ABORT_QUEUE_GENERATED:
1578 csio->ccb_h.status = CAM_REQ_TERMIO;
1579 break;
1580 case BTSTAT_SCSI_PERROR_DETECTED:
1581 csio->ccb_h.status = CAM_UNCOR_PARITY;
1582 break;
1583 }
1584 if (csio->ccb_h.status != CAM_REQ_CMP) {
1585 xpt_freeze_devq(csio->ccb_h.path, /*count*/1);
1586 csio->ccb_h.status |= CAM_DEV_QFRZN;
1587 }
1588 if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0)
1589 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1590 btfreeccb(bt, bccb);
1591 xpt_done(ccb);
1592 break;
1593 case BMBI_OK:
1594 /* All completed without incident */
1595 ccb->ccb_h.status |= CAM_REQ_CMP;
1596 if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0)
1597 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1598 btfreeccb(bt, bccb);
1599 xpt_done(ccb);
1600 break;
1601 }
1602}
1603
1604static int
1605btreset(struct bt_softc* bt, int hard_reset)
1606{
1607 struct ccb_hdr *ccb_h;
1608 u_int status;
1609 u_int timeout;
1610 u_int8_t reset_type;
1611
1612 if (hard_reset != 0)
1613 reset_type = HARD_RESET;
1614 else
1615 reset_type = SOFT_RESET;
1616 bt_outb(bt, CONTROL_REG, reset_type);
1617
1618 /* Wait 5sec. for Diagnostic start */
1619 timeout = 5 * 10000;
1620 while (--timeout) {
1621 status = bt_inb(bt, STATUS_REG);
1622 if ((status & DIAG_ACTIVE) != 0)
1623 break;
1624 DELAY(100);
1625 }
1626 if (timeout == 0) {
1627 if (bootverbose)
1628 printf("%s: btreset - Diagnostic Active failed to "
1629 "assert. status = 0x%x\n", bt_name(bt), status);
1630 return (ETIMEDOUT);
1631 }
1632
1633 /* Wait 10sec. for Diagnostic end */
1634 timeout = 10 * 10000;
1635 while (--timeout) {
1636 status = bt_inb(bt, STATUS_REG);
1637 if ((status & DIAG_ACTIVE) == 0)
1638 break;
1639 DELAY(100);
1640 }
1641 if (timeout == 0) {
1642 panic("%s: btreset - Diagnostic Active failed to drop. "
1643 "status = 0x%x\n", bt_name(bt), status);
1644 return (ETIMEDOUT);
1645 }
1646
1647 /* Wait for the host adapter to become ready or report a failure */
1648 timeout = 10000;
1649 while (--timeout) {
1650 status = bt_inb(bt, STATUS_REG);
1651 if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0)
1652 break;
1653 DELAY(100);
1654 }
1655 if (timeout == 0) {
1656 printf("%s: btreset - Host adapter failed to come ready. "
1657 "status = 0x%x\n", bt_name(bt), status);
1658 return (ETIMEDOUT);
1659 }
1660
1661 /* If the diagnostics failed, tell the user */
1662 if ((status & DIAG_FAIL) != 0
1663 || (status & HA_READY) == 0) {
1664 printf("%s: btreset - Adapter failed diagnostics\n",
1665 bt_name(bt));
1666
1667 if ((status & DATAIN_REG_READY) != 0)
1668 printf("%s: btreset - Host Adapter Error code = 0x%x\n",
1669 bt_name(bt), bt_inb(bt, DATAIN_REG));
1670 return (ENXIO);
1671 }
1672
1673 /* If we've allocated mailboxes, initialize them */
1674 if (bt->init_level > 4)
1675 btinitmboxes(bt);
1676
1677 /* If we've attached to the XPT, tell it about the event */
1678 if (bt->path != NULL)
1679 xpt_async(AC_BUS_RESET, bt->path, NULL);
1680
1681 /*
1682 * Perform completion processing for all outstanding CCBs.
1683 */
1684 while ((ccb_h = LIST_FIRST(&bt->pending_ccbs)) != NULL) {
1685 struct bt_ccb *pending_bccb;
1686
1687 pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr;
1688 pending_bccb->hccb.btstat = BTSTAT_HA_SCSI_BUS_RESET;
1689 btdone(bt, pending_bccb, BMBI_ERROR);
1690 }
1691
1692 return (0);
1693}
1694
1695/*
1696 * Send a command to the adapter.
1697 */
1698int
1699bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len,
1700 u_int8_t *reply_data, u_int reply_len, u_int cmd_timeout)
1701{
1702 u_int timeout;
1703 u_int status;
1704 u_int intstat;
1705 u_int reply_buf_size;
1706 int s;
1707
1708 /* No data returned to start */
1709 reply_buf_size = reply_len;
1710 reply_len = 0;
1711 intstat = 0;
1712
1713 bt->command_cmp = 0;
1714 /*
1715 * Wait up to 1 sec. for the adapter to become
1716 * ready to accept commands.
1717 */
1718 timeout = 10000;
1719 while (--timeout) {
1720
1721 status = bt_inb(bt, STATUS_REG);
1722 if ((status & HA_READY) != 0
1723 && (status & CMD_REG_BUSY) == 0)
1724 break;
1725 DELAY(100);
1726 }
1727 if (timeout == 0) {
1728 printf("%s: bt_cmd: Timeout waiting for adapter ready, "
1729 "status = 0x%x\n", bt_name(bt), status);
1730 return (ETIMEDOUT);
1731 }
1732
1733 /*
1734 * Send the opcode followed by any necessary parameter bytes.
1735 */
1736 bt_outb(bt, COMMAND_REG, opcode);
1737
1738 /*
1739 * Wait for up to 1sec to get the parameter list sent
1740 */
1741 timeout = 10000;
1742 while (param_len && --timeout) {
1743 DELAY(100);
1744 status = bt_inb(bt, STATUS_REG);
1745 intstat = bt_inb(bt, INTSTAT_REG);
1746 if ((intstat & (INTR_PENDING|CMD_COMPLETE))
1747 == (INTR_PENDING|CMD_COMPLETE))
1748 break;
1749 if (bt->command_cmp != 0) {
1750 status = bt->latched_status;
1751 break;
1752 }
1753 if ((status & DATAIN_REG_READY) != 0)
1754 break;
1755 if ((status & CMD_REG_BUSY) == 0) {
1756 bt_outb(bt, COMMAND_REG, *params++);
1757 param_len--;
1758 }
1759 }
1760 if (timeout == 0) {
1761 printf("%s: bt_cmd: Timeout sending parameters, "
1762 "status = 0x%x\n", bt_name(bt), status);
1763 return (ETIMEDOUT);
1764 }
1765
1766 /*
1767 * The BOP_MODIFY_IO_ADDR does not issue a CMD_COMPLETE, but
1768 * it should update the status register. So, we wait for
1769 * the CMD_REG_BUSY status to clear and check for a command
1770 * failure.
1771 */
1772 if (opcode == BOP_MODIFY_IO_ADDR) {
1773
1774 while (--cmd_timeout) {
1775 status = bt_inb(bt, STATUS_REG);
1776 if ((status & CMD_REG_BUSY) == 0) {
1777 if ((status & CMD_INVALID) != 0) {
1778 printf("%s: bt_cmd - Modify I/O Address"
1779 " invalid\n", bt_name(bt));
1780 return (EINVAL);
1781 }
1782 return (0);
1783 }
1784 DELAY(100);
1785 }
1786 if (timeout == 0) {
1787 printf("%s: bt_cmd: Timeout on Modify I/O Address CMD, "
1788 "status = 0x%x\n", bt_name(bt), status);
1789 return (ETIMEDOUT);
1790 }
1791 }
1792
1793 /*
1794 * For all other commands, we wait for any output data
1795 * and the final comand completion interrupt.
1796 */
1797 while (--cmd_timeout) {
1798
1799 status = bt_inb(bt, STATUS_REG);
1800 intstat = bt_inb(bt, INTSTAT_REG);
1801 if ((intstat & (INTR_PENDING|CMD_COMPLETE))
1802 == (INTR_PENDING|CMD_COMPLETE))
1803 break;
1804
1805 if (bt->command_cmp != 0) {
1806 status = bt->latched_status;
1807 break;
1808 }
1809
1810 if ((status & DATAIN_REG_READY) != 0) {
1811 u_int8_t data;
1812
1813 data = bt_inb(bt, DATAIN_REG);
1814 if (reply_len < reply_buf_size) {
1815 *reply_data++ = data;
1816 } else {
1817 printf("%s: bt_cmd - Discarded reply data byte "
1818 "for opcode 0x%x\n", bt_name(bt),
1819 opcode);
1820 }
1821 reply_len++;
1822 }
1823
1824 if ((opcode == BOP_FETCH_LRAM)
1825 && (status & HA_READY) != 0)
1826 break;
1827 DELAY(100);
1828 }
1829 if (timeout == 0) {
1830 printf("%s: bt_cmd: Timeout waiting for reply data and "
1831 "command complete.\n%s: status = 0x%x, intstat = 0x%x, "
1832 "reply_len = %d\n", bt_name(bt), bt_name(bt), status,
1833 intstat, reply_len);
1834 return (ETIMEDOUT);
1835 }
1836
1837 /*
1838 * Clear any pending interrupts. Block interrupts so our
1839 * interrupt handler is not re-entered.
1840 */
1841 s = splcam();
1842 bt_intr(bt);
1843 splx(s);
1844
1845 /*
1846 * If the command was rejected by the controller, tell the caller.
1847 */
1848 if ((status & CMD_INVALID) != 0) {
1849 /*
1850 * Some early adapters may not recover properly from
1851 * an invalid command. If it appears that the controller
1852 * has wedged (i.e. status was not cleared by our interrupt
1853 * reset above), perform a soft reset.
1854 */
1855 if (bootverbose)
1856 printf("%s: Invalid Command 0x%x\n", bt_name(bt),
1857 opcode);
1858 DELAY(1000);
1859 status = bt_inb(bt, STATUS_REG);
1860 if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY|
1861 CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0
1862 || (status & (HA_READY|INIT_REQUIRED))
1863 != (HA_READY|INIT_REQUIRED)) {
1864 btreset(bt, /*hard_reset*/FALSE);
1865 }
1866 return (EINVAL);
1867 }
1868
1869
1870 if (param_len > 0) {
1871 /* The controller did not accept the full argument list */
1872 return (E2BIG);
1873 }
1874
1875 if (reply_len != reply_buf_size) {
1876 /* Too much or too little data received */
1877 return (EMSGSIZE);
1878 }
1879
1880 /* We were successful */
1881 return (0);
1882}
1883
1884static int
1885btinitmboxes(struct bt_softc *bt) {
1886 init_32b_mbox_params_t init_mbox;
1887 int error;
1888
1889 bzero(bt->in_boxes, sizeof(bt_mbox_in_t) * bt->num_boxes);
1890 bzero(bt->out_boxes, sizeof(bt_mbox_out_t) * bt->num_boxes);
1891 bt->cur_inbox = bt->in_boxes;
1892 bt->last_inbox = bt->in_boxes + bt->num_boxes - 1;
1893 bt->cur_outbox = bt->out_boxes;
1894 bt->last_outbox = bt->out_boxes + bt->num_boxes - 1;
1895
1896 /* Tell the adapter about them */
1897 init_mbox.num_boxes = bt->num_boxes;
1898 init_mbox.base_addr[0] = bt->mailbox_physbase & 0xFF;
1899 init_mbox.base_addr[1] = (bt->mailbox_physbase >> 8) & 0xFF;
1900 init_mbox.base_addr[2] = (bt->mailbox_physbase >> 16) & 0xFF;
1901 init_mbox.base_addr[3] = (bt->mailbox_physbase >> 24) & 0xFF;
1902 error = bt_cmd(bt, BOP_INITIALIZE_32BMBOX, (u_int8_t *)&init_mbox,
1903 /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL,
1904 /*reply_len*/0, DEFAULT_CMD_TIMEOUT);
1905
1906 if (error != 0)
1907 printf("btinitmboxes: Initialization command failed\n");
1908 else if (bt->strict_rr != 0) {
1909 /*
1910 * If the controller supports
1911 * strict round robin mode,
1912 * enable it
1913 */
1914 u_int8_t param;
1915
1916 param = 0;
1917 error = bt_cmd(bt, BOP_ENABLE_STRICT_RR, &param, 1,
1918 /*reply_buf*/NULL, /*reply_len*/0,
1919 DEFAULT_CMD_TIMEOUT);
1920
1921 if (error != 0) {
1922 printf("btinitmboxes: Unable to enable strict RR\n");
1923 error = 0;
1924 } else if (bootverbose) {
1925 printf("%s: Using Strict Round Robin Mailbox Mode\n",
1926 bt_name(bt));
1927 }
1928 }
1929
1930 return (error);
1931}
1932
1933/*
1934 * Update the XPT's idea of the negotiated transfer
1935 * parameters for a particular target.
1936 */
1937static void
1938btfetchtransinfo(struct bt_softc *bt, struct ccb_trans_settings* cts)
1939{
1940 setup_data_t setup_info;
1941 u_int target;
1942 u_int targ_offset;
1943 u_int targ_mask;
1944 u_int sync_period;
1945 int error;
1946 u_int8_t param;
1947 targ_syncinfo_t sync_info;
1948
1949 target = cts->ccb_h.target_id;
1950 targ_offset = (target & 0x7);
1951 targ_mask = (0x01 << targ_offset);
1952
1953 /*
1954 * Inquire Setup Information. This command retreives the
1955 * Wide negotiation status for recent adapters as well as
1956 * the sync info for older models.
1957 */
1958 param = sizeof(setup_info);
1959 error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, &param, /*paramlen*/1,
1960 (u_int8_t*)&setup_info, sizeof(setup_info),
1961 DEFAULT_CMD_TIMEOUT);
1962
1963 if (error != 0) {
1964 printf("%s: btfetchtransinfo - Inquire Setup Info Failed\n",
1965 bt_name(bt));
1966 return;
1967 }
1968
1969 sync_info = (target < 8) ? setup_info.low_syncinfo[targ_offset]
1970 : setup_info.high_syncinfo[targ_offset];
1971
1972 if (sync_info.sync == 0)
1973 cts->sync_offset = 0;
1974 else
1975 cts->sync_offset = sync_info.offset;
1976
1977 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1978 if (strcmp(bt->firmware_ver, "5.06L") >= 0) {
1979 u_int wide_active;
1980
1981 wide_active =
1982 (target < 8) ? (setup_info.low_wide_active & targ_mask)
1983 : (setup_info.high_wide_active & targ_mask);
1984
1985 if (wide_active)
1986 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1987 } else if ((bt->wide_permitted & targ_mask) != 0) {
1988 struct ccb_getdev cgd;
1989
1990 /*
1991 * Prior to rev 5.06L, wide status isn't provided,
1992 * so we "guess" that wide transfers are in effect
1993 * if the user settings allow for wide and the inquiry
1994 * data for the device indicates that it can handle
1995 * wide transfers.
1996 */
1997 xpt_setup_ccb(&cgd.ccb_h, cts->ccb_h.path, /*priority*/1);
1998 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
1999 xpt_action((union ccb *)&cgd);
2000 if ((cgd.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP
2001 && (cgd.inq_data.flags & SID_WBus16) != 0)
2002 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2003 }
2004
2005 if (bt->firmware_ver[0] >= 3) {
2006 /*
2007 * For adapters that can do fast or ultra speeds,
2008 * use the more exact Target Sync Information command.
2009 */
2010 target_sync_info_data_t sync_info;
2011
2012 param = sizeof(sync_info);
2013 error = bt_cmd(bt, BOP_TARG_SYNC_INFO, &param, /*paramlen*/1,
2014 (u_int8_t*)&sync_info, sizeof(sync_info),
2015 DEFAULT_CMD_TIMEOUT);
2016
2017 if (error != 0) {
2018 printf("%s: btfetchtransinfo - Inquire Sync "
2019 "Info Failed 0x%x\n", bt_name(bt), error);
2020 return;
2021 }
2022 sync_period = sync_info.sync_rate[target] * 100;
2023 } else {
2024 sync_period = 2000 + (500 * sync_info.period);
2025 }
2026
2027 /* Convert ns value to standard SCSI sync rate */
2028 if (cts->sync_offset != 0)
2029 cts->sync_period = scsi_calc_syncparam(sync_period);
2030 else
2031 cts->sync_period = 0;
2032
2033 cts->valid = CCB_TRANS_SYNC_RATE_VALID
2034 | CCB_TRANS_SYNC_OFFSET_VALID
2035 | CCB_TRANS_BUS_WIDTH_VALID;
2036 xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts);
2037}
2038
2039static void
2040btmapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2041{
2042 struct bt_softc* bt;
2043
2044 bt = (struct bt_softc*)arg;
2045 bt->mailbox_physbase = segs->ds_addr;
2046}
2047
2048static void
2049btmapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2050{
2051 struct bt_softc* bt;
2052
2053 bt = (struct bt_softc*)arg;
2054 bt->bt_ccb_physbase = segs->ds_addr;
2055}
2056
2057static void
2058btmapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2059{
2060
2061 struct bt_softc* bt;
2062
2063 bt = (struct bt_softc*)arg;
2064 SLIST_FIRST(&bt->sg_maps)->sg_physaddr = segs->ds_addr;
2065}
2066
2067static void
2068btpoll(struct cam_sim *sim)
2069{
2070 bt_intr(cam_sim_softc(sim));
2071}
2072
2073void
2074bttimeout(void *arg)
2075{
2076 struct bt_ccb *bccb;
2077 union ccb *ccb;
2078 struct bt_softc *bt;
2079 int s;
2080
2081 bccb = (struct bt_ccb *)arg;
2082 ccb = bccb->ccb;
2083 bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr;
2084 xpt_print_path(ccb->ccb_h.path);
2085 printf("CCB %p - timed out\n", (void *)bccb);
2086
2087 s = splcam();
2088
2089 if ((bccb->flags & BCCB_ACTIVE) == 0) {
2090 xpt_print_path(ccb->ccb_h.path);
2091 printf("CCB %p - timed out CCB already completed\n",
2092 (void *)bccb);
2093 splx(s);
2094 return;
2095 }
2096
2097 /*
2098 * In order to simplify the recovery process, we ask the XPT
2099 * layer to halt the queue of new transactions and we traverse
2100 * the list of pending CCBs and remove their timeouts. This
2101 * means that the driver attempts to clear only one error
2102 * condition at a time. In general, timeouts that occur
2103 * close together are related anyway, so there is no benefit
2104 * in attempting to handle errors in parrallel. Timeouts will
2105 * be reinstated when the recovery process ends.
2106 */
2107 if ((bccb->flags & BCCB_DEVICE_RESET) == 0) {
2108 struct ccb_hdr *ccb_h;
2109
2110 if ((bccb->flags & BCCB_RELEASE_SIMQ) == 0) {
2111 xpt_freeze_simq(bt->sim, /*count*/1);
2112 bccb->flags |= BCCB_RELEASE_SIMQ;
2113 }
2114
2115 ccb_h = LIST_FIRST(&bt->pending_ccbs);
2116 while (ccb_h != NULL) {
2117 struct bt_ccb *pending_bccb;
2118
2119 pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr;
2120 untimeout(bttimeout, pending_bccb, ccb_h->timeout_ch);
2121 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
2122 }
2123 }
2124
2125 if ((bccb->flags & BCCB_DEVICE_RESET) != 0
2126 || bt->cur_outbox->action_code != BMBO_FREE
2127 || ((bccb->hccb.tag_enable == TRUE)
2128 && (bt->firmware_ver[0] < '5'))) {
2129 /*
2130 * Try a full host adapter/SCSI bus reset.
2131 * We do this only if we have already attempted
2132 * to clear the condition with a BDR, or we cannot
2133 * attempt a BDR for lack of mailbox resources
2134 * or because of faulty firmware. It turns out
2135 * that firmware versions prior to 5.xx treat BDRs
2136 * as untagged commands that cannot be sent until
2137 * all outstanding tagged commands have been processed.
2138 * This makes it somewhat difficult to use a BDR to
2139 * clear up a problem with an uncompleted tagged command.
2140 */
2141 ccb->ccb_h.status = CAM_CMD_TIMEOUT;
2142 btreset(bt, /*hardreset*/TRUE);
2143 printf("%s: No longer in timeout\n", bt_name(bt));
2144 } else {
2145 /*
2146 * Send a Bus Device Reset message:
2147 * The target that is holding up the bus may not
2148 * be the same as the one that triggered this timeout
2149 * (different commands have different timeout lengths),
2150 * but we have no way of determining this from our
2151 * timeout handler. Our strategy here is to queue a
2152 * BDR message to the target of the timed out command.
2153 * If this fails, we'll get another timeout 2 seconds
2154 * later which will attempt a bus reset.
2155 */
2156 bccb->flags |= BCCB_DEVICE_RESET;
2157 ccb->ccb_h.timeout_ch =
2158 timeout(bttimeout, (caddr_t)bccb, 2 * hz);
2159
2160 bt->recovery_bccb->hccb.opcode = INITIATOR_BUS_DEV_RESET;
2161
2162 /* No Data Transfer */
2163 bt->recovery_bccb->hccb.datain = TRUE;
2164 bt->recovery_bccb->hccb.dataout = TRUE;
2165 bt->recovery_bccb->hccb.btstat = 0;
2166 bt->recovery_bccb->hccb.sdstat = 0;
2167 bt->recovery_bccb->hccb.target_id = ccb->ccb_h.target_id;
2168
2169 /* Tell the adapter about this command */
2170 bt->cur_outbox->ccb_addr = btccbvtop(bt, bt->recovery_bccb);
2171 bt->cur_outbox->action_code = BMBO_START;
2172 bt_outb(bt, COMMAND_REG, BOP_START_MBOX);
2173 btnextoutbox(bt);
2174 }
2175
2176 splx(s);
2177}
2178
1555 csio->ccb_h.status = CAM_DATA_RUN_ERR;
1556 break;
1557 }
1558 /* FALLTHROUGH */
1559 case BTSTAT_NOERROR:
1560 case BTSTAT_LINKED_CMD_COMPLETE:
1561 case BTSTAT_LINKED_CMD_FLAG_COMPLETE:
1562 case BTSTAT_DATAUNDERUN_ERROR:
1563
1564 csio->scsi_status = bccb->hccb.sdstat;
1565 csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
1566 switch(csio->scsi_status) {
1567 case SCSI_STATUS_CHECK_COND:
1568 case SCSI_STATUS_CMD_TERMINATED:
1569 csio->ccb_h.status |= CAM_AUTOSNS_VALID;
1570 /* Bounce sense back if necessary */
1571 if (bt->sense_buffers != NULL) {
1572 csio->sense_data =
1573 *btsensevaddr(bt, bccb);
1574 }
1575 break;
1576 default:
1577 break;
1578 case SCSI_STATUS_OK:
1579 csio->ccb_h.status = CAM_REQ_CMP;
1580 break;
1581 }
1582 csio->resid = bccb->hccb.data_len;
1583 break;
1584 case BTSTAT_SELTIMEOUT:
1585 csio->ccb_h.status = CAM_SEL_TIMEOUT;
1586 break;
1587 case BTSTAT_UNEXPECTED_BUSFREE:
1588 csio->ccb_h.status = CAM_UNEXP_BUSFREE;
1589 break;
1590 case BTSTAT_INVALID_PHASE:
1591 csio->ccb_h.status = CAM_SEQUENCE_FAIL;
1592 break;
1593 case BTSTAT_INVALID_ACTION_CODE:
1594 panic("%s: Inavlid Action code", bt_name(bt));
1595 break;
1596 case BTSTAT_INVALID_OPCODE:
1597 panic("%s: Inavlid CCB Opcode code", bt_name(bt));
1598 break;
1599 case BTSTAT_LINKED_CCB_LUN_MISMATCH:
1600 /* We don't even support linked commands... */
1601 panic("%s: Linked CCB Lun Mismatch", bt_name(bt));
1602 break;
1603 case BTSTAT_INVALID_CCB_OR_SG_PARAM:
1604 panic("%s: Invalid CCB or SG list", bt_name(bt));
1605 break;
1606 case BTSTAT_AUTOSENSE_FAILED:
1607 csio->ccb_h.status = CAM_AUTOSENSE_FAIL;
1608 break;
1609 case BTSTAT_TAGGED_MSG_REJECTED:
1610 {
1611 struct ccb_trans_settings neg;
1612
1613 xpt_print_path(csio->ccb_h.path);
1614 printf("refuses tagged commands. Performing "
1615 "non-tagged I/O\n");
1616 neg.flags = 0;
1617 neg.valid = CCB_TRANS_TQ_VALID;
1618 xpt_setup_ccb(&neg.ccb_h, csio->ccb_h.path,
1619 /*priority*/1);
1620 xpt_async(AC_TRANSFER_NEG, csio->ccb_h.path, &neg);
1621 bt->tags_permitted &= ~(0x01 << csio->ccb_h.target_id);
1622 csio->ccb_h.status = CAM_MSG_REJECT_REC;
1623 break;
1624 }
1625 case BTSTAT_UNSUPPORTED_MSG_RECEIVED:
1626 /*
1627 * XXX You would think that this is
1628 * a recoverable error... Hmmm.
1629 */
1630 csio->ccb_h.status = CAM_REQ_CMP_ERR;
1631 break;
1632 case BTSTAT_HA_SOFTWARE_ERROR:
1633 case BTSTAT_HA_WATCHDOG_ERROR:
1634 case BTSTAT_HARDWARE_FAILURE:
1635 /* Hardware reset ??? Can we recover ??? */
1636 csio->ccb_h.status = CAM_NO_HBA;
1637 break;
1638 case BTSTAT_TARGET_IGNORED_ATN:
1639 case BTSTAT_OTHER_SCSI_BUS_RESET:
1640 case BTSTAT_HA_SCSI_BUS_RESET:
1641 if ((csio->ccb_h.status & CAM_STATUS_MASK)
1642 != CAM_CMD_TIMEOUT)
1643 csio->ccb_h.status = CAM_SCSI_BUS_RESET;
1644 break;
1645 case BTSTAT_HA_BDR:
1646 if ((bccb->flags & BCCB_DEVICE_RESET) == 0)
1647 csio->ccb_h.status = CAM_BDR_SENT;
1648 else
1649 csio->ccb_h.status = CAM_CMD_TIMEOUT;
1650 break;
1651 case BTSTAT_INVALID_RECONNECT:
1652 case BTSTAT_ABORT_QUEUE_GENERATED:
1653 csio->ccb_h.status = CAM_REQ_TERMIO;
1654 break;
1655 case BTSTAT_SCSI_PERROR_DETECTED:
1656 csio->ccb_h.status = CAM_UNCOR_PARITY;
1657 break;
1658 }
1659 if (csio->ccb_h.status != CAM_REQ_CMP) {
1660 xpt_freeze_devq(csio->ccb_h.path, /*count*/1);
1661 csio->ccb_h.status |= CAM_DEV_QFRZN;
1662 }
1663 if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0)
1664 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1665 btfreeccb(bt, bccb);
1666 xpt_done(ccb);
1667 break;
1668 case BMBI_OK:
1669 /* All completed without incident */
1670 ccb->ccb_h.status |= CAM_REQ_CMP;
1671 if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0)
1672 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1673 btfreeccb(bt, bccb);
1674 xpt_done(ccb);
1675 break;
1676 }
1677}
1678
1679static int
1680btreset(struct bt_softc* bt, int hard_reset)
1681{
1682 struct ccb_hdr *ccb_h;
1683 u_int status;
1684 u_int timeout;
1685 u_int8_t reset_type;
1686
1687 if (hard_reset != 0)
1688 reset_type = HARD_RESET;
1689 else
1690 reset_type = SOFT_RESET;
1691 bt_outb(bt, CONTROL_REG, reset_type);
1692
1693 /* Wait 5sec. for Diagnostic start */
1694 timeout = 5 * 10000;
1695 while (--timeout) {
1696 status = bt_inb(bt, STATUS_REG);
1697 if ((status & DIAG_ACTIVE) != 0)
1698 break;
1699 DELAY(100);
1700 }
1701 if (timeout == 0) {
1702 if (bootverbose)
1703 printf("%s: btreset - Diagnostic Active failed to "
1704 "assert. status = 0x%x\n", bt_name(bt), status);
1705 return (ETIMEDOUT);
1706 }
1707
1708 /* Wait 10sec. for Diagnostic end */
1709 timeout = 10 * 10000;
1710 while (--timeout) {
1711 status = bt_inb(bt, STATUS_REG);
1712 if ((status & DIAG_ACTIVE) == 0)
1713 break;
1714 DELAY(100);
1715 }
1716 if (timeout == 0) {
1717 panic("%s: btreset - Diagnostic Active failed to drop. "
1718 "status = 0x%x\n", bt_name(bt), status);
1719 return (ETIMEDOUT);
1720 }
1721
1722 /* Wait for the host adapter to become ready or report a failure */
1723 timeout = 10000;
1724 while (--timeout) {
1725 status = bt_inb(bt, STATUS_REG);
1726 if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0)
1727 break;
1728 DELAY(100);
1729 }
1730 if (timeout == 0) {
1731 printf("%s: btreset - Host adapter failed to come ready. "
1732 "status = 0x%x\n", bt_name(bt), status);
1733 return (ETIMEDOUT);
1734 }
1735
1736 /* If the diagnostics failed, tell the user */
1737 if ((status & DIAG_FAIL) != 0
1738 || (status & HA_READY) == 0) {
1739 printf("%s: btreset - Adapter failed diagnostics\n",
1740 bt_name(bt));
1741
1742 if ((status & DATAIN_REG_READY) != 0)
1743 printf("%s: btreset - Host Adapter Error code = 0x%x\n",
1744 bt_name(bt), bt_inb(bt, DATAIN_REG));
1745 return (ENXIO);
1746 }
1747
1748 /* If we've allocated mailboxes, initialize them */
1749 if (bt->init_level > 4)
1750 btinitmboxes(bt);
1751
1752 /* If we've attached to the XPT, tell it about the event */
1753 if (bt->path != NULL)
1754 xpt_async(AC_BUS_RESET, bt->path, NULL);
1755
1756 /*
1757 * Perform completion processing for all outstanding CCBs.
1758 */
1759 while ((ccb_h = LIST_FIRST(&bt->pending_ccbs)) != NULL) {
1760 struct bt_ccb *pending_bccb;
1761
1762 pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr;
1763 pending_bccb->hccb.btstat = BTSTAT_HA_SCSI_BUS_RESET;
1764 btdone(bt, pending_bccb, BMBI_ERROR);
1765 }
1766
1767 return (0);
1768}
1769
1770/*
1771 * Send a command to the adapter.
1772 */
1773int
1774bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len,
1775 u_int8_t *reply_data, u_int reply_len, u_int cmd_timeout)
1776{
1777 u_int timeout;
1778 u_int status;
1779 u_int intstat;
1780 u_int reply_buf_size;
1781 int s;
1782
1783 /* No data returned to start */
1784 reply_buf_size = reply_len;
1785 reply_len = 0;
1786 intstat = 0;
1787
1788 bt->command_cmp = 0;
1789 /*
1790 * Wait up to 1 sec. for the adapter to become
1791 * ready to accept commands.
1792 */
1793 timeout = 10000;
1794 while (--timeout) {
1795
1796 status = bt_inb(bt, STATUS_REG);
1797 if ((status & HA_READY) != 0
1798 && (status & CMD_REG_BUSY) == 0)
1799 break;
1800 DELAY(100);
1801 }
1802 if (timeout == 0) {
1803 printf("%s: bt_cmd: Timeout waiting for adapter ready, "
1804 "status = 0x%x\n", bt_name(bt), status);
1805 return (ETIMEDOUT);
1806 }
1807
1808 /*
1809 * Send the opcode followed by any necessary parameter bytes.
1810 */
1811 bt_outb(bt, COMMAND_REG, opcode);
1812
1813 /*
1814 * Wait for up to 1sec to get the parameter list sent
1815 */
1816 timeout = 10000;
1817 while (param_len && --timeout) {
1818 DELAY(100);
1819 status = bt_inb(bt, STATUS_REG);
1820 intstat = bt_inb(bt, INTSTAT_REG);
1821 if ((intstat & (INTR_PENDING|CMD_COMPLETE))
1822 == (INTR_PENDING|CMD_COMPLETE))
1823 break;
1824 if (bt->command_cmp != 0) {
1825 status = bt->latched_status;
1826 break;
1827 }
1828 if ((status & DATAIN_REG_READY) != 0)
1829 break;
1830 if ((status & CMD_REG_BUSY) == 0) {
1831 bt_outb(bt, COMMAND_REG, *params++);
1832 param_len--;
1833 }
1834 }
1835 if (timeout == 0) {
1836 printf("%s: bt_cmd: Timeout sending parameters, "
1837 "status = 0x%x\n", bt_name(bt), status);
1838 return (ETIMEDOUT);
1839 }
1840
1841 /*
1842 * The BOP_MODIFY_IO_ADDR does not issue a CMD_COMPLETE, but
1843 * it should update the status register. So, we wait for
1844 * the CMD_REG_BUSY status to clear and check for a command
1845 * failure.
1846 */
1847 if (opcode == BOP_MODIFY_IO_ADDR) {
1848
1849 while (--cmd_timeout) {
1850 status = bt_inb(bt, STATUS_REG);
1851 if ((status & CMD_REG_BUSY) == 0) {
1852 if ((status & CMD_INVALID) != 0) {
1853 printf("%s: bt_cmd - Modify I/O Address"
1854 " invalid\n", bt_name(bt));
1855 return (EINVAL);
1856 }
1857 return (0);
1858 }
1859 DELAY(100);
1860 }
1861 if (timeout == 0) {
1862 printf("%s: bt_cmd: Timeout on Modify I/O Address CMD, "
1863 "status = 0x%x\n", bt_name(bt), status);
1864 return (ETIMEDOUT);
1865 }
1866 }
1867
1868 /*
1869 * For all other commands, we wait for any output data
1870 * and the final comand completion interrupt.
1871 */
1872 while (--cmd_timeout) {
1873
1874 status = bt_inb(bt, STATUS_REG);
1875 intstat = bt_inb(bt, INTSTAT_REG);
1876 if ((intstat & (INTR_PENDING|CMD_COMPLETE))
1877 == (INTR_PENDING|CMD_COMPLETE))
1878 break;
1879
1880 if (bt->command_cmp != 0) {
1881 status = bt->latched_status;
1882 break;
1883 }
1884
1885 if ((status & DATAIN_REG_READY) != 0) {
1886 u_int8_t data;
1887
1888 data = bt_inb(bt, DATAIN_REG);
1889 if (reply_len < reply_buf_size) {
1890 *reply_data++ = data;
1891 } else {
1892 printf("%s: bt_cmd - Discarded reply data byte "
1893 "for opcode 0x%x\n", bt_name(bt),
1894 opcode);
1895 }
1896 reply_len++;
1897 }
1898
1899 if ((opcode == BOP_FETCH_LRAM)
1900 && (status & HA_READY) != 0)
1901 break;
1902 DELAY(100);
1903 }
1904 if (timeout == 0) {
1905 printf("%s: bt_cmd: Timeout waiting for reply data and "
1906 "command complete.\n%s: status = 0x%x, intstat = 0x%x, "
1907 "reply_len = %d\n", bt_name(bt), bt_name(bt), status,
1908 intstat, reply_len);
1909 return (ETIMEDOUT);
1910 }
1911
1912 /*
1913 * Clear any pending interrupts. Block interrupts so our
1914 * interrupt handler is not re-entered.
1915 */
1916 s = splcam();
1917 bt_intr(bt);
1918 splx(s);
1919
1920 /*
1921 * If the command was rejected by the controller, tell the caller.
1922 */
1923 if ((status & CMD_INVALID) != 0) {
1924 /*
1925 * Some early adapters may not recover properly from
1926 * an invalid command. If it appears that the controller
1927 * has wedged (i.e. status was not cleared by our interrupt
1928 * reset above), perform a soft reset.
1929 */
1930 if (bootverbose)
1931 printf("%s: Invalid Command 0x%x\n", bt_name(bt),
1932 opcode);
1933 DELAY(1000);
1934 status = bt_inb(bt, STATUS_REG);
1935 if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY|
1936 CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0
1937 || (status & (HA_READY|INIT_REQUIRED))
1938 != (HA_READY|INIT_REQUIRED)) {
1939 btreset(bt, /*hard_reset*/FALSE);
1940 }
1941 return (EINVAL);
1942 }
1943
1944
1945 if (param_len > 0) {
1946 /* The controller did not accept the full argument list */
1947 return (E2BIG);
1948 }
1949
1950 if (reply_len != reply_buf_size) {
1951 /* Too much or too little data received */
1952 return (EMSGSIZE);
1953 }
1954
1955 /* We were successful */
1956 return (0);
1957}
1958
1959static int
1960btinitmboxes(struct bt_softc *bt) {
1961 init_32b_mbox_params_t init_mbox;
1962 int error;
1963
1964 bzero(bt->in_boxes, sizeof(bt_mbox_in_t) * bt->num_boxes);
1965 bzero(bt->out_boxes, sizeof(bt_mbox_out_t) * bt->num_boxes);
1966 bt->cur_inbox = bt->in_boxes;
1967 bt->last_inbox = bt->in_boxes + bt->num_boxes - 1;
1968 bt->cur_outbox = bt->out_boxes;
1969 bt->last_outbox = bt->out_boxes + bt->num_boxes - 1;
1970
1971 /* Tell the adapter about them */
1972 init_mbox.num_boxes = bt->num_boxes;
1973 init_mbox.base_addr[0] = bt->mailbox_physbase & 0xFF;
1974 init_mbox.base_addr[1] = (bt->mailbox_physbase >> 8) & 0xFF;
1975 init_mbox.base_addr[2] = (bt->mailbox_physbase >> 16) & 0xFF;
1976 init_mbox.base_addr[3] = (bt->mailbox_physbase >> 24) & 0xFF;
1977 error = bt_cmd(bt, BOP_INITIALIZE_32BMBOX, (u_int8_t *)&init_mbox,
1978 /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL,
1979 /*reply_len*/0, DEFAULT_CMD_TIMEOUT);
1980
1981 if (error != 0)
1982 printf("btinitmboxes: Initialization command failed\n");
1983 else if (bt->strict_rr != 0) {
1984 /*
1985 * If the controller supports
1986 * strict round robin mode,
1987 * enable it
1988 */
1989 u_int8_t param;
1990
1991 param = 0;
1992 error = bt_cmd(bt, BOP_ENABLE_STRICT_RR, &param, 1,
1993 /*reply_buf*/NULL, /*reply_len*/0,
1994 DEFAULT_CMD_TIMEOUT);
1995
1996 if (error != 0) {
1997 printf("btinitmboxes: Unable to enable strict RR\n");
1998 error = 0;
1999 } else if (bootverbose) {
2000 printf("%s: Using Strict Round Robin Mailbox Mode\n",
2001 bt_name(bt));
2002 }
2003 }
2004
2005 return (error);
2006}
2007
2008/*
2009 * Update the XPT's idea of the negotiated transfer
2010 * parameters for a particular target.
2011 */
2012static void
2013btfetchtransinfo(struct bt_softc *bt, struct ccb_trans_settings* cts)
2014{
2015 setup_data_t setup_info;
2016 u_int target;
2017 u_int targ_offset;
2018 u_int targ_mask;
2019 u_int sync_period;
2020 int error;
2021 u_int8_t param;
2022 targ_syncinfo_t sync_info;
2023
2024 target = cts->ccb_h.target_id;
2025 targ_offset = (target & 0x7);
2026 targ_mask = (0x01 << targ_offset);
2027
2028 /*
2029 * Inquire Setup Information. This command retreives the
2030 * Wide negotiation status for recent adapters as well as
2031 * the sync info for older models.
2032 */
2033 param = sizeof(setup_info);
2034 error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, &param, /*paramlen*/1,
2035 (u_int8_t*)&setup_info, sizeof(setup_info),
2036 DEFAULT_CMD_TIMEOUT);
2037
2038 if (error != 0) {
2039 printf("%s: btfetchtransinfo - Inquire Setup Info Failed\n",
2040 bt_name(bt));
2041 return;
2042 }
2043
2044 sync_info = (target < 8) ? setup_info.low_syncinfo[targ_offset]
2045 : setup_info.high_syncinfo[targ_offset];
2046
2047 if (sync_info.sync == 0)
2048 cts->sync_offset = 0;
2049 else
2050 cts->sync_offset = sync_info.offset;
2051
2052 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
2053 if (strcmp(bt->firmware_ver, "5.06L") >= 0) {
2054 u_int wide_active;
2055
2056 wide_active =
2057 (target < 8) ? (setup_info.low_wide_active & targ_mask)
2058 : (setup_info.high_wide_active & targ_mask);
2059
2060 if (wide_active)
2061 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2062 } else if ((bt->wide_permitted & targ_mask) != 0) {
2063 struct ccb_getdev cgd;
2064
2065 /*
2066 * Prior to rev 5.06L, wide status isn't provided,
2067 * so we "guess" that wide transfers are in effect
2068 * if the user settings allow for wide and the inquiry
2069 * data for the device indicates that it can handle
2070 * wide transfers.
2071 */
2072 xpt_setup_ccb(&cgd.ccb_h, cts->ccb_h.path, /*priority*/1);
2073 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
2074 xpt_action((union ccb *)&cgd);
2075 if ((cgd.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP
2076 && (cgd.inq_data.flags & SID_WBus16) != 0)
2077 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2078 }
2079
2080 if (bt->firmware_ver[0] >= 3) {
2081 /*
2082 * For adapters that can do fast or ultra speeds,
2083 * use the more exact Target Sync Information command.
2084 */
2085 target_sync_info_data_t sync_info;
2086
2087 param = sizeof(sync_info);
2088 error = bt_cmd(bt, BOP_TARG_SYNC_INFO, &param, /*paramlen*/1,
2089 (u_int8_t*)&sync_info, sizeof(sync_info),
2090 DEFAULT_CMD_TIMEOUT);
2091
2092 if (error != 0) {
2093 printf("%s: btfetchtransinfo - Inquire Sync "
2094 "Info Failed 0x%x\n", bt_name(bt), error);
2095 return;
2096 }
2097 sync_period = sync_info.sync_rate[target] * 100;
2098 } else {
2099 sync_period = 2000 + (500 * sync_info.period);
2100 }
2101
2102 /* Convert ns value to standard SCSI sync rate */
2103 if (cts->sync_offset != 0)
2104 cts->sync_period = scsi_calc_syncparam(sync_period);
2105 else
2106 cts->sync_period = 0;
2107
2108 cts->valid = CCB_TRANS_SYNC_RATE_VALID
2109 | CCB_TRANS_SYNC_OFFSET_VALID
2110 | CCB_TRANS_BUS_WIDTH_VALID;
2111 xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts);
2112}
2113
2114static void
2115btmapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2116{
2117 struct bt_softc* bt;
2118
2119 bt = (struct bt_softc*)arg;
2120 bt->mailbox_physbase = segs->ds_addr;
2121}
2122
2123static void
2124btmapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2125{
2126 struct bt_softc* bt;
2127
2128 bt = (struct bt_softc*)arg;
2129 bt->bt_ccb_physbase = segs->ds_addr;
2130}
2131
2132static void
2133btmapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2134{
2135
2136 struct bt_softc* bt;
2137
2138 bt = (struct bt_softc*)arg;
2139 SLIST_FIRST(&bt->sg_maps)->sg_physaddr = segs->ds_addr;
2140}
2141
2142static void
2143btpoll(struct cam_sim *sim)
2144{
2145 bt_intr(cam_sim_softc(sim));
2146}
2147
2148void
2149bttimeout(void *arg)
2150{
2151 struct bt_ccb *bccb;
2152 union ccb *ccb;
2153 struct bt_softc *bt;
2154 int s;
2155
2156 bccb = (struct bt_ccb *)arg;
2157 ccb = bccb->ccb;
2158 bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr;
2159 xpt_print_path(ccb->ccb_h.path);
2160 printf("CCB %p - timed out\n", (void *)bccb);
2161
2162 s = splcam();
2163
2164 if ((bccb->flags & BCCB_ACTIVE) == 0) {
2165 xpt_print_path(ccb->ccb_h.path);
2166 printf("CCB %p - timed out CCB already completed\n",
2167 (void *)bccb);
2168 splx(s);
2169 return;
2170 }
2171
2172 /*
2173 * In order to simplify the recovery process, we ask the XPT
2174 * layer to halt the queue of new transactions and we traverse
2175 * the list of pending CCBs and remove their timeouts. This
2176 * means that the driver attempts to clear only one error
2177 * condition at a time. In general, timeouts that occur
2178 * close together are related anyway, so there is no benefit
2179 * in attempting to handle errors in parrallel. Timeouts will
2180 * be reinstated when the recovery process ends.
2181 */
2182 if ((bccb->flags & BCCB_DEVICE_RESET) == 0) {
2183 struct ccb_hdr *ccb_h;
2184
2185 if ((bccb->flags & BCCB_RELEASE_SIMQ) == 0) {
2186 xpt_freeze_simq(bt->sim, /*count*/1);
2187 bccb->flags |= BCCB_RELEASE_SIMQ;
2188 }
2189
2190 ccb_h = LIST_FIRST(&bt->pending_ccbs);
2191 while (ccb_h != NULL) {
2192 struct bt_ccb *pending_bccb;
2193
2194 pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr;
2195 untimeout(bttimeout, pending_bccb, ccb_h->timeout_ch);
2196 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
2197 }
2198 }
2199
2200 if ((bccb->flags & BCCB_DEVICE_RESET) != 0
2201 || bt->cur_outbox->action_code != BMBO_FREE
2202 || ((bccb->hccb.tag_enable == TRUE)
2203 && (bt->firmware_ver[0] < '5'))) {
2204 /*
2205 * Try a full host adapter/SCSI bus reset.
2206 * We do this only if we have already attempted
2207 * to clear the condition with a BDR, or we cannot
2208 * attempt a BDR for lack of mailbox resources
2209 * or because of faulty firmware. It turns out
2210 * that firmware versions prior to 5.xx treat BDRs
2211 * as untagged commands that cannot be sent until
2212 * all outstanding tagged commands have been processed.
2213 * This makes it somewhat difficult to use a BDR to
2214 * clear up a problem with an uncompleted tagged command.
2215 */
2216 ccb->ccb_h.status = CAM_CMD_TIMEOUT;
2217 btreset(bt, /*hardreset*/TRUE);
2218 printf("%s: No longer in timeout\n", bt_name(bt));
2219 } else {
2220 /*
2221 * Send a Bus Device Reset message:
2222 * The target that is holding up the bus may not
2223 * be the same as the one that triggered this timeout
2224 * (different commands have different timeout lengths),
2225 * but we have no way of determining this from our
2226 * timeout handler. Our strategy here is to queue a
2227 * BDR message to the target of the timed out command.
2228 * If this fails, we'll get another timeout 2 seconds
2229 * later which will attempt a bus reset.
2230 */
2231 bccb->flags |= BCCB_DEVICE_RESET;
2232 ccb->ccb_h.timeout_ch =
2233 timeout(bttimeout, (caddr_t)bccb, 2 * hz);
2234
2235 bt->recovery_bccb->hccb.opcode = INITIATOR_BUS_DEV_RESET;
2236
2237 /* No Data Transfer */
2238 bt->recovery_bccb->hccb.datain = TRUE;
2239 bt->recovery_bccb->hccb.dataout = TRUE;
2240 bt->recovery_bccb->hccb.btstat = 0;
2241 bt->recovery_bccb->hccb.sdstat = 0;
2242 bt->recovery_bccb->hccb.target_id = ccb->ccb_h.target_id;
2243
2244 /* Tell the adapter about this command */
2245 bt->cur_outbox->ccb_addr = btccbvtop(bt, bt->recovery_bccb);
2246 bt->cur_outbox->action_code = BMBO_START;
2247 bt_outb(bt, COMMAND_REG, BOP_START_MBOX);
2248 btnextoutbox(bt);
2249 }
2250
2251 splx(s);
2252}
2253