Add in the twa(4) driver. This adds in support for the 3Ware
[dragonfly.git] / sys / dev / raid / twa / twa_cam.c
1 /*-
2  * Copyright (c) 2003-04 3ware, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *      $FreeBSD$
27  * $DragonFly: src/sys/dev/raid/twa/twa_cam.c,v 1.1 2004/04/16 20:13:16 drhodus Exp $
28  */
29
30 /*
31  * 3ware driver for 9000 series storage controllers.
32  *
33  * Author: Vinod Kashyap
34  */
35
36
37 #include "twa_includes.h"
38
39 #include <bus/cam/cam.h>
40 #include <bus/cam/cam_ccb.h>
41 #include <bus/cam/cam_sim.h>
42 #include <bus/cam/cam_xpt_sim.h>
43 #include <bus/cam/cam_xpt_periph.h>
44 #include <bus/cam/cam_debug.h>
45 #include <bus/cam/cam_periph.h>
46
47 #include <bus/cam/scsi/scsi_all.h>
48 #include <bus/cam/scsi/scsi_message.h>
49
50 static int      twa_execute_scsi(struct twa_request *tr, union ccb *ccb);
51 static void     twa_action(struct cam_sim *sim, union ccb *ccb);
52 static void     twa_poll(struct cam_sim *sim);
53 static void     twa_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg);
54 static void     twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
55
56
57
58 /*
59  * Function name:       twa_cam_setup
60  * Description:         Attaches the driver to CAM.
61  *
62  * Input:               sc      -- ptr to per ctlr structure
63  * Output:              None
64  * Return value:        0       -- success
65  *                      non-zero-- failure
66  */
67 int
68 twa_cam_setup(struct twa_softc *sc)
69 {
70         struct cam_devq         *devq;
71         struct ccb_setasync     csa;
72
73         twa_dbg_dprint(3, sc, "sc = %p", sc);
74         /*
75          * Create the device queue for our SIM.
76          */
77         devq = cam_simq_alloc(TWA_Q_LENGTH);
78         if (devq == NULL)
79                 return(ENOMEM);
80
81         /*
82          * Create a SIM entry.  Though we can support TWA_Q_LENGTH simultaneous
83          * requests, we claim to be able to handle only (TWA_Q_LENGTH - 1), so
84          * that we always have a request packet available to service attention
85          * interrupts.
86          */
87         twa_dbg_dprint(3, sc, "Calling cam_sim_alloc");
88         sc->twa_sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
89                                         device_get_unit(sc->twa_bus_dev),
90                                         TWA_Q_LENGTH - 1, 1, devq);
91         cam_simq_release(devq);
92         if (sc->twa_sim == NULL) {
93                 return(ENOMEM);
94         }
95
96         /*
97          * Register the bus.
98          */
99         twa_dbg_dprint(3, sc, "Calling xpt_bus_register");
100         if (xpt_bus_register(sc->twa_sim, 0) != CAM_SUCCESS) {
101                 cam_sim_free(sc->twa_sim);
102                 sc->twa_sim = NULL; /* so twa_cam_detach will not try to free it */
103                 return(ENXIO);
104         }
105
106         twa_dbg_dprint(3, sc, "Calling xpt_create_path");
107         if (xpt_create_path(&sc->twa_path, NULL,
108                                 cam_sim_path(sc->twa_sim),
109                                 CAM_TARGET_WILDCARD,
110                                 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
111                 xpt_bus_deregister(cam_sim_path (sc->twa_sim));
112                 cam_sim_free(sc->twa_sim); /* passing TRUE will free the devq as well */
113                 return(ENXIO);
114         }
115
116         twa_dbg_dprint(3, sc, "Calling xpt_setup_ccb");
117         xpt_setup_ccb(&csa.ccb_h, sc->twa_path, 5);
118         csa.ccb_h.func_code = XPT_SASYNC_CB;
119         csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
120         csa.callback = twa_async;
121         csa.callback_arg = sc;
122         xpt_action((union ccb *)&csa);
123
124         twa_dbg_dprint(3, sc, "Calling twa_request_bus_scan");
125         /*
126          * Request a bus scan, so that CAM gets to know of
127          * the logical units that we control.
128          */
129         twa_request_bus_scan(sc);
130         twa_dbg_dprint(3, sc, "Exiting");
131         return(0);
132 }
133
134
135
136 /*
137  * Function name:       twa_cam_detach
138  * Description:         Detaches the driver from CAM.
139  *
140  * Input:               sc      -- ptr to per ctlr structure
141  * Output:              None
142  * Return value:        None
143  */
144 void
145 twa_cam_detach(struct twa_softc *sc)
146 {
147         if (sc->twa_path)
148                 xpt_free_path(sc->twa_path);
149         if (sc->twa_sim) {
150                 xpt_bus_deregister(cam_sim_path(sc->twa_sim));
151                 cam_sim_free(sc->twa_sim); /* passing TRUE will free the devq as well */
152         }
153 }
154
155
156
157 /*
158  * Function name:       twa_send_scsi_cmd
159  * Description:         Sends down a scsi cmd to fw.
160  *
161  * Input:               tr      -- ptr to request pkt
162  *                      cmd     -- opcode of scsi cmd to send
163  * Output:              None
164  * Return value:        0       -- success
165  *                      non-zero-- failure
166  */
167 int
168 twa_send_scsi_cmd(struct twa_request *tr, int cmd)
169 {
170         union ccb       ccb;
171
172         bzero(&ccb, sizeof(union ccb));
173         ccb.csio.cdb_io.cdb_bytes[0] = (u_int8_t)cmd;
174         ccb.csio.cdb_io.cdb_bytes[4] = 128;
175         ccb.csio.cdb_len = 16;
176         if ((ccb.csio.data_ptr = malloc(TWA_SECTOR_SIZE, M_DEVBUF, M_NOWAIT))
177                                         == NULL)
178                 return(ENOMEM);
179         bzero(ccb.csio.data_ptr, TWA_SECTOR_SIZE);
180         ccb.csio.dxfer_len = TWA_SECTOR_SIZE;
181
182         ccb.ccb_h.target_id = 0;
183         ccb.ccb_h.flags |= CAM_DIR_IN;
184
185         if (twa_execute_scsi(tr, &ccb))
186                 return(EIO);
187         return(0);
188 }
189
190
191
192 /*
193  * Function name:       twa_execute_scsi
194  * Description:         Build a fw cmd, based on a CAM style ccb, and
195  *                      send it down.
196  *
197  * Input:               tr      -- ptr to request pkt
198  *                      ccb     -- ptr to CAM style ccb
199  * Output:              None
200  * Return value:        0       -- success
201  *                      non-zero-- failure
202  */
203 int
204 twa_execute_scsi(struct twa_request *tr, union ccb *ccb)
205 {
206         struct twa_softc                *sc = tr->tr_sc;
207         struct twa_command_packet       *cmdpkt;
208         struct twa_command_9k           *cmd9k;
209         struct ccb_hdr                  *ccb_h = &(ccb->ccb_h);
210         struct ccb_scsiio               *csio = &(ccb->csio);
211         int                             error;
212
213         twa_dbg_dprint(3, sc, "SCSI I/O request 0x%x", 
214                                 csio->cdb_io.cdb_bytes[0]);
215
216         if (ccb_h->target_id >= TWA_MAX_UNITS) {
217                 twa_dbg_dprint(3, sc, "Invalid target. PTL = %x %x %x",
218                         ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
219                 ccb_h->status |= CAM_TID_INVALID;
220                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
221                         xpt_done(ccb);
222                 return(1);
223         }
224         if (ccb_h->target_lun != 0) {
225                 twa_dbg_dprint(3, sc, "Invalid lun. PTL = %x %x %x",
226                         ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
227                 ccb_h->status |= CAM_LUN_INVALID;
228                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
229                         xpt_done(ccb);
230                 return(1);
231         }
232
233         if(ccb_h->flags & CAM_CDB_PHYS) {
234                 twa_printf(sc, "Physical CDB address!\n");
235                 ccb_h->status = CAM_REQ_CMP_ERR;
236                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
237                         xpt_done(ccb);
238                 return(1);
239         }
240
241         /*
242          * We are going to work on this request.  Mark it as enqueued (though
243          * we don't actually queue it...)
244          */
245         ccb_h->status |= CAM_SIM_QUEUED;
246
247         if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
248                 if(ccb_h->flags & CAM_DIR_IN)
249                         tr->tr_flags |= TWA_CMD_DATA_IN;
250                 else
251                         tr->tr_flags |= TWA_CMD_DATA_OUT;
252         }
253
254         cmdpkt = tr->tr_command;
255
256         cmdpkt->cmd_hdr.header_desc.size_header = 128;
257                 
258         cmd9k = &(cmdpkt->command.cmd_pkt_9k);
259         cmd9k->command.opcode = TWA_OP_EXECUTE_SCSI_COMMAND;
260         cmd9k->unit = ccb_h->target_id;
261         cmd9k->request_id = tr->tr_request_id;
262         cmd9k->status = 0;
263         cmd9k->sgl_offset = 16; /* offset from end of hdr = max cdb len */
264
265         if(ccb_h->flags & CAM_CDB_POINTER)
266                 bcopy(csio->cdb_io.cdb_ptr, cmd9k->cdb, csio->cdb_len);
267         else
268                 bcopy(csio->cdb_io.cdb_bytes, cmd9k->cdb, csio->cdb_len);
269
270         if (!(ccb_h->flags & CAM_DATA_PHYS)) {
271                 /* Virtual data addresses.  Need to convert them... */
272                 twa_dbg_dprint(3, sc, "XPT_SCSI_IO: Single virtual address!");
273                 if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
274                         if (csio->dxfer_len > TWA_MAX_IO_SIZE) {
275                                 twa_printf(sc, "I/O size %d too big.\n",
276                                                         csio->dxfer_len);
277                                 ccb_h->status = CAM_REQ_TOO_BIG;
278                                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
279                                         xpt_done(ccb);
280                                 return(1);
281                         }
282
283                         if ((tr->tr_length = csio->dxfer_len)) {
284                                 tr->tr_data = csio->data_ptr;
285                                 cmd9k->sgl_entries = 1;
286                         }
287                 } else {
288                         twa_printf(sc, "twa_execute_scsi: XPT_SCSI_IO: Got SGList!\n");
289                         ccb_h->status = CAM_REQ_CMP_ERR;
290                         if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
291                                 xpt_done(ccb);
292                         }
293                         return(1);
294                 }
295         } else {
296                 /* Data addresses are physical. */
297                 twa_printf(sc, "twa_execute_scsi: XPT_SCSI_IO: Physical data addresses!\n");
298                 ccb_h->status = CAM_REQ_CMP_ERR;
299                 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
300                         ccb_h->status |= CAM_RELEASE_SIMQ;
301                         ccb_h->status &= ~CAM_SIM_QUEUED;
302                         xpt_done(ccb);
303                 }
304                 return(1);
305         }
306
307         tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_9K;
308         /* twa_setup_data_dmamap will fill in the SGL, and submit the I/O. */
309         error = twa_map_request(tr);
310         return(error);
311 }
312
313
314
315 /*
316  * Function name:       twa_action
317  * Description:         Driver entry point for CAM's use.
318  *
319  * Input:               sim     -- sim corresponding to the ctlr
320  *                      ccb     -- ptr to CAM request
321  * Output:              None
322  * Return value:        None
323  */
324 void
325 twa_action(struct cam_sim *sim, union ccb *ccb)
326 {
327         struct twa_softc        *sc = (struct twa_softc *)cam_sim_softc(sim);
328         struct ccb_hdr          *ccb_h = &(ccb->ccb_h);
329
330         switch (ccb_h->func_code) {
331         case XPT_SCSI_IO:       /* SCSI I/O */
332         {
333                 struct twa_request      *tr;
334
335                 if ((sc->twa_state & TWA_STATE_SIMQ_FROZEN) ||
336                                 ((tr = twa_get_request(sc)) == NULL)) {
337                         twa_dbg_dprint(2, sc, "simq frozen/Cannot get request pkt.");
338                         /*
339                          * Freeze the simq to maintain ccb ordering.  The next
340                          * ccb that gets completed will unfreeze the simq.
341                          */
342                         twa_disallow_new_requests(sc);
343                         ccb_h->status |= CAM_REQUEUE_REQ;
344                         xpt_done(ccb);
345                         break;
346                 }
347                 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_EXTERNAL;
348                 tr->tr_private = ccb;
349                 tr->tr_callback = twa_complete_io;
350                 if (twa_execute_scsi(tr, ccb))
351                         twa_release_request(tr);
352                 break;
353         }
354
355         case XPT_ABORT:
356                 twa_dbg_dprint(2, sc, "Abort request");
357                 ccb_h->status = CAM_UA_ABORT;
358                 xpt_done(ccb);
359                 break;
360
361         case XPT_RESET_BUS:
362                 twa_printf(sc, "Reset Bus request from CAM...\n");
363                 if (twa_reset(sc)) {
364                         twa_printf(sc, "Reset Bus failed!\n");
365                         ccb_h->status = CAM_REQ_CMP_ERR;
366                 }
367                 else
368                         ccb_h->status = CAM_REQ_CMP;
369
370                 xpt_done(ccb);
371                 break;
372
373         case XPT_SET_TRAN_SETTINGS:
374                 twa_dbg_dprint(3, sc, "XPT_SET_TRAN_SETTINGS");
375
376                 /*
377                  * This command is not supported, since it's very specific
378                  * to SCSI, and we are doing ATA.
379                  */
380                 ccb_h->status = CAM_FUNC_NOTAVAIL;
381                 xpt_done(ccb);
382                 break;
383
384         case XPT_GET_TRAN_SETTINGS: 
385         {
386                 struct ccb_trans_settings       *cts = &ccb->cts;
387
388                 twa_dbg_dprint(3, sc, "XPT_GET_TRAN_SETTINGS");
389                 cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
390                 cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
391                 ccb_h->status = CAM_REQ_CMP;
392                 xpt_done(ccb);
393                 break;
394         }
395
396         case XPT_CALC_GEOMETRY:
397         {
398                 struct ccb_calc_geometry        *geom;
399
400                 twa_dbg_dprint(3, sc, "XPT_CALC_GEOMETRY request");
401                 geom = &ccb->ccg;
402
403                 if (geom->volume_size > 0x200000) /* 1 GB */ {
404                         geom->heads = 255;
405                         geom->secs_per_track = 63;
406                 } else {
407                         geom->heads = 64;
408                         geom->secs_per_track = 32;
409                 }
410                 geom->cylinders = geom->volume_size /
411                                         (geom->heads * geom->secs_per_track);
412                 ccb_h->status = CAM_REQ_CMP;
413                 xpt_done(ccb);
414                 break;
415         }
416
417         case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
418         {
419                 struct ccb_pathinq      *path_inq = &ccb->cpi;
420
421                 twa_dbg_dprint(3, sc, "XPT_PATH_INQ request");
422
423                 path_inq->version_num = 1;
424                 path_inq->hba_inquiry = 0;
425                 path_inq->target_sprt = 0;
426                 path_inq->hba_misc = 0;
427                 path_inq->hba_eng_cnt = 0;
428                 path_inq->max_target = TWA_MAX_UNITS;
429                 path_inq->max_lun = 0;
430                 path_inq->unit_number = cam_sim_unit(sim);
431                 path_inq->bus_id = cam_sim_bus(sim);
432                 path_inq->initiator_id = 12;
433                 path_inq->base_transfer_speed = 100000;
434                 strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
435                 strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
436                 strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
437                 ccb_h->status = CAM_REQ_CMP;
438                 xpt_done(ccb);
439                 break;
440         }
441
442         default:
443                 twa_dbg_dprint(3, sc, "func_code = %x", ccb_h->func_code);
444                 ccb_h->status = CAM_REQ_INVALID;
445                 xpt_done(ccb);
446                 break;
447         }
448 }
449
450
451
452 /*
453  * Function name:       twa_poll
454  * Description:         Driver entry point called when interrupts are not available.
455  *
456  * Input:               sim     -- sim corresponding to the controller
457  * Output:              None
458  * Return value:        None
459  */
460 void
461 twa_poll(struct cam_sim *sim)
462 {
463 #ifdef TWA_DEBUG
464         struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim);
465 #endif /* TWA_DEBUG */
466
467         twa_dbg_dprint(3, sc, "Entering sc = %p", sc);
468         twa_interrupt(cam_sim_softc(sim));
469         twa_dbg_dprint(3, sc, "Exiting sc = %p", sc);
470 }
471
472
473
474 /*
475  * Function name:       twa_async
476  * Description:         Driver entry point for CAM to notify driver of special
477  *                      events.  We don't use this for now.
478  *
479  * Input:               callback_arg    -- ptr to per ctlr structure
480  *                      code            -- code associated with the event
481  *                      path            -- cam path
482  *                      arg             -- 
483  * Output:              None
484  * Return value:        0       -- success
485  *                      non-zero-- failure
486  */
487 void
488 twa_async(void *callback_arg, u_int32_t code, 
489                         struct cam_path *path, void *arg)
490 {
491 #ifdef TWA_DEBUG
492         struct twa_softc *sc = (struct twa_softc *)callback_arg;
493 #endif /* TWA_DEBUG */
494
495         twa_dbg_dprint(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
496                                 sc, code, path, arg);
497 }
498
499
500
501 /*
502  * Function name:       twa_request_bus_scan
503  * Description:         Requests CAM for a scan of the bus.
504  *
505  * Input:               sc      -- ptr to per ctlr structure
506  * Output:              None
507  * Return value:        None
508  */
509 void
510 twa_request_bus_scan(struct twa_softc *sc)
511 {
512         struct cam_path *path;
513         union ccb       *ccb;
514
515         if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
516                 return;
517         bzero(ccb, sizeof(union ccb));
518         if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->twa_sim),
519                         CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
520                 return;
521
522         xpt_setup_ccb(&ccb->ccb_h, path, 5);
523         ccb->ccb_h.func_code = XPT_SCAN_BUS;
524         ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
525         ccb->crcn.flags = CAM_FLAG_NONE;
526         xpt_action(ccb);
527 }
528
529
530
531 /*
532  * Function name:       twa_bus_scan_cb
533  * Description:         Callback from CAM on a bus scan request.
534  *
535  * Input:               periph  -- we don't use this
536  *                      ccb     -- bus scan request ccb that we sent to CAM
537  * Output:              None
538  * Return value:        None
539  */
540 static void
541 twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
542 {
543         twa_dbg_print(3, "ccb = %p\n", ccb);
544         if (ccb->ccb_h.status != CAM_REQ_CMP)
545                 printf("cam_scan_callback: failure status = %x\n",
546                                         ccb->ccb_h.status);
547         else
548                 twa_dbg_print(3, "success");
549
550         xpt_free_path(ccb->ccb_h.path);
551         free(ccb, M_TEMP);
552 }
553
554
555
556 /*
557  * Function name:       twa_scsi_complete
558  * Description:         Called to complete CAM scsi requests.
559  *
560  * Input:               tr      -- ptr to request pkt to be completed
561  * Output:              None
562  * Return value:        None
563  */
564 void
565 twa_scsi_complete(struct twa_request *tr)
566 {
567         struct twa_softc                *sc = tr->tr_sc;
568         struct twa_command_header       *cmd_hdr = &(tr->tr_command->cmd_hdr);
569         struct twa_command_9k           *cmd = &(tr->tr_command->command.cmd_pkt_9k);
570         union ccb                       *ccb = (union ccb *)(tr->tr_private);
571         u_int16_t                       error;
572         u_int8_t                        *cdb;
573
574         if (tr->tr_error) {
575                 if (tr->tr_error == EBUSY)
576                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
577                 else if (tr->tr_error == EFBIG)
578                         ccb->ccb_h.status = CAM_REQ_TOO_BIG;
579                 else
580                         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
581         } else {
582                 if (cmd->status) {
583                         twa_dbg_dprint(1, sc, "req_id = 0x%x, status = 0x%x",
584                                                 cmd->request_id,
585                                                 cmd->status);
586
587                         error = cmd_hdr->status_block.error;
588                         if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
589                                         (error == TWA_ERROR_UNIT_OFFLINE)) {
590                                 twa_dbg_dprint(3, sc, "Unsupported unit. PTL = %x %x %x",
591                                                         ccb->ccb_h.path_id,
592                                                         ccb->ccb_h.target_id,
593                                                         ccb->ccb_h.target_lun);
594                                 ccb->ccb_h.status |= CAM_TID_INVALID;
595                         } else {
596                                 twa_dbg_dprint(2, sc, "cmd = %x %x %x %x %x %x %x",
597                                                 cmd->command.opcode,
598                                                 cmd->command.reserved,
599                                                 cmd->unit,
600                                                 cmd->request_id,
601                                                 cmd->status,
602                                                 cmd->sgl_offset,
603                                                 cmd->sgl_entries);
604
605                                 cdb = (u_int8_t *)(cmd->cdb);
606                                 twa_dbg_dprint(2, sc, "cdb = %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
607                                         cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7],
608                                         cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]);
609
610                                 cmd_hdr->err_specific_desc[sizeof(cmd_hdr->err_specific_desc) - 1] = '\0';
611                                 /* 
612                                  * Print the error. Firmware doesn't yet support
613                                  * the 'Mode Sense' cmd.  Don't print if the cmd
614                                  * is 'Mode Sense', and the error is 'Invalid field
615                                  * in CDB'.
616                                  */
617                                 if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
618                                         twa_printf(sc, "SCSI cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
619                                                 cdb[0],
620                                                 TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
621                                                 error,
622                                                 twa_find_msg_string(twa_error_table, error),
623                                                 cmd_hdr->err_specific_desc);
624                         }
625
626                         bcopy(cmd_hdr->sense_data, &(ccb->csio.sense_data),
627                                                 TWA_SENSE_DATA_LENGTH);
628                         ccb->csio.sense_len = TWA_SENSE_DATA_LENGTH;
629                         ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
630                 } else
631                         ccb->ccb_h.status = CAM_REQ_CMP;
632
633                 ccb->csio.scsi_status = cmd->status;
634                 /* If simq is frozen, unfreeze it. */
635                 if (sc->twa_state & TWA_STATE_SIMQ_FROZEN)
636                         twa_allow_new_requests(sc, (void *)ccb);
637         }
638
639         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
640         xpt_done(ccb);
641 }
642
643
644
645 /*
646  * Function name:       twa_drain_busy_queue
647  * Description:         This function gets called after a controller reset.
648  *                      It errors back to CAM, all those requests that were
649  *                      pending with the firmware, at the time of the reset.
650  *
651  * Input:               sc      -- ptr to per ctlr structure
652  * Output:              None
653  * Return value:        None
654  */
655 void
656 twa_drain_busy_queue(struct twa_softc *sc)
657 {
658         struct twa_request      *tr;
659         union ccb               *ccb;
660
661         /* Walk the busy queue. */
662         while ((tr = twa_dequeue_busy(sc))) {
663                 twa_unmap_request(tr);
664                 if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_INTERNAL) ||
665                         (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_IOCTL)) {
666                         /* It's an internal/ioctl request.  Simply free it. */
667                         if (tr->tr_data)
668                                 free(tr->tr_data, M_DEVBUF);
669                 } else {
670                         if ((ccb = tr->tr_private)) {
671                                 /* It's a SCSI request.  Complete it. */
672                                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET |
673                                                         CAM_RELEASE_SIMQ;
674                                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
675                                 xpt_done(ccb);
676                         }
677                 }
678                 twa_release_request(tr);
679         }
680 }
681
682
683
684 /*
685  * Function name:       twa_allow_new_requests
686  * Description:         Sets the appropriate status bits in a ccb such that,
687  *                      when the ccb is completed by a call to xpt_done,
688  *                      CAM knows that it's ok to unfreeze the flow of new
689  *                      requests to this controller, if the flow is frozen.
690  *
691  * Input:               sc      -- ptr to per ctlr structure
692  *                      ccb     -- ptr to CAM request
693  * Output:              None
694  * Return value:        None
695  */
696 void
697 twa_allow_new_requests(struct twa_softc *sc, void *ccb)
698 {
699         ((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
700         sc->twa_state &= ~TWA_STATE_SIMQ_FROZEN;
701 }
702
703
704
705 /*
706  * Function name:       twa_disallow_new_requests
707  * Description:         Calls the appropriate CAM function, so as to freeze
708  *                      the flow of new requests from CAM to this controller.
709  *
710  * Input:               sc      -- ptr to per ctlr structure
711  * Output:              None
712  * Return value:        None
713  */
714 void
715 twa_disallow_new_requests(struct twa_softc *sc)
716 {
717         xpt_freeze_simq(sc->twa_sim, 1);
718         sc->twa_state |= TWA_STATE_SIMQ_FROZEN;
719 }