1 /* $FreeBSD: src/sys/dev/mpt/mpt_freebsd.c,v 1.3.2.3 2002/09/24 21:37:25 mjacob Exp $ */
2 /* $DragonFly: src/sys/dev/disk/mpt/mpt_freebsd.c,v 1.7 2005/03/21 22:08:41 dillon Exp $ */
4 * FreeBSD/CAM specific routines for LSI '909 FC adapters.
7 * Copyright (c) 2000, 2001 by Greg Ansley
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice immediately at the beginning of the file, without modification,
14 * this list of conditions, and the following disclaimer.
15 * 2. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Additional Copyright (c) 2002 by Matthew Jacob under same license.
34 #include "mpt_freebsd.h"
36 static void mpt_poll(struct cam_sim *);
37 static timeout_t mpttimeout;
38 static timeout_t mpttimeout2;
39 static void mpt_action(struct cam_sim *, union ccb *);
40 static int mpt_setwidth(mpt_softc_t *, int, int);
41 static int mpt_setsync(mpt_softc_t *, int, int, int);
44 mpt_cam_attach(mpt_softc_t *mpt)
50 maxq = (mpt->mpt_global_credits < MPT_MAX_REQUESTS(mpt))?
51 mpt->mpt_global_credits : MPT_MAX_REQUESTS(mpt);
55 * Construct our SIM entry.
57 sim = cam_sim_alloc(mpt_action, mpt_poll, "mpt", mpt,
58 mpt->unit, 1, maxq, NULL);
63 * Register exactly the bus.
66 if (xpt_bus_register(sim, 0) != CAM_SUCCESS) {
71 if (xpt_create_path(&mpt->path, NULL, cam_sim_path(sim),
72 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
73 xpt_bus_deregister(cam_sim_path(sim));
81 mpt_cam_detach(mpt_softc_t *mpt)
83 if (mpt->sim != NULL) {
84 xpt_free_path(mpt->path);
85 xpt_bus_deregister(cam_sim_path(mpt->sim));
86 cam_sim_free(mpt->sim);
91 /* This routine is used after a system crash to dump core onto the
95 mpt_poll(struct cam_sim *sim)
97 mpt_softc_t *mpt = (mpt_softc_t *) cam_sim_softc(sim);
104 * This routine is called if the 9x9 does not return completion status
105 * for a command after a CAM specified time.
108 mpttimeout(void *arg)
111 union ccb *ccb = arg;
115 mpt = ccb->ccb_h.ccb_mpt_ptr;
117 req = ccb->ccb_h.ccb_req_ptr;
118 oseq = req->sequence;
121 if (req->sequence != oseq) {
122 device_printf(mpt->dev, "bullet missed in timeout\n");
126 device_printf(mpt->dev, "bullet U-turned in timeout: got us\n");
128 device_printf(mpt->dev,
129 "time out on request index = 0x%02x sequence = 0x%08x\n",
130 req->index, req->sequence);
131 mpt_check_doorbell(mpt);
132 device_printf(mpt->dev, "Status %08X; Mask %08X; Doorbell %08X\n",
133 mpt_read(mpt, MPT_OFFSET_INTR_STATUS),
134 mpt_read(mpt, MPT_OFFSET_INTR_MASK),
135 mpt_read(mpt, MPT_OFFSET_DOORBELL) );
136 printf("request state %s\n", mpt_req_state(req->debug));
137 if (ccb != req->ccb) {
138 printf("time out: ccb %p != req->ccb %p\n",
141 mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);
142 req->debug = REQ_TIMEOUT;
144 req->link.sle_next = (void *) mpt;
145 callout_reset(&req->timeout, hz / 10, mpttimeout2, req);
146 ccb->ccb_h.status = CAM_CMD_TIMEOUT;
147 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
149 MPTLOCK_2_CAMLOCK(mpt);
151 CAMLOCK_2_MPTLOCK(mpt);
156 mpttimeout2(void *arg)
158 request_t *req = arg;
159 if (req->debug == REQ_TIMEOUT) {
160 mpt_softc_t *mpt = (mpt_softc_t *) req->link.sle_next;
162 mpt_free_request(mpt, req);
168 * Callback routine from "bus_dmamap_load" or in simple case called directly.
170 * Takes a list of physical segments and builds the SGL for SCSI IO command
171 * and forwards the commard to the IOC after one last check that CAM has not
172 * aborted the transaction.
175 mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
180 MSG_SCSI_IO_REQUEST *mpt_req;
183 req = (request_t *)arg;
186 mpt = ccb->ccb_h.ccb_mpt_ptr;
187 req = ccb->ccb_h.ccb_req_ptr;
188 mpt_req = req->req_vbuf;
190 if (error == 0 && nseg > MPT_SGL_MAX) {
196 device_printf(mpt->dev, "bus_dmamap_load returned %d\n",
198 if (ccb->ccb_h.status == CAM_REQ_INPROG) {
199 xpt_freeze_devq(ccb->ccb_h.path, 1);
200 ccb->ccb_h.status = CAM_DEV_QFRZN;
202 ccb->ccb_h.status |= CAM_REQ_TOO_BIG;
204 ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
206 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
208 CAMLOCK_2_MPTLOCK(mpt);
209 mpt_free_request(mpt, req);
210 MPTLOCK_2_CAMLOCK(mpt);
214 if (nseg > MPT_NSGL_FIRST(mpt)) {
220 mpt_req->DataLength = ccb->csio.dxfer_len;
221 flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT;
222 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
223 flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
225 se = (SGE_SIMPLE32 *) &mpt_req->SGL;
226 for (i = 0; i < MPT_NSGL_FIRST(mpt) - 1; i++, se++, dm_segs++) {
229 bzero(se, sizeof (*se));
230 se->Address = dm_segs->ds_addr;
231 MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
233 if (i == MPT_NSGL_FIRST(mpt) - 2) {
234 tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
236 MPI_pSGE_SET_FLAGS(se, tf);
241 * Tell the IOC where to find the first chain element
243 mpt_req->ChainOffset = ((char *)se - (char *)mpt_req) >> 2;
246 * Until we're finished with all segments...
251 * Construct the chain element that point to the
254 ce = (SGE_CHAIN32 *) se++;
255 if (nleft > MPT_NSGL(mpt)) {
256 ntodo = MPT_NSGL(mpt) - 1;
257 ce->NextChainOffset = (MPT_RQSL(mpt) -
258 sizeof (SGE_SIMPLE32)) >> 2;
259 ce->Length = MPT_NSGL(mpt)
260 * sizeof(SGE_SIMPLE32);
263 ce->NextChainOffset = 0;
264 ce->Length = ntodo * sizeof (SGE_SIMPLE32);
266 ce->Address = req->req_pbuf +
267 ((char *)se - (char *)mpt_req);
268 ce->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
269 for (i = 0; i < ntodo; i++, se++, dm_segs++) {
272 bzero(se, sizeof (*se));
273 se->Address = dm_segs->ds_addr;
274 MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
276 if (i == ntodo - 1) {
277 tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
278 if (ce->NextChainOffset == 0) {
280 MPI_SGE_FLAGS_END_OF_LIST |
281 MPI_SGE_FLAGS_END_OF_BUFFER;
284 MPI_pSGE_SET_FLAGS(se, tf);
290 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
291 op = BUS_DMASYNC_PREREAD;
293 op = BUS_DMASYNC_PREWRITE;
294 if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) {
295 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
297 } else if (nseg > 0) {
302 mpt_req->DataLength = ccb->csio.dxfer_len;
303 flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT;
304 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
305 flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
307 /* Copy the segments into our SG list */
308 se = (SGE_SIMPLE32 *) &mpt_req->SGL;
309 for (i = 0; i < nseg; i++, se++, dm_segs++) {
312 bzero(se, sizeof (*se));
313 se->Address = dm_segs->ds_addr;
314 MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
318 MPI_SGE_FLAGS_LAST_ELEMENT |
319 MPI_SGE_FLAGS_END_OF_BUFFER |
320 MPI_SGE_FLAGS_END_OF_LIST;
322 MPI_pSGE_SET_FLAGS(se, tf);
325 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
326 op = BUS_DMASYNC_PREREAD;
328 op = BUS_DMASYNC_PREWRITE;
329 if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) {
330 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
333 se = (SGE_SIMPLE32 *) &mpt_req->SGL;
335 * No data to transfer so we just make a single simple SGL
338 MPI_pSGE_SET_FLAGS(se,
339 (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
340 MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
344 * Last time we need to check if this CCB needs to be aborted.
346 if (ccb->ccb_h.status != CAM_REQ_INPROG) {
347 if (nseg && (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0)
348 bus_dmamap_unload(mpt->buffer_dmat, req->dmap);
349 CAMLOCK_2_MPTLOCK(mpt);
350 mpt_free_request(mpt, req);
351 MPTLOCK_2_CAMLOCK(mpt);
356 ccb->ccb_h.status |= CAM_SIM_QUEUED;
357 MPTLOCK_2_CAMLOCK(mpt);
358 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
359 callout_reset(&ccb->ccb_h.timeout_ch,
360 (ccb->ccb_h.timeout * hz) / 1000, mpttimeout, ccb);
362 if (mpt->verbose > 1)
363 mpt_print_scsi_io_request(mpt_req);
364 mpt_send_cmd(mpt, req);
365 MPTLOCK_2_CAMLOCK(mpt);
369 mpt_start(union ccb *ccb)
372 struct mpt_softc *mpt;
373 MSG_SCSI_IO_REQUEST *mpt_req;
374 struct ccb_scsiio *csio = &ccb->csio;
375 struct ccb_hdr *ccbh = &ccb->ccb_h;
377 /* Get the pointer for the physical addapter */
378 mpt = ccb->ccb_h.ccb_mpt_ptr;
380 CAMLOCK_2_MPTLOCK(mpt);
381 /* Get a request structure off the free list */
382 if ((req = mpt_get_request(mpt)) == NULL) {
383 if (mpt->outofbeer == 0) {
385 xpt_freeze_simq(mpt->sim, 1);
386 if (mpt->verbose > 1) {
387 device_printf(mpt->dev, "FREEZEQ\n");
390 MPTLOCK_2_CAMLOCK(mpt);
391 ccb->ccb_h.status = CAM_REQUEUE_REQ;
395 MPTLOCK_2_CAMLOCK(mpt);
397 /* Link the ccb and the request structure so we can find */
398 /* the other knowing either the request or the ccb */
400 ccb->ccb_h.ccb_req_ptr = req;
402 /* Now we build the command for the IOC */
403 mpt_req = req->req_vbuf;
404 bzero(mpt_req, sizeof *mpt_req);
406 mpt_req->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
407 mpt_req->Bus = mpt->bus;
409 mpt_req->SenseBufferLength =
410 (csio->sense_len < MPT_SENSE_SIZE) ?
411 csio->sense_len : MPT_SENSE_SIZE;
413 /* We use the message context to find the request structure when we */
414 /* Get the command competion interrupt from the FC IOC. */
415 mpt_req->MsgContext = req->index;
417 /* Which physical device to do the I/O on */
418 mpt_req->TargetID = ccb->ccb_h.target_id;
419 mpt_req->LUN[1] = ccb->ccb_h.target_lun;
421 /* Set the direction of the transfer */
422 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
423 mpt_req->Control = MPI_SCSIIO_CONTROL_READ;
424 else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
425 mpt_req->Control = MPI_SCSIIO_CONTROL_WRITE;
427 mpt_req->Control = MPI_SCSIIO_CONTROL_NODATATRANSFER;
429 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) {
430 switch(ccb->csio.tag_action) {
431 case MSG_HEAD_OF_Q_TAG:
432 mpt_req->Control |= MPI_SCSIIO_CONTROL_HEADOFQ;
435 mpt_req->Control |= MPI_SCSIIO_CONTROL_ACAQ;
437 case MSG_ORDERED_Q_TAG:
438 mpt_req->Control |= MPI_SCSIIO_CONTROL_ORDEREDQ;
440 case MSG_SIMPLE_Q_TAG:
442 mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
447 mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
449 mpt_req->Control |= MPI_SCSIIO_CONTROL_UNTAGGED;
452 if (mpt->is_fc == 0) {
453 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
454 mpt_req->Control |= MPI_SCSIIO_CONTROL_NO_DISCONNECT;
458 /* Copy the scsi command block into place */
459 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0)
460 bcopy(csio->cdb_io.cdb_ptr, mpt_req->CDB, csio->cdb_len);
462 bcopy(csio->cdb_io.cdb_bytes, mpt_req->CDB, csio->cdb_len);
464 mpt_req->CDBLength = csio->cdb_len;
465 mpt_req->DataLength = csio->dxfer_len;
466 mpt_req->SenseBufferLowAddr = req->sense_pbuf;
469 * If we have any data to send with this command,
470 * map it into bus space.
473 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
474 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {
476 * We've been given a pointer to a single buffer.
478 if ((ccbh->flags & CAM_DATA_PHYS) == 0) {
480 * Virtual address that needs to translated into
481 * one or more physical pages.
485 error = bus_dmamap_load(mpt->buffer_dmat,
486 req->dmap, csio->data_ptr, csio->dxfer_len,
487 mpt_execute_req, req, 0);
488 if (error == EINPROGRESS) {
490 * So as to maintain ordering,
491 * freeze the controller queue
492 * until our mapping is
495 xpt_freeze_simq(mpt->sim, 1);
496 ccbh->status |= CAM_RELEASE_SIMQ;
500 * We have been given a pointer to single
503 struct bus_dma_segment seg;
504 seg.ds_addr = (bus_addr_t)csio->data_ptr;
505 seg.ds_len = csio->dxfer_len;
506 mpt_execute_req(req, &seg, 1, 0);
510 * We have been given a list of addresses.
511 * These case could be easily done but they are not
512 * currently generated by the CAM subsystem so there
513 * is no point in wasting the time right now.
515 struct bus_dma_segment *segs;
516 if ((ccbh->flags & CAM_SG_LIST_PHYS) == 0) {
517 mpt_execute_req(req, NULL, 0, EFAULT);
519 /* Just use the segments provided */
520 segs = (struct bus_dma_segment *)csio->data_ptr;
521 mpt_execute_req(req, segs, csio->sglist_cnt,
522 (csio->sglist_cnt < MPT_SGL_MAX)?
527 mpt_execute_req(req, NULL, 0, 0);
532 mpt_bus_reset(union ccb *ccb)
537 MSG_SCSI_TASK_MGMT *reset_req;
539 /* Get the pointer for the physical adapter */
540 mpt = ccb->ccb_h.ccb_mpt_ptr;
542 /* Get a request structure off the free list */
543 if ((req = mpt_get_request(mpt)) == NULL) {
544 return (CAM_REQUEUE_REQ);
547 /* Link the ccb and the request structure so we can find */
548 /* the other knowing either the request or the ccb */
550 ccb->ccb_h.ccb_req_ptr = req;
552 reset_req = req->req_vbuf;
553 bzero(reset_req, sizeof *reset_req);
555 reset_req->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
556 reset_req->MsgContext = req->index;
557 reset_req->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
560 * Should really be TARGET_RESET_OPTION
562 reset_req->MsgFlags =
563 MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION;
565 /* Which physical device Reset */
566 reset_req->TargetID = ccb->ccb_h.target_id;
567 reset_req->LUN[1] = ccb->ccb_h.target_lun;
569 ccb->ccb_h.status |= CAM_SIM_QUEUED;
571 error = mpt_send_handshake_cmd(mpt,
572 sizeof (MSG_SCSI_TASK_MGMT), reset_req);
574 device_printf(mpt->dev,
575 "mpt_bus_reset: mpt_send_handshake return %d\n", error);
576 return (CAM_REQ_CMP_ERR);
578 return (CAM_REQ_CMP);
583 * Process an asynchronous event from the IOC.
585 static void mpt_ctlop(mpt_softc_t *, void *, u_int32_t);
586 static void mpt_event_notify_reply(mpt_softc_t *mpt, MSG_EVENT_NOTIFY_REPLY *);
589 mpt_ctlop(mpt_softc_t *mpt, void *vmsg, u_int32_t reply)
591 MSG_DEFAULT_REPLY *dmsg = vmsg;
593 if (dmsg->Function == MPI_FUNCTION_EVENT_NOTIFICATION) {
594 mpt_event_notify_reply(mpt, vmsg);
595 mpt_free_reply(mpt, (reply << 1));
596 } else if (dmsg->Function == MPI_FUNCTION_EVENT_ACK) {
597 mpt_free_reply(mpt, (reply << 1));
598 } else if (dmsg->Function == MPI_FUNCTION_PORT_ENABLE) {
599 MSG_PORT_ENABLE_REPLY *msg = vmsg;
600 int index = msg->MsgContext & ~0x80000000;
601 if (mpt->verbose > 1) {
602 device_printf(mpt->dev, "enable port reply idx %d\n",
605 if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) {
606 request_t *req = &mpt->request_pool[index];
607 req->debug = REQ_DONE;
609 mpt_free_reply(mpt, (reply << 1));
610 } else if (dmsg->Function == MPI_FUNCTION_CONFIG) {
611 MSG_CONFIG_REPLY *msg = vmsg;
612 int index = msg->MsgContext & ~0x80000000;
613 if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) {
614 request_t *req = &mpt->request_pool[index];
615 req->debug = REQ_DONE;
616 req->sequence = reply;
618 mpt_free_reply(mpt, (reply << 1));
621 device_printf(mpt->dev, "unknown mpt_ctlop: %x\n",
627 mpt_event_notify_reply(mpt_softc_t *mpt, MSG_EVENT_NOTIFY_REPLY *msg)
630 case MPI_EVENT_LOG_DATA:
631 /* Some error occured that LSI wants logged */
632 device_printf(mpt->dev,
633 "\tEvtLogData: IOCLogInfo: 0x%08x\n",
635 device_printf(mpt->dev, "\tEvtLogData: Event Data:");
638 for (i = 0; i < msg->EventDataLength; i++) {
639 device_printf(mpt->dev,
640 " %08X", msg->Data[i]);
643 device_printf(mpt->dev, "\n");
646 case MPI_EVENT_UNIT_ATTENTION:
647 device_printf(mpt->dev,
648 "Bus: 0x%02x TargetID: 0x%02x\n",
649 (msg->Data[0] >> 8) & 0xff, msg->Data[0] & 0xff);
652 case MPI_EVENT_IOC_BUS_RESET:
653 /* We generated a bus reset */
654 device_printf(mpt->dev, "IOC Bus Reset Port: %d\n",
655 (msg->Data[0] >> 8) & 0xff);
658 case MPI_EVENT_EXT_BUS_RESET:
659 /* Someone else generated a bus reset */
660 device_printf(mpt->dev, "Ext Bus Reset\n");
662 * These replies don't return EventData like the MPI
665 /* xpt_async(AC_BUS_RESET, path, NULL); */
668 case MPI_EVENT_RESCAN:
670 * In general this means a device has been added
673 device_printf(mpt->dev,
674 "Rescan Port: %d\n", (msg->Data[0] >> 8) & 0xff);
675 /* xpt_async(AC_FOUND_DEVICE, path, NULL); */
678 case MPI_EVENT_LINK_STATUS_CHANGE:
679 device_printf(mpt->dev, "Port %d: LinkState: %s\n",
680 (msg->Data[1] >> 8) & 0xff,
681 ((msg->Data[0] & 0xff) == 0)? "Failed" : "Active");
684 case MPI_EVENT_LOOP_STATE_CHANGE:
685 switch ((msg->Data[0] >> 16) & 0xff) {
687 device_printf(mpt->dev,
688 "Port 0x%x: FC LinkEvent: LIP(%02X,%02X) (Loop Initialization)\n",
689 (msg->Data[1] >> 8) & 0xff,
690 (msg->Data[0] >> 8) & 0xff,
691 (msg->Data[0] ) & 0xff);
692 switch ((msg->Data[0] >> 8) & 0xff) {
694 if ((msg->Data[0] & 0xff) == 0xF7) {
695 printf("Device needs AL_PA\n");
697 printf("Device %02X doesn't like FC performance\n",
698 msg->Data[0] & 0xFF);
702 if ((msg->Data[0] & 0xff) == 0xF7) {
703 printf("Device had loop failure at its receiver prior to acquiring AL_PA\n");
705 printf("Device %02X detected loop failure at its receiver\n",
706 msg->Data[0] & 0xFF);
710 printf("Device %02X requests that device %02X reset itself\n",
712 (msg->Data[0] >> 8) & 0xFF);
717 device_printf(mpt->dev, "Port 0x%x: FC LinkEvent: LPE(%02X,%02X) (Loop Port Enable)\n",
718 (msg->Data[1] >> 8) & 0xff, /* Port */
719 (msg->Data[0] >> 8) & 0xff, /* Character 3 */
720 (msg->Data[0] ) & 0xff /* Character 4 */
724 device_printf(mpt->dev, "Port 0x%x: FC LinkEvent: LPB(%02X,%02X) (Loop Port Bypass)\n",
725 (msg->Data[1] >> 8) & 0xff, /* Port */
726 (msg->Data[0] >> 8) & 0xff, /* Character 3 */
727 (msg->Data[0] ) & 0xff /* Character 4 */
731 device_printf(mpt->dev, "Port 0x%x: FC LinkEvent: Unknown FC event (%02X %02X %02X)\n",
732 (msg->Data[1] >> 8) & 0xff, /* Port */
733 (msg->Data[0] >> 16) & 0xff, /* Event */
734 (msg->Data[0] >> 8) & 0xff, /* Character 3 */
735 (msg->Data[0] ) & 0xff /* Character 4 */
740 case MPI_EVENT_LOGOUT:
741 device_printf(mpt->dev, "FC Logout Port: %d N_PortID: %02X\n",
742 (msg->Data[1] >> 8) & 0xff,
745 case MPI_EVENT_EVENT_CHANGE:
746 /* This is just an acknowledgement of our
747 mpt_send_event_request */
750 device_printf(mpt->dev, "Unknown event %X\n", msg->Event);
752 if (msg->AckRequired) {
755 if ((req = mpt_get_request(mpt)) == NULL) {
756 panic("unable to get request to acknowledge notify");
758 ackp = (MSG_EVENT_ACK *) req->req_vbuf;
759 bzero(ackp, sizeof *ackp);
760 ackp->Function = MPI_FUNCTION_EVENT_ACK;
761 ackp->Event = msg->Event;
762 ackp->EventContext = msg->EventContext;
763 ackp->MsgContext = req->index | 0x80000000;
764 mpt_check_doorbell(mpt);
765 mpt_send_cmd(mpt, req);
770 mpt_done(mpt_softc_t *mpt, u_int32_t reply)
775 MSG_REQUEST_HEADER *mpt_req;
776 MSG_SCSI_IO_REPLY *mpt_reply;
778 index = -1; /* Shutup the complier */
780 if ((reply & MPT_CONTEXT_REPLY) == 0) {
783 index = reply & MPT_CONTEXT_MASK;
787 bus_dmamap_sync(mpt->reply_dmat, mpt->reply_dmap,
788 BUS_DMASYNC_POSTREAD);
789 /* address reply (Error) */
790 mpt_reply = MPT_REPLY_PTOV(mpt, reply);
791 if (mpt->verbose > 1) {
792 pReply = (unsigned *) mpt_reply;
793 device_printf(mpt->dev, "Address Reply (index %u)\n",
794 mpt_reply->MsgContext & 0xffff);
795 device_printf(mpt->dev, "%08X %08X %08X %08X\n",
796 pReply[0], pReply[1], pReply[2], pReply[3]);
797 device_printf(mpt->dev, "%08X %08X %08X %08X\n",
798 pReply[4], pReply[5], pReply[6], pReply[7]);
799 device_printf(mpt->dev, "%08X %08X %08X %08X\n\n",
800 pReply[8], pReply[9], pReply[10], pReply[11]);
802 index = mpt_reply->MsgContext;
806 * Address reply with MessageContext high bit set
807 * This is most likely a notify message so we try
808 * to process it then free it
810 if ((index & 0x80000000) != 0) {
811 if (mpt_reply != NULL) {
812 mpt_ctlop(mpt, mpt_reply, reply);
814 device_printf(mpt->dev,
815 "mpt_done: index 0x%x, NULL reply\n", index);
820 /* Did we end up with a valid index into the table? */
821 if (index < 0 || index >= MPT_MAX_REQUESTS(mpt)) {
822 printf("mpt_done: invalid index (%x) in reply\n", index);
826 req = &mpt->request_pool[index];
828 /* Make sure memory hasn't been trashed */
829 if (req->index != index) {
830 printf("mpt_done: corrupted request struct");
834 /* Short cut for task management replys; nothing more for us to do */
835 mpt_req = req->req_vbuf;
836 if (mpt_req->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
837 if (mpt->verbose > 1) {
838 device_printf(mpt->dev, "mpt_done: TASK MGMT\n");
843 if (mpt_req->Function == MPI_FUNCTION_PORT_ENABLE) {
848 * At this point it better be a SCSI IO command, but don't
851 if (mpt_req->Function != MPI_FUNCTION_SCSI_IO_REQUEST) {
855 /* Recover the CAM control block from the request structure */
858 /* Can't have had a SCSI command with out a CAM control block */
859 if (ccb == NULL || (ccb->ccb_h.status & CAM_SIM_QUEUED) == 0) {
860 device_printf(mpt->dev,
861 "mpt_done: corrupted ccb, index = 0x%02x seq = 0x%08x",
862 req->index, req->sequence);
863 printf(" request state %s\nmpt_request:\n",
864 mpt_req_state(req->debug));
865 mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);
867 if (mpt_reply != NULL) {
868 printf("\nmpt_done: reply:\n");
869 mpt_print_reply(MPT_REPLY_PTOV(mpt, reply));
871 printf("\nmpt_done: context reply: 0x%08x\n", reply);
876 callout_stop(&ccb->ccb_h.timeout_ch);
878 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
881 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
882 op = BUS_DMASYNC_POSTREAD;
884 op = BUS_DMASYNC_POSTWRITE;
886 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
887 bus_dmamap_unload(mpt->buffer_dmat, req->dmap);
891 if (mpt_reply == NULL) {
892 /* Context reply; report that the command was successfull */
893 ccb->ccb_h.status = CAM_REQ_CMP;
894 ccb->csio.scsi_status = SCSI_STATUS_OK;
895 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
896 if (mpt->outofbeer) {
897 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
899 if (mpt->verbose > 1) {
900 device_printf(mpt->dev, "THAWQ\n");
903 MPTLOCK_2_CAMLOCK(mpt);
905 CAMLOCK_2_MPTLOCK(mpt);
909 ccb->csio.scsi_status = mpt_reply->SCSIStatus;
910 switch(mpt_reply->IOCStatus) {
911 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
912 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
915 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
917 * Yikes, Tagged queue full comes through this path!
919 * So we'll change it to a status error and anything
920 * that returns status should probably be a status
924 ccb->csio.dxfer_len - mpt_reply->TransferCount;
925 if (mpt_reply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) {
926 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
930 device_printf(mpt->dev, "underrun, scsi status is %x\n", ccb->csio.scsi_status);
931 ccb->csio.scsi_status = SCSI_STATUS_QUEUE_FULL;
934 case MPI_IOCSTATUS_SUCCESS:
935 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:
936 switch (ccb->csio.scsi_status) {
938 ccb->ccb_h.status = CAM_REQ_CMP;
941 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
945 case MPI_IOCSTATUS_BUSY:
946 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
947 ccb->ccb_h.status = CAM_BUSY;
950 case MPI_IOCSTATUS_SCSI_INVALID_BUS:
951 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
952 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
953 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
956 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
957 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
960 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:
961 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:
962 ccb->ccb_h.status = CAM_UNCOR_PARITY;
965 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
966 ccb->ccb_h.status = CAM_REQ_CMP;
969 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
970 ccb->ccb_h.status = CAM_UA_TERMIO;
973 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
974 ccb->ccb_h.status = CAM_REQ_TERMIO;
977 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
978 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
982 ccb->ccb_h.status = CAM_UNREC_HBA_ERROR;
986 if ((mpt_reply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) != 0) {
987 if (ccb->ccb_h.flags & (CAM_SENSE_PHYS | CAM_SENSE_PTR)) {
988 ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
990 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
991 ccb->csio.sense_resid = mpt_reply->SenseCount;
992 bcopy(req->sense_vbuf, &ccb->csio.sense_data,
993 ccb->csio.sense_len);
995 } else if (mpt_reply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
996 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
997 ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
1000 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1001 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1002 ccb->ccb_h.status |= CAM_DEV_QFRZN;
1003 xpt_freeze_devq(ccb->ccb_h.path, 1);
1008 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1009 if (mpt->outofbeer) {
1010 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1012 if (mpt->verbose > 1) {
1013 device_printf(mpt->dev, "THAWQ\n");
1016 MPTLOCK_2_CAMLOCK(mpt);
1018 CAMLOCK_2_MPTLOCK(mpt);
1021 /* If IOC done with this request free it up */
1022 if (mpt_reply == NULL || (mpt_reply->MsgFlags & 0x80) == 0)
1023 mpt_free_request(mpt, req);
1025 /* If address reply; give the buffer back to the IOC */
1026 if (mpt_reply != NULL)
1027 mpt_free_reply(mpt, (reply << 1));
1031 mpt_action(struct cam_sim *sim, union ccb *ccb)
1035 struct ccb_trans_settings *cts;
1037 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mpt_action\n"));
1039 mpt = (mpt_softc_t *)cam_sim_softc(sim);
1041 ccb->ccb_h.ccb_mpt_ptr = mpt;
1043 switch (ccb->ccb_h.func_code) {
1045 if (mpt->verbose > 1)
1046 device_printf(mpt->dev, "XPT_RESET_BUS\n");
1047 CAMLOCK_2_MPTLOCK(mpt);
1048 error = mpt_bus_reset(ccb);
1050 case CAM_REQ_INPROG:
1051 MPTLOCK_2_CAMLOCK(mpt);
1053 case CAM_REQUEUE_REQ:
1054 if (mpt->outofbeer == 0) {
1056 xpt_freeze_simq(sim, 1);
1057 if (mpt->verbose > 1) {
1058 device_printf(mpt->dev, "FREEZEQ\n");
1061 ccb->ccb_h.status = CAM_REQUEUE_REQ;
1062 MPTLOCK_2_CAMLOCK(mpt);
1067 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1068 ccb->ccb_h.status |= CAM_REQ_CMP;
1069 if (mpt->outofbeer) {
1070 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1072 if (mpt->verbose > 1) {
1073 device_printf(mpt->dev, "THAWQ\n");
1076 MPTLOCK_2_CAMLOCK(mpt);
1081 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1082 MPTLOCK_2_CAMLOCK(mpt);
1087 case XPT_SCSI_IO: /* Execute the requested I/O operation */
1089 * Do a couple of preliminary checks...
1091 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1092 if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
1093 ccb->ccb_h.status = CAM_REQ_INVALID;
1098 /* Max supported CDB length is 16 bytes */
1099 if (ccb->csio.cdb_len >
1100 sizeof (((PTR_MSG_SCSI_IO_REQUEST)0)->CDB)) {
1101 ccb->ccb_h.status = CAM_REQ_INVALID;
1105 ccb->csio.scsi_status = SCSI_STATUS_OK;
1111 * XXX: Need to implement
1113 ccb->ccb_h.status = CAM_UA_ABORT;
1117 #ifdef CAM_NEW_TRAN_CODE
1118 #define IS_CURRENT_SETTINGS(c) (c->type == CTS_TYPE_CURRENT_SETTINGS)
1120 #define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS)
1122 #define DP_DISC_ENABLE 0x1
1123 #define DP_DISC_DISABL 0x2
1124 #define DP_DISC (DP_DISC_ENABLE|DP_DISC_DISABL)
1126 #define DP_TQING_ENABLE 0x4
1127 #define DP_TQING_DISABL 0x8
1128 #define DP_TQING (DP_TQING_ENABLE|DP_TQING_DISABL)
1130 #define DP_WIDE 0x10
1131 #define DP_NARROW 0x20
1132 #define DP_WIDTH (DP_WIDE|DP_NARROW)
1134 #define DP_SYNC 0x40
1136 case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */
1138 if (!IS_CURRENT_SETTINGS(cts)) {
1139 ccb->ccb_h.status = CAM_REQ_INVALID;
1143 tgt = cts->ccb_h.target_id;
1144 if (mpt->is_fc == 0) {
1146 u_int period = 0, offset = 0;
1147 #ifndef CAM_NEW_TRAN_CODE
1148 if (cts->valid & CCB_TRANS_DISC_VALID) {
1149 dval |= DP_DISC_ENABLE;
1151 if (cts->valid & CCB_TRANS_TQ_VALID) {
1152 dval |= DP_TQING_ENABLE;
1154 if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
1161 * Any SYNC RATE of nonzero and SYNC_OFFSET
1162 * of nonzero will cause us to go to the
1163 * selected (from NVRAM) maximum value for
1164 * this device. At a later point, we'll
1165 * allow finer control.
1167 if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
1168 (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)) {
1170 period = cts->sync_period;
1171 offset = cts->sync_offset;
1174 struct ccb_trans_settings_scsi *scsi =
1175 &cts->proto_specific.scsi;
1176 struct ccb_trans_settings_spi *spi =
1177 &cts->xport_specific.spi;
1179 if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
1180 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
1181 dval |= DP_DISC_ENABLE;
1183 dval |= DP_DISC_DISABL;
1186 if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
1187 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
1188 dval |= DP_TQING_ENABLE;
1190 dval |= DP_TQING_DISABL;
1193 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1194 if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT)
1200 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) &&
1201 (spi->valid & CTS_SPI_VALID_SYNC_RATE) &&
1202 (spi->sync_period && spi->sync_offset)) {
1204 period = spi->sync_period;
1205 offset = spi->sync_offset;
1208 CAMLOCK_2_MPTLOCK(mpt);
1209 if (dval & DP_DISC_ENABLE) {
1210 mpt->mpt_disc_enable |= (1 << tgt);
1211 } else if (dval & DP_DISC_DISABL) {
1212 mpt->mpt_disc_enable &= ~(1 << tgt);
1214 if (dval & DP_TQING_ENABLE) {
1215 mpt->mpt_tag_enable |= (1 << tgt);
1216 } else if (dval & DP_TQING_DISABL) {
1217 mpt->mpt_tag_enable &= ~(1 << tgt);
1219 if (dval & DP_WIDTH) {
1220 if (mpt_setwidth(mpt, tgt, dval & DP_WIDE)) {
1221 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1222 MPTLOCK_2_CAMLOCK(mpt);
1227 if (dval & DP_SYNC) {
1228 if (mpt_setsync(mpt, tgt, period, offset)) {
1229 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1230 MPTLOCK_2_CAMLOCK(mpt);
1235 MPTLOCK_2_CAMLOCK(mpt);
1236 if (mpt->verbose > 1) {
1237 device_printf(mpt->dev,
1238 "SET tgt %d flags %x period %x off %x\n",
1239 tgt, dval, period, offset);
1242 ccb->ccb_h.status = CAM_REQ_CMP;
1246 case XPT_GET_TRAN_SETTINGS:
1248 tgt = cts->ccb_h.target_id;
1250 #ifndef CAM_NEW_TRAN_CODE
1252 * a lot of normal SCSI things don't make sense.
1254 cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
1255 cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
1257 * How do you measure the width of a high
1258 * speed serial bus? Well, in bytes.
1260 * Offset and period make no sense, though, so we set
1261 * (above) a 'base' transfer speed to be gigabit.
1263 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1265 struct ccb_trans_settings_fc *fc =
1266 &cts->xport_specific.fc;
1268 cts->protocol = PROTO_SCSI;
1269 cts->protocol_version = SCSI_REV_2;
1270 cts->transport = XPORT_FC;
1271 cts->transport_version = 0;
1273 fc->valid = CTS_FC_VALID_SPEED;
1274 fc->bitrate = 100000; /* XXX: Need for 2Gb/s */
1275 /* XXX: need a port database for each target */
1278 #ifdef CAM_NEW_TRAN_CODE
1279 struct ccb_trans_settings_scsi *scsi =
1280 &cts->proto_specific.scsi;
1281 struct ccb_trans_settings_spi *spi =
1282 &cts->xport_specific.spi;
1284 u_int8_t dval, pval, oval;
1287 * We aren't going off of Port PAGE2 params for
1288 * tagged queuing or disconnect capabilities
1289 * for current settings. For goal settings,
1290 * we assert all capabilities- we've had some
1291 * problems with reading NVRAM data.
1293 if (IS_CURRENT_SETTINGS(cts)) {
1294 fCONFIG_PAGE_SCSI_DEVICE_0 tmp;
1297 tmp = mpt->mpt_dev_page0[tgt];
1298 CAMLOCK_2_MPTLOCK(mpt);
1299 if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) {
1300 device_printf(mpt->dev,
1301 "cannot get target %d DP0\n", tgt);
1303 if (mpt->verbose > 1) {
1304 device_printf(mpt->dev,
1305 "SPI Tgt %d Page 0: NParms %x Information %x\n",
1307 tmp.NegotiatedParameters,
1311 MPTLOCK_2_CAMLOCK(mpt);
1313 if (tmp.NegotiatedParameters &
1314 MPI_SCSIDEVPAGE0_NP_WIDE)
1317 if (mpt->mpt_disc_enable & (1 << tgt)) {
1318 dval |= DP_DISC_ENABLE;
1320 if (mpt->mpt_tag_enable & (1 << tgt)) {
1321 dval |= DP_TQING_ENABLE;
1323 oval = (tmp.NegotiatedParameters >> 16) & 0xff;
1324 pval = (tmp.NegotiatedParameters >> 8) & 0xff;
1327 * XXX: Fix wrt NVRAM someday. Attempts
1328 * XXX: to read port page2 device data
1329 * XXX: just returns zero in these areas.
1331 dval = DP_WIDE|DP_DISC|DP_TQING;
1332 oval = (mpt->mpt_port_page0.Capabilities >> 16);
1333 pval = (mpt->mpt_port_page0.Capabilities >> 8);
1335 #ifndef CAM_NEW_TRAN_CODE
1336 cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
1337 if (dval & DP_DISC_ENABLE) {
1338 cts->flags |= CCB_TRANS_DISC_ENB;
1340 if (dval & DP_TQING_ENABLE) {
1341 cts->flags |= CCB_TRANS_TAG_ENB;
1343 if (dval & DP_WIDE) {
1344 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1346 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1348 cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
1349 CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
1351 cts->sync_period = pval;
1352 cts->sync_offset = oval;
1354 CCB_TRANS_SYNC_RATE_VALID |
1355 CCB_TRANS_SYNC_OFFSET_VALID;
1358 cts->protocol = PROTO_SCSI;
1359 cts->protocol_version = SCSI_REV_2;
1360 cts->transport = XPORT_SPI;
1361 cts->transport_version = 2;
1363 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
1364 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
1365 if (dval & DP_DISC_ENABLE) {
1366 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
1368 if (dval & DP_TQING_ENABLE) {
1369 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
1372 spi->sync_offset = oval;
1373 spi->sync_period = pval;
1374 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
1375 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
1377 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
1378 if (dval & DP_WIDE) {
1379 spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1381 spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1383 if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
1384 scsi->valid = CTS_SCSI_VALID_TQ;
1385 spi->valid |= CTS_SPI_VALID_DISC;
1390 if (mpt->verbose > 1) {
1391 device_printf(mpt->dev,
1392 "GET %s tgt %d flags %x period %x off %x\n",
1393 IS_CURRENT_SETTINGS(cts)? "ACTIVE" :
1394 "NVRAM", tgt, dval, pval, oval);
1397 ccb->ccb_h.status = CAM_REQ_CMP;
1401 case XPT_CALC_GEOMETRY:
1403 struct ccb_calc_geometry *ccg;
1404 u_int32_t secs_per_cylinder;
1408 if (ccg->block_size == 0) {
1409 ccb->ccb_h.status = CAM_REQ_INVALID;
1414 size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
1415 if (size_mb > 1024) {
1417 ccg->secs_per_track = 63;
1420 ccg->secs_per_track = 32;
1422 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1423 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1424 ccb->ccb_h.status = CAM_REQ_CMP;
1428 case XPT_PATH_INQ: /* Path routing inquiry */
1430 struct ccb_pathinq *cpi = &ccb->cpi;
1432 cpi->version_num = 1;
1433 cpi->target_sprt = 0;
1434 cpi->hba_eng_cnt = 0;
1436 cpi->bus_id = cam_sim_bus(sim);
1438 cpi->max_target = 255;
1439 cpi->hba_misc = PIM_NOBUSRESET;
1440 cpi->initiator_id = cpi->max_target + 1;
1441 cpi->base_transfer_speed = 100000;
1442 cpi->hba_inquiry = PI_TAG_ABLE;
1444 cpi->initiator_id = mpt->mpt_ini_id;
1445 cpi->base_transfer_speed = 3300;
1446 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
1448 cpi->max_target = 15;
1451 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1452 strncpy(cpi->hba_vid, "LSI", HBA_IDLEN);
1453 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1454 cpi->unit_number = cam_sim_unit(sim);
1455 cpi->ccb_h.status = CAM_REQ_CMP;
1460 ccb->ccb_h.status = CAM_REQ_INVALID;
1467 mpt_setwidth(mpt_softc_t *mpt, int tgt, int onoff)
1469 fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
1470 tmp = mpt->mpt_dev_page1[tgt];
1472 tmp.RequestedParameters |= MPI_SCSIDEVPAGE1_RP_WIDE;
1474 tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_WIDE;
1476 if (mpt_write_cfg_page(mpt, tgt, &tmp.Header)) {
1479 if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) {
1482 mpt->mpt_dev_page1[tgt] = tmp;
1483 if (mpt->verbose > 1) {
1484 device_printf(mpt->dev,
1485 "SPI Target %d Page 1: RequestedParameters %x Config %x\n",
1486 tgt, mpt->mpt_dev_page1[tgt].RequestedParameters,
1487 mpt->mpt_dev_page1[tgt].Configuration);
1493 mpt_setsync(mpt_softc_t *mpt, int tgt, int period, int offset)
1495 fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
1496 tmp = mpt->mpt_dev_page1[tgt];
1497 tmp.RequestedParameters &=
1498 ~MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
1499 tmp.RequestedParameters &=
1500 ~MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
1501 tmp.RequestedParameters &=
1502 ~MPI_SCSIDEVPAGE1_RP_DT;
1503 tmp.RequestedParameters &=
1504 ~MPI_SCSIDEVPAGE1_RP_QAS;
1505 tmp.RequestedParameters &=
1506 ~MPI_SCSIDEVPAGE1_RP_IU;
1508 * XXX: For now, we're ignoring specific settings
1510 if (period && offset) {
1511 int factor, offset, np;
1512 factor = (mpt->mpt_port_page0.Capabilities >> 8) & 0xff;
1513 offset = (mpt->mpt_port_page0.Capabilities >> 16) & 0xff;
1516 np |= MPI_SCSIDEVPAGE1_RP_QAS;
1517 np |= MPI_SCSIDEVPAGE1_RP_IU;
1520 np |= MPI_SCSIDEVPAGE1_RP_DT;
1522 np |= (factor << 8) | (offset << 16);
1523 tmp.RequestedParameters |= np;
1525 if (mpt_write_cfg_page(mpt, tgt, &tmp.Header)) {
1528 if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) {
1531 mpt->mpt_dev_page1[tgt] = tmp;
1532 if (mpt->verbose > 1) {
1533 device_printf(mpt->dev,
1534 "SPI Target %d Page 1: RParams %x Config %x\n",
1535 tgt, mpt->mpt_dev_page1[tgt].RequestedParameters,
1536 mpt->mpt_dev_page1[tgt].Configuration);