2 * FreeBSD/CAM specific routines for LSI '909 FC adapters.
5 * Copyright (c) 2000, 2001 by Greg Ansley
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice immediately at the beginning of the file, without modification,
12 * this list of conditions, and the following disclaimer.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * Additional Copyright (c) 2002 by Matthew Jacob under same license.
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <dev/mpt/mpt_freebsd.h>
37 static void mpt_poll(struct cam_sim *);
38 static timeout_t mpttimeout;
39 static timeout_t mpttimeout2;
40 static void mpt_action(struct cam_sim *, union ccb *);
41 static int mpt_setwidth(mpt_softc_t *, int, int);
42 static int mpt_setsync(mpt_softc_t *, int, int, int);
45 mpt_cam_attach(mpt_softc_t *mpt)
47 struct cam_devq *devq;
52 maxq = (mpt->mpt_global_credits < MPT_MAX_REQUESTS(mpt))?
53 mpt->mpt_global_credits : MPT_MAX_REQUESTS(mpt);
57 * Create the device queue for our SIM(s).
60 devq = cam_simq_alloc(maxq);
66 * Construct our SIM entry.
68 sim = cam_sim_alloc(mpt_action, mpt_poll, "mpt", mpt,
69 mpt->unit, 1, maxq, devq);
76 * Register exactly the bus.
79 if (xpt_bus_register(sim, 0) != CAM_SUCCESS) {
80 cam_sim_free(sim, TRUE);
84 if (xpt_create_path(&mpt->path, NULL, cam_sim_path(sim),
85 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
86 xpt_bus_deregister(cam_sim_path(sim));
87 cam_sim_free(sim, TRUE);
94 mpt_cam_detach(mpt_softc_t *mpt)
96 if (mpt->sim != NULL) {
97 xpt_free_path(mpt->path);
98 xpt_bus_deregister(cam_sim_path(mpt->sim));
99 cam_sim_free(mpt->sim, TRUE);
104 /* This routine is used after a system crash to dump core onto the
108 mpt_poll(struct cam_sim *sim)
110 mpt_softc_t *mpt = (mpt_softc_t *) cam_sim_softc(sim);
117 * This routine is called if the 9x9 does not return completion status
118 * for a command after a CAM specified time.
121 mpttimeout(void *arg)
124 union ccb *ccb = arg;
128 mpt = ccb->ccb_h.ccb_mpt_ptr;
130 req = ccb->ccb_h.ccb_req_ptr;
131 oseq = req->sequence;
134 if (req->sequence != oseq) {
135 mpt_prt(mpt, "bullet missed in timeout");
139 mpt_prt(mpt, "bullet U-turned in timeout: got us");
142 "time out on request index = 0x%02x sequence = 0x%08x",
143 req->index, req->sequence);
144 mpt_check_doorbell(mpt);
145 mpt_prt(mpt, "Status %08x; Mask %08x; Doorbell %08x",
146 mpt_read(mpt, MPT_OFFSET_INTR_STATUS),
147 mpt_read(mpt, MPT_OFFSET_INTR_MASK),
148 mpt_read(mpt, MPT_OFFSET_DOORBELL) );
149 printf("request state %s\n", mpt_req_state(req->debug));
150 if (ccb != req->ccb) {
151 printf("time out: ccb %p != req->ccb %p\n",
154 mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);
155 req->debug = REQ_TIMEOUT;
157 req->link.sle_next = (void *) mpt;
158 (void) timeout(mpttimeout2, (caddr_t)req, hz / 10);
159 ccb->ccb_h.status = CAM_CMD_TIMEOUT;
160 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
162 MPTLOCK_2_CAMLOCK(mpt);
164 CAMLOCK_2_MPTLOCK(mpt);
169 mpttimeout2(void *arg)
171 request_t *req = arg;
172 if (req->debug == REQ_TIMEOUT) {
173 mpt_softc_t *mpt = (mpt_softc_t *) req->link.sle_next;
175 mpt_free_request(mpt, req);
181 * Callback routine from "bus_dmamap_load" or in simple case called directly.
183 * Takes a list of physical segments and builds the SGL for SCSI IO command
184 * and forwards the commard to the IOC after one last check that CAM has not
185 * aborted the transaction.
188 mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
193 MSG_SCSI_IO_REQUEST *mpt_req;
196 req = (request_t *)arg;
199 mpt = ccb->ccb_h.ccb_mpt_ptr;
200 req = ccb->ccb_h.ccb_req_ptr;
201 mpt_req = req->req_vbuf;
203 if (error == 0 && nseg > MPT_SGL_MAX) {
209 mpt_prt(mpt, "bus_dmamap_load returned %d", error);
210 if (ccb->ccb_h.status == CAM_REQ_INPROG) {
211 xpt_freeze_devq(ccb->ccb_h.path, 1);
212 ccb->ccb_h.status = CAM_DEV_QFRZN;
214 ccb->ccb_h.status |= CAM_REQ_TOO_BIG;
216 ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
218 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
220 CAMLOCK_2_MPTLOCK(mpt);
221 mpt_free_request(mpt, req);
222 MPTLOCK_2_CAMLOCK(mpt);
226 if (nseg > MPT_NSGL_FIRST(mpt)) {
232 mpt_req->DataLength = ccb->csio.dxfer_len;
233 flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT;
234 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
235 flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
237 se = (SGE_SIMPLE32 *) &mpt_req->SGL;
238 for (i = 0; i < MPT_NSGL_FIRST(mpt) - 1; i++, se++, dm_segs++) {
241 bzero(se, sizeof (*se));
242 se->Address = dm_segs->ds_addr;
243 MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
245 if (i == MPT_NSGL_FIRST(mpt) - 2) {
246 tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
248 MPI_pSGE_SET_FLAGS(se, tf);
253 * Tell the IOC where to find the first chain element
255 mpt_req->ChainOffset = ((char *)se - (char *)mpt_req) >> 2;
258 * Until we're finished with all segments...
263 * Construct the chain element that point to the
266 ce = (SGE_CHAIN32 *) se++;
267 if (nleft > MPT_NSGL(mpt)) {
268 ntodo = MPT_NSGL(mpt) - 1;
269 ce->NextChainOffset = (MPT_RQSL(mpt) -
270 sizeof (SGE_SIMPLE32)) >> 2;
271 ce->Length = MPT_NSGL(mpt) *
272 sizeof (SGE_SIMPLE32);
275 ce->NextChainOffset = 0;
276 ce->Length = ntodo * sizeof (SGE_SIMPLE32);
278 ce->Address = req->req_pbuf +
279 ((char *)se - (char *)mpt_req);
280 ce->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
281 for (i = 0; i < ntodo; i++, se++, dm_segs++) {
284 bzero(se, sizeof (*se));
285 se->Address = dm_segs->ds_addr;
286 MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
288 if (i == ntodo - 1) {
289 tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
290 if (ce->NextChainOffset == 0) {
292 MPI_SGE_FLAGS_END_OF_LIST |
293 MPI_SGE_FLAGS_END_OF_BUFFER;
296 MPI_pSGE_SET_FLAGS(se, tf);
302 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
303 op = BUS_DMASYNC_PREREAD;
305 op = BUS_DMASYNC_PREWRITE;
306 if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) {
307 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
309 } else if (nseg > 0) {
314 mpt_req->DataLength = ccb->csio.dxfer_len;
315 flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT;
316 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
317 flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
319 /* Copy the segments into our SG list */
320 se = (SGE_SIMPLE32 *) &mpt_req->SGL;
321 for (i = 0; i < nseg; i++, se++, dm_segs++) {
324 bzero(se, sizeof (*se));
325 se->Address = dm_segs->ds_addr;
326 MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
330 MPI_SGE_FLAGS_LAST_ELEMENT |
331 MPI_SGE_FLAGS_END_OF_BUFFER |
332 MPI_SGE_FLAGS_END_OF_LIST;
334 MPI_pSGE_SET_FLAGS(se, tf);
337 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
338 op = BUS_DMASYNC_PREREAD;
340 op = BUS_DMASYNC_PREWRITE;
341 if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) {
342 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
345 se = (SGE_SIMPLE32 *) &mpt_req->SGL;
347 * No data to transfer so we just make a single simple SGL
350 MPI_pSGE_SET_FLAGS(se,
351 (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
352 MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
356 * Last time we need to check if this CCB needs to be aborted.
358 if (ccb->ccb_h.status != CAM_REQ_INPROG) {
359 if (nseg && (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0)
360 bus_dmamap_unload(mpt->buffer_dmat, req->dmap);
361 CAMLOCK_2_MPTLOCK(mpt);
362 mpt_free_request(mpt, req);
363 MPTLOCK_2_CAMLOCK(mpt);
368 ccb->ccb_h.status |= CAM_SIM_QUEUED;
369 MPTLOCK_2_CAMLOCK(mpt);
370 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
371 ccb->ccb_h.timeout_ch =
372 timeout(mpttimeout, (caddr_t)ccb,
373 (ccb->ccb_h.timeout * hz) / 1000);
375 callout_handle_init(&ccb->ccb_h.timeout_ch);
377 if (mpt->verbose > 1)
378 mpt_print_scsi_io_request(mpt_req);
379 mpt_send_cmd(mpt, req);
380 MPTLOCK_2_CAMLOCK(mpt);
384 mpt_start(union ccb *ccb)
387 struct mpt_softc *mpt;
388 MSG_SCSI_IO_REQUEST *mpt_req;
389 struct ccb_scsiio *csio = &ccb->csio;
390 struct ccb_hdr *ccbh = &ccb->ccb_h;
392 /* Get the pointer for the physical addapter */
393 mpt = ccb->ccb_h.ccb_mpt_ptr;
395 CAMLOCK_2_MPTLOCK(mpt);
396 /* Get a request structure off the free list */
397 if ((req = mpt_get_request(mpt)) == NULL) {
398 if (mpt->outofbeer == 0) {
400 xpt_freeze_simq(mpt->sim, 1);
401 if (mpt->verbose > 1) {
402 mpt_prt(mpt, "FREEZEQ");
405 MPTLOCK_2_CAMLOCK(mpt);
406 ccb->ccb_h.status = CAM_REQUEUE_REQ;
410 MPTLOCK_2_CAMLOCK(mpt);
412 /* Link the ccb and the request structure so we can find */
413 /* the other knowing either the request or the ccb */
415 ccb->ccb_h.ccb_req_ptr = req;
417 /* Now we build the command for the IOC */
418 mpt_req = req->req_vbuf;
419 bzero(mpt_req, sizeof *mpt_req);
421 mpt_req->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
422 mpt_req->Bus = mpt->bus;
424 mpt_req->SenseBufferLength =
425 (csio->sense_len < MPT_SENSE_SIZE) ?
426 csio->sense_len : MPT_SENSE_SIZE;
428 /* We use the message context to find the request structure when we */
429 /* Get the command competion interrupt from the FC IOC. */
430 mpt_req->MsgContext = req->index;
432 /* Which physical device to do the I/O on */
433 mpt_req->TargetID = ccb->ccb_h.target_id;
434 mpt_req->LUN[1] = ccb->ccb_h.target_lun;
436 /* Set the direction of the transfer */
437 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
438 mpt_req->Control = MPI_SCSIIO_CONTROL_READ;
439 else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
440 mpt_req->Control = MPI_SCSIIO_CONTROL_WRITE;
442 mpt_req->Control = MPI_SCSIIO_CONTROL_NODATATRANSFER;
444 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) {
445 switch(ccb->csio.tag_action) {
446 case MSG_HEAD_OF_Q_TAG:
447 mpt_req->Control |= MPI_SCSIIO_CONTROL_HEADOFQ;
450 mpt_req->Control |= MPI_SCSIIO_CONTROL_ACAQ;
452 case MSG_ORDERED_Q_TAG:
453 mpt_req->Control |= MPI_SCSIIO_CONTROL_ORDEREDQ;
455 case MSG_SIMPLE_Q_TAG:
457 mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
462 mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
464 mpt_req->Control |= MPI_SCSIIO_CONTROL_UNTAGGED;
467 if (mpt->is_fc == 0) {
468 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
469 mpt_req->Control |= MPI_SCSIIO_CONTROL_NO_DISCONNECT;
473 /* Copy the scsi command block into place */
474 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0)
475 bcopy(csio->cdb_io.cdb_ptr, mpt_req->CDB, csio->cdb_len);
477 bcopy(csio->cdb_io.cdb_bytes, mpt_req->CDB, csio->cdb_len);
479 mpt_req->CDBLength = csio->cdb_len;
480 mpt_req->DataLength = csio->dxfer_len;
481 mpt_req->SenseBufferLowAddr = req->sense_pbuf;
484 * If we have any data to send with this command,
485 * map it into bus space.
488 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
489 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {
491 * We've been given a pointer to a single buffer.
493 if ((ccbh->flags & CAM_DATA_PHYS) == 0) {
495 * Virtual address that needs to translated into
496 * one or more physical pages.
500 error = bus_dmamap_load(mpt->buffer_dmat,
501 req->dmap, csio->data_ptr, csio->dxfer_len,
502 mpt_execute_req, req, 0);
503 if (error == EINPROGRESS) {
505 * So as to maintain ordering,
506 * freeze the controller queue
507 * until our mapping is
510 xpt_freeze_simq(mpt->sim, 1);
511 ccbh->status |= CAM_RELEASE_SIMQ;
515 * We have been given a pointer to single
518 struct bus_dma_segment seg;
520 (bus_addr_t)(vm_offset_t)csio->data_ptr;
521 seg.ds_len = csio->dxfer_len;
522 mpt_execute_req(req, &seg, 1, 0);
526 * We have been given a list of addresses.
527 * These case could be easily done but they are not
528 * currently generated by the CAM subsystem so there
529 * is no point in wasting the time right now.
531 struct bus_dma_segment *segs;
532 if ((ccbh->flags & CAM_SG_LIST_PHYS) == 0) {
533 mpt_execute_req(req, NULL, 0, EFAULT);
535 /* Just use the segments provided */
536 segs = (struct bus_dma_segment *)csio->data_ptr;
537 mpt_execute_req(req, segs, csio->sglist_cnt,
538 (csio->sglist_cnt < MPT_SGL_MAX)?
543 mpt_execute_req(req, NULL, 0, 0);
548 mpt_bus_reset(union ccb *ccb)
553 MSG_SCSI_TASK_MGMT *reset_req;
555 /* Get the pointer for the physical adapter */
556 mpt = ccb->ccb_h.ccb_mpt_ptr;
558 /* Get a request structure off the free list */
559 if ((req = mpt_get_request(mpt)) == NULL) {
560 return (CAM_REQUEUE_REQ);
563 /* Link the ccb and the request structure so we can find */
564 /* the other knowing either the request or the ccb */
566 ccb->ccb_h.ccb_req_ptr = req;
568 reset_req = req->req_vbuf;
569 bzero(reset_req, sizeof *reset_req);
571 reset_req->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
572 reset_req->MsgContext = req->index;
573 reset_req->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
576 * Should really be TARGET_RESET_OPTION
578 reset_req->MsgFlags =
579 MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION;
581 /* Which physical device Reset */
582 reset_req->TargetID = ccb->ccb_h.target_id;
583 reset_req->LUN[1] = ccb->ccb_h.target_lun;
585 ccb->ccb_h.status |= CAM_SIM_QUEUED;
587 error = mpt_send_handshake_cmd(mpt,
588 sizeof (MSG_SCSI_TASK_MGMT), reset_req);
591 "mpt_bus_reset: mpt_send_handshake return %d", error);
592 return (CAM_REQ_CMP_ERR);
594 return (CAM_REQ_CMP);
599 * Process an asynchronous event from the IOC.
601 static void mpt_ctlop(mpt_softc_t *, void *, u_int32_t);
602 static void mpt_event_notify_reply(mpt_softc_t *mpt, MSG_EVENT_NOTIFY_REPLY *);
605 mpt_ctlop(mpt_softc_t *mpt, void *vmsg, u_int32_t reply)
607 MSG_DEFAULT_REPLY *dmsg = vmsg;
609 if (dmsg->Function == MPI_FUNCTION_EVENT_NOTIFICATION) {
610 mpt_event_notify_reply(mpt, vmsg);
611 mpt_free_reply(mpt, (reply << 1));
612 } else if (dmsg->Function == MPI_FUNCTION_EVENT_ACK) {
613 mpt_free_reply(mpt, (reply << 1));
614 } else if (dmsg->Function == MPI_FUNCTION_PORT_ENABLE) {
615 MSG_PORT_ENABLE_REPLY *msg = vmsg;
616 int index = msg->MsgContext & ~0x80000000;
617 if (mpt->verbose > 1) {
618 mpt_prt(mpt, "enable port reply idx %d", index);
620 if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) {
621 request_t *req = &mpt->request_pool[index];
622 req->debug = REQ_DONE;
624 mpt_free_reply(mpt, (reply << 1));
625 } else if (dmsg->Function == MPI_FUNCTION_CONFIG) {
626 MSG_CONFIG_REPLY *msg = vmsg;
627 int index = msg->MsgContext & ~0x80000000;
628 if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) {
629 request_t *req = &mpt->request_pool[index];
630 req->debug = REQ_DONE;
631 req->sequence = reply;
633 mpt_free_reply(mpt, (reply << 1));
636 mpt_prt(mpt, "unknown mpt_ctlop: %x", dmsg->Function);
641 mpt_event_notify_reply(mpt_softc_t *mpt, MSG_EVENT_NOTIFY_REPLY *msg)
644 case MPI_EVENT_LOG_DATA:
645 /* Some error occured that LSI wants logged */
646 printf("\tEvtLogData: IOCLogInfo: 0x%08x\n", msg->IOCLogInfo);
647 printf("\tEvtLogData: Event Data:");
650 for (i = 0; i < msg->EventDataLength; i++) {
651 printf(" %08x", msg->Data[i]);
657 case MPI_EVENT_UNIT_ATTENTION:
658 mpt_prt(mpt, "Bus: 0x%02x TargetID: 0x%02x",
659 (msg->Data[0] >> 8) & 0xff, msg->Data[0] & 0xff);
662 case MPI_EVENT_IOC_BUS_RESET:
663 /* We generated a bus reset */
664 mpt_prt(mpt, "IOC Bus Reset Port: %d",
665 (msg->Data[0] >> 8) & 0xff);
668 case MPI_EVENT_EXT_BUS_RESET:
669 /* Someone else generated a bus reset */
670 mpt_prt(mpt, "Ext Bus Reset");
672 * These replies don't return EventData like the MPI
675 /* xpt_async(AC_BUS_RESET, path, NULL); */
678 case MPI_EVENT_RESCAN:
680 * In general this means a device has been added
683 mpt_prt(mpt, "Rescan Port: %d", (msg->Data[0] >> 8) & 0xff);
684 /* xpt_async(AC_FOUND_DEVICE, path, NULL); */
687 case MPI_EVENT_LINK_STATUS_CHANGE:
688 mpt_prt(mpt, "Port %d: LinkState: %s",
689 (msg->Data[1] >> 8) & 0xff,
690 ((msg->Data[0] & 0xff) == 0)? "Failed" : "Active");
693 case MPI_EVENT_LOOP_STATE_CHANGE:
694 switch ((msg->Data[0] >> 16) & 0xff) {
697 "Port 0x%x: FC LinkEvent: LIP(%02x,%02x) (Loop Initialization)\n",
698 (msg->Data[1] >> 8) & 0xff,
699 (msg->Data[0] >> 8) & 0xff,
700 (msg->Data[0] ) & 0xff);
701 switch ((msg->Data[0] >> 8) & 0xff) {
703 if ((msg->Data[0] & 0xff) == 0xF7) {
704 printf("Device needs AL_PA\n");
706 printf("Device %02x doesn't like FC performance\n",
707 msg->Data[0] & 0xFF);
711 if ((msg->Data[0] & 0xff) == 0xF7) {
712 printf("Device had loop failure at its receiver prior to acquiring AL_PA\n");
714 printf("Device %02x detected loop failure at its receiver\n",
715 msg->Data[0] & 0xFF);
719 printf("Device %02x requests that device %02x reset itself\n",
721 (msg->Data[0] >> 8) & 0xFF);
726 mpt_prt(mpt, "Port 0x%x: FC LinkEvent: LPE(%02x,%02x) (Loop Port Enable)",
727 (msg->Data[1] >> 8) & 0xff, /* Port */
728 (msg->Data[0] >> 8) & 0xff, /* Character 3 */
729 (msg->Data[0] ) & 0xff /* Character 4 */
733 mpt_prt(mpt, "Port 0x%x: FC LinkEvent: LPB(%02x,%02x) (Loop Port Bypass)",
734 (msg->Data[1] >> 8) & 0xff, /* Port */
735 (msg->Data[0] >> 8) & 0xff, /* Character 3 */
736 (msg->Data[0] ) & 0xff /* Character 4 */
740 mpt_prt(mpt, "Port 0x%x: FC LinkEvent: Unknown FC event (%02x %02x %02x)",
741 (msg->Data[1] >> 8) & 0xff, /* Port */
742 (msg->Data[0] >> 16) & 0xff, /* Event */
743 (msg->Data[0] >> 8) & 0xff, /* Character 3 */
744 (msg->Data[0] ) & 0xff /* Character 4 */
749 case MPI_EVENT_LOGOUT:
750 mpt_prt(mpt, "FC Logout Port: %d N_PortID: %02x",
751 (msg->Data[1] >> 8) & 0xff, msg->Data[0]);
753 case MPI_EVENT_EVENT_CHANGE:
754 /* This is just an acknowledgement of our
755 mpt_send_event_request */
758 mpt_prt(mpt, "Unknown event 0x%x\n", msg->Event);
760 if (msg->AckRequired) {
763 if ((req = mpt_get_request(mpt)) == NULL) {
764 panic("unable to get request to acknowledge notify");
766 ackp = (MSG_EVENT_ACK *) req->req_vbuf;
767 bzero(ackp, sizeof *ackp);
768 ackp->Function = MPI_FUNCTION_EVENT_ACK;
769 ackp->Event = msg->Event;
770 ackp->EventContext = msg->EventContext;
771 ackp->MsgContext = req->index | 0x80000000;
772 mpt_check_doorbell(mpt);
773 mpt_send_cmd(mpt, req);
778 mpt_done(mpt_softc_t *mpt, u_int32_t reply)
783 MSG_REQUEST_HEADER *mpt_req;
784 MSG_SCSI_IO_REPLY *mpt_reply;
786 index = -1; /* Shutup the complier */
788 if ((reply & MPT_CONTEXT_REPLY) == 0) {
791 index = reply & MPT_CONTEXT_MASK;
795 bus_dmamap_sync(mpt->reply_dmat, mpt->reply_dmap,
796 BUS_DMASYNC_POSTREAD);
797 /* address reply (Error) */
798 mpt_reply = MPT_REPLY_PTOV(mpt, reply);
799 if (mpt->verbose > 1) {
800 pReply = (unsigned *) mpt_reply;
801 mpt_prt(mpt, "Address Reply (index %u)",
802 mpt_reply->MsgContext & 0xffff);
803 printf("%08x %08x %08x %08x\n",
804 pReply[0], pReply[1], pReply[2], pReply[3]);
805 printf("%08x %08x %08x %08x\n",
806 pReply[4], pReply[5], pReply[6], pReply[7]);
807 printf("%08x %08x %08x %08x\n\n",
808 pReply[8], pReply[9], pReply[10], pReply[11]);
810 index = mpt_reply->MsgContext;
814 * Address reply with MessageContext high bit set
815 * This is most likely a notify message so we try
816 * to process it then free it
818 if ((index & 0x80000000) != 0) {
819 if (mpt_reply != NULL) {
820 mpt_ctlop(mpt, mpt_reply, reply);
822 mpt_prt(mpt, "mpt_done: index 0x%x, NULL reply", index);
827 /* Did we end up with a valid index into the table? */
828 if (index < 0 || index >= MPT_MAX_REQUESTS(mpt)) {
829 mpt_prt(mpt, "mpt_done: invalid index (%x) in reply", index);
833 req = &mpt->request_pool[index];
835 /* Make sure memory hasn't been trashed */
836 if (req->index != index) {
837 printf("mpt_done: corrupted request struct");
841 /* Short cut for task management replys; nothing more for us to do */
842 mpt_req = req->req_vbuf;
843 if (mpt_req->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
844 if (mpt->verbose > 1) {
845 mpt_prt(mpt, "mpt_done: TASK MGMT");
850 if (mpt_req->Function == MPI_FUNCTION_PORT_ENABLE) {
855 * At this point it better be a SCSI IO command, but don't
858 if (mpt_req->Function != MPI_FUNCTION_SCSI_IO_REQUEST) {
862 /* Recover the CAM control block from the request structure */
865 /* Can't have had a SCSI command with out a CAM control block */
866 if (ccb == NULL || (ccb->ccb_h.status & CAM_SIM_QUEUED) == 0) {
868 "mpt_done: corrupted ccb, index = 0x%02x seq = 0x%08x",
869 req->index, req->sequence);
870 printf(" request state %s\nmpt_request:\n",
871 mpt_req_state(req->debug));
872 mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);
874 if (mpt_reply != NULL) {
875 printf("\nmpt_done: reply:\n");
876 mpt_print_reply(MPT_REPLY_PTOV(mpt, reply));
878 printf("\nmpt_done: context reply: 0x%08x\n", reply);
883 untimeout(mpttimeout, ccb, ccb->ccb_h.timeout_ch);
885 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
888 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
889 op = BUS_DMASYNC_POSTREAD;
891 op = BUS_DMASYNC_POSTWRITE;
893 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
894 bus_dmamap_unload(mpt->buffer_dmat, req->dmap);
898 if (mpt_reply == NULL) {
899 /* Context reply; report that the command was successfull */
900 ccb->ccb_h.status = CAM_REQ_CMP;
901 ccb->csio.scsi_status = SCSI_STATUS_OK;
902 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
903 if (mpt->outofbeer) {
904 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
906 if (mpt->verbose > 1) {
907 mpt_prt(mpt, "THAWQ");
910 MPTLOCK_2_CAMLOCK(mpt);
912 CAMLOCK_2_MPTLOCK(mpt);
916 ccb->csio.scsi_status = mpt_reply->SCSIStatus;
917 switch(mpt_reply->IOCStatus) {
918 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
919 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
922 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
924 * Yikes, Tagged queue full comes through this path!
926 * So we'll change it to a status error and anything
927 * that returns status should probably be a status
931 ccb->csio.dxfer_len - mpt_reply->TransferCount;
932 if (mpt_reply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) {
933 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
937 case MPI_IOCSTATUS_SUCCESS:
938 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:
939 switch (ccb->csio.scsi_status) {
941 ccb->ccb_h.status = CAM_REQ_CMP;
944 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
948 case MPI_IOCSTATUS_BUSY:
949 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
950 ccb->ccb_h.status = CAM_BUSY;
953 case MPI_IOCSTATUS_SCSI_INVALID_BUS:
954 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
955 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
956 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
959 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
960 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
963 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:
964 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:
965 ccb->ccb_h.status = CAM_UNCOR_PARITY;
968 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
969 ccb->ccb_h.status = CAM_REQ_CMP;
972 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
973 ccb->ccb_h.status = CAM_UA_TERMIO;
976 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
977 ccb->ccb_h.status = CAM_REQ_TERMIO;
980 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
981 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
985 ccb->ccb_h.status = CAM_UNREC_HBA_ERROR;
989 if ((mpt_reply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) != 0) {
990 if (ccb->ccb_h.flags & (CAM_SENSE_PHYS | CAM_SENSE_PTR)) {
991 ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
993 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
994 ccb->csio.sense_resid = mpt_reply->SenseCount;
995 bcopy(req->sense_vbuf, &ccb->csio.sense_data,
996 ccb->csio.sense_len);
998 } else if (mpt_reply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
999 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1000 ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
1003 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1004 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1005 ccb->ccb_h.status |= CAM_DEV_QFRZN;
1006 xpt_freeze_devq(ccb->ccb_h.path, 1);
1011 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1012 if (mpt->outofbeer) {
1013 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1015 if (mpt->verbose > 1) {
1016 mpt_prt(mpt, "THAWQ");
1019 MPTLOCK_2_CAMLOCK(mpt);
1021 CAMLOCK_2_MPTLOCK(mpt);
1024 /* If IOC done with this request free it up */
1025 if (mpt_reply == NULL || (mpt_reply->MsgFlags & 0x80) == 0)
1026 mpt_free_request(mpt, req);
1028 /* If address reply; give the buffer back to the IOC */
1029 if (mpt_reply != NULL)
1030 mpt_free_reply(mpt, (reply << 1));
1034 mpt_action(struct cam_sim *sim, union ccb *ccb)
1038 struct ccb_trans_settings *cts;
1040 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mpt_action\n"));
1042 mpt = (mpt_softc_t *)cam_sim_softc(sim);
1044 ccb->ccb_h.ccb_mpt_ptr = mpt;
1046 switch (ccb->ccb_h.func_code) {
1048 if (mpt->verbose > 1)
1049 mpt_prt(mpt, "XPT_RESET_BUS");
1050 CAMLOCK_2_MPTLOCK(mpt);
1051 error = mpt_bus_reset(ccb);
1053 case CAM_REQ_INPROG:
1054 MPTLOCK_2_CAMLOCK(mpt);
1056 case CAM_REQUEUE_REQ:
1057 if (mpt->outofbeer == 0) {
1059 xpt_freeze_simq(sim, 1);
1060 if (mpt->verbose > 1) {
1061 mpt_prt(mpt, "FREEZEQ");
1064 ccb->ccb_h.status = CAM_REQUEUE_REQ;
1065 MPTLOCK_2_CAMLOCK(mpt);
1070 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1071 ccb->ccb_h.status |= CAM_REQ_CMP;
1072 if (mpt->outofbeer) {
1073 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1075 if (mpt->verbose > 1) {
1076 mpt_prt(mpt, "THAWQ");
1079 MPTLOCK_2_CAMLOCK(mpt);
1084 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1085 MPTLOCK_2_CAMLOCK(mpt);
1090 case XPT_SCSI_IO: /* Execute the requested I/O operation */
1092 * Do a couple of preliminary checks...
1094 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1095 if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
1096 ccb->ccb_h.status = CAM_REQ_INVALID;
1101 /* Max supported CDB length is 16 bytes */
1102 if (ccb->csio.cdb_len >
1103 sizeof (((PTR_MSG_SCSI_IO_REQUEST)0)->CDB)) {
1104 ccb->ccb_h.status = CAM_REQ_INVALID;
1108 ccb->csio.scsi_status = SCSI_STATUS_OK;
1114 * XXX: Need to implement
1116 ccb->ccb_h.status = CAM_UA_ABORT;
1120 #ifdef CAM_NEW_TRAN_CODE
1121 #define IS_CURRENT_SETTINGS(c) (c->type == CTS_TYPE_CURRENT_SETTINGS)
1123 #define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS)
1125 #define DP_DISC_ENABLE 0x1
1126 #define DP_DISC_DISABL 0x2
1127 #define DP_DISC (DP_DISC_ENABLE|DP_DISC_DISABL)
1129 #define DP_TQING_ENABLE 0x4
1130 #define DP_TQING_DISABL 0x8
1131 #define DP_TQING (DP_TQING_ENABLE|DP_TQING_DISABL)
1133 #define DP_WIDE 0x10
1134 #define DP_NARROW 0x20
1135 #define DP_WIDTH (DP_WIDE|DP_NARROW)
1137 #define DP_SYNC 0x40
1139 case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */
1141 if (!IS_CURRENT_SETTINGS(cts)) {
1142 ccb->ccb_h.status = CAM_REQ_INVALID;
1146 tgt = cts->ccb_h.target_id;
1147 if (mpt->is_fc == 0) {
1149 u_int period = 0, offset = 0;
1150 #ifndef CAM_NEW_TRAN_CODE
1151 if (cts->valid & CCB_TRANS_DISC_VALID) {
1152 dval |= DP_DISC_ENABLE;
1154 if (cts->valid & CCB_TRANS_TQ_VALID) {
1155 dval |= DP_TQING_ENABLE;
1157 if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
1164 * Any SYNC RATE of nonzero and SYNC_OFFSET
1165 * of nonzero will cause us to go to the
1166 * selected (from NVRAM) maximum value for
1167 * this device. At a later point, we'll
1168 * allow finer control.
1170 if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
1171 (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)) {
1173 period = cts->sync_period;
1174 offset = cts->sync_offset;
1177 struct ccb_trans_settings_scsi *scsi =
1178 &cts->proto_specific.scsi;
1179 struct ccb_trans_settings_spi *spi =
1180 &cts->xport_specific.spi;
1182 if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
1183 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
1184 dval |= DP_DISC_ENABLE;
1186 dval |= DP_DISC_DISABL;
1189 if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
1190 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
1191 dval |= DP_TQING_ENABLE;
1193 dval |= DP_TQING_DISABL;
1196 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1197 if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT)
1203 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) &&
1204 (spi->valid & CTS_SPI_VALID_SYNC_RATE) &&
1205 (spi->sync_period && spi->sync_offset)) {
1207 period = spi->sync_period;
1208 offset = spi->sync_offset;
1211 CAMLOCK_2_MPTLOCK(mpt);
1212 if (dval & DP_DISC_ENABLE) {
1213 mpt->mpt_disc_enable |= (1 << tgt);
1214 } else if (dval & DP_DISC_DISABL) {
1215 mpt->mpt_disc_enable &= ~(1 << tgt);
1217 if (dval & DP_TQING_ENABLE) {
1218 mpt->mpt_tag_enable |= (1 << tgt);
1219 } else if (dval & DP_TQING_DISABL) {
1220 mpt->mpt_tag_enable &= ~(1 << tgt);
1222 if (dval & DP_WIDTH) {
1223 if (mpt_setwidth(mpt, tgt, dval & DP_WIDE)) {
1224 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1225 MPTLOCK_2_CAMLOCK(mpt);
1230 if (dval & DP_SYNC) {
1231 if (mpt_setsync(mpt, tgt, period, offset)) {
1232 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1233 MPTLOCK_2_CAMLOCK(mpt);
1238 MPTLOCK_2_CAMLOCK(mpt);
1239 if (mpt->verbose > 1) {
1241 "SET tgt %d flags %x period %x off %x",
1242 tgt, dval, period, offset);
1245 ccb->ccb_h.status = CAM_REQ_CMP;
1249 case XPT_GET_TRAN_SETTINGS:
1251 tgt = cts->ccb_h.target_id;
1253 #ifndef CAM_NEW_TRAN_CODE
1255 * a lot of normal SCSI things don't make sense.
1257 cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
1258 cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
1260 * How do you measure the width of a high
1261 * speed serial bus? Well, in bytes.
1263 * Offset and period make no sense, though, so we set
1264 * (above) a 'base' transfer speed to be gigabit.
1266 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1268 struct ccb_trans_settings_fc *fc =
1269 &cts->xport_specific.fc;
1271 cts->protocol = PROTO_SCSI;
1272 cts->protocol_version = SCSI_REV_2;
1273 cts->transport = XPORT_FC;
1274 cts->transport_version = 0;
1276 fc->valid = CTS_FC_VALID_SPEED;
1277 fc->bitrate = 100000; /* XXX: Need for 2Gb/s */
1278 /* XXX: need a port database for each target */
1281 #ifdef CAM_NEW_TRAN_CODE
1282 struct ccb_trans_settings_scsi *scsi =
1283 &cts->proto_specific.scsi;
1284 struct ccb_trans_settings_spi *spi =
1285 &cts->xport_specific.spi;
1287 u_int8_t dval, pval, oval;
1290 * We aren't going off of Port PAGE2 params for
1291 * tagged queuing or disconnect capabilities
1292 * for current settings. For goal settings,
1293 * we assert all capabilities- we've had some
1294 * problems with reading NVRAM data.
1296 if (IS_CURRENT_SETTINGS(cts)) {
1297 CONFIG_PAGE_SCSI_DEVICE_0 tmp;
1300 tmp = mpt->mpt_dev_page0[tgt];
1301 CAMLOCK_2_MPTLOCK(mpt);
1302 if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) {
1304 "cannot get target %d DP0", tgt);
1306 if (mpt->verbose > 1) {
1308 "SPI Tgt %d Page 0: NParms %x Information %x",
1310 tmp.NegotiatedParameters,
1314 MPTLOCK_2_CAMLOCK(mpt);
1316 if (tmp.NegotiatedParameters &
1317 MPI_SCSIDEVPAGE0_NP_WIDE)
1320 if (mpt->mpt_disc_enable & (1 << tgt)) {
1321 dval |= DP_DISC_ENABLE;
1323 if (mpt->mpt_tag_enable & (1 << tgt)) {
1324 dval |= DP_TQING_ENABLE;
1326 oval = (tmp.NegotiatedParameters >> 16) & 0xff;
1327 pval = (tmp.NegotiatedParameters >> 8) & 0xff;
1330 * XXX: Fix wrt NVRAM someday. Attempts
1331 * XXX: to read port page2 device data
1332 * XXX: just returns zero in these areas.
1334 dval = DP_WIDE|DP_DISC|DP_TQING;
1335 oval = (mpt->mpt_port_page0.Capabilities >> 16);
1336 pval = (mpt->mpt_port_page0.Capabilities >> 8);
1338 #ifndef CAM_NEW_TRAN_CODE
1339 cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
1340 if (dval & DP_DISC_ENABLE) {
1341 cts->flags |= CCB_TRANS_DISC_ENB;
1343 if (dval & DP_TQING_ENABLE) {
1344 cts->flags |= CCB_TRANS_TAG_ENB;
1346 if (dval & DP_WIDE) {
1347 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1349 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1351 cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
1352 CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
1354 cts->sync_period = pval;
1355 cts->sync_offset = oval;
1357 CCB_TRANS_SYNC_RATE_VALID |
1358 CCB_TRANS_SYNC_OFFSET_VALID;
1361 cts->protocol = PROTO_SCSI;
1362 cts->protocol_version = SCSI_REV_2;
1363 cts->transport = XPORT_SPI;
1364 cts->transport_version = 2;
1366 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
1367 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
1368 if (dval & DP_DISC_ENABLE) {
1369 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
1371 if (dval & DP_TQING_ENABLE) {
1372 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
1375 spi->sync_offset = oval;
1376 spi->sync_period = pval;
1377 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
1378 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
1380 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
1381 if (dval & DP_WIDE) {
1382 spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1384 spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1386 if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
1387 scsi->valid = CTS_SCSI_VALID_TQ;
1388 spi->valid |= CTS_SPI_VALID_DISC;
1393 if (mpt->verbose > 1) {
1395 "GET %s tgt %d flags %x period %x off %x",
1396 IS_CURRENT_SETTINGS(cts)? "ACTIVE" :
1397 "NVRAM", tgt, dval, pval, oval);
1400 ccb->ccb_h.status = CAM_REQ_CMP;
1404 case XPT_CALC_GEOMETRY:
1406 struct ccb_calc_geometry *ccg;
1409 if (ccg->block_size == 0) {
1410 ccb->ccb_h.status = CAM_REQ_INVALID;
1415 cam_calc_geometry(ccg, /*extended*/1);
1419 case XPT_PATH_INQ: /* Path routing inquiry */
1421 struct ccb_pathinq *cpi = &ccb->cpi;
1423 cpi->version_num = 1;
1424 cpi->target_sprt = 0;
1425 cpi->hba_eng_cnt = 0;
1427 cpi->bus_id = cam_sim_bus(sim);
1429 cpi->max_target = 255;
1430 cpi->hba_misc = PIM_NOBUSRESET;
1431 cpi->initiator_id = cpi->max_target + 1;
1432 cpi->base_transfer_speed = 100000;
1433 cpi->hba_inquiry = PI_TAG_ABLE;
1435 cpi->initiator_id = mpt->mpt_ini_id;
1436 cpi->base_transfer_speed = 3300;
1437 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
1439 cpi->max_target = 15;
1442 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1443 strncpy(cpi->hba_vid, "LSI", HBA_IDLEN);
1444 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1445 cpi->unit_number = cam_sim_unit(sim);
1446 cpi->ccb_h.status = CAM_REQ_CMP;
1451 ccb->ccb_h.status = CAM_REQ_INVALID;
1458 mpt_setwidth(mpt_softc_t *mpt, int tgt, int onoff)
1460 CONFIG_PAGE_SCSI_DEVICE_1 tmp;
1461 tmp = mpt->mpt_dev_page1[tgt];
1463 tmp.RequestedParameters |= MPI_SCSIDEVPAGE1_RP_WIDE;
1465 tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_WIDE;
1467 if (mpt_write_cfg_page(mpt, tgt, &tmp.Header)) {
1470 if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) {
1473 mpt->mpt_dev_page1[tgt] = tmp;
1474 if (mpt->verbose > 1) {
1476 "SPI Target %d Page 1: RequestedParameters %x Config %x",
1477 tgt, mpt->mpt_dev_page1[tgt].RequestedParameters,
1478 mpt->mpt_dev_page1[tgt].Configuration);
1484 mpt_setsync(mpt_softc_t *mpt, int tgt, int period, int offset)
1486 CONFIG_PAGE_SCSI_DEVICE_1 tmp;
1487 tmp = mpt->mpt_dev_page1[tgt];
1488 tmp.RequestedParameters &=
1489 ~MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
1490 tmp.RequestedParameters &=
1491 ~MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
1492 tmp.RequestedParameters &=
1493 ~MPI_SCSIDEVPAGE1_RP_DT;
1494 tmp.RequestedParameters &=
1495 ~MPI_SCSIDEVPAGE1_RP_QAS;
1496 tmp.RequestedParameters &=
1497 ~MPI_SCSIDEVPAGE1_RP_IU;
1499 * XXX: For now, we're ignoring specific settings
1501 if (period && offset) {
1502 int factor, offset, np;
1503 factor = (mpt->mpt_port_page0.Capabilities >> 8) & 0xff;
1504 offset = (mpt->mpt_port_page0.Capabilities >> 16) & 0xff;
1507 np |= MPI_SCSIDEVPAGE1_RP_QAS;
1508 np |= MPI_SCSIDEVPAGE1_RP_IU;
1511 np |= MPI_SCSIDEVPAGE1_RP_DT;
1513 np |= (factor << 8) | (offset << 16);
1514 tmp.RequestedParameters |= np;
1516 if (mpt_write_cfg_page(mpt, tgt, &tmp.Header)) {
1519 if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) {
1522 mpt->mpt_dev_page1[tgt] = tmp;
1523 if (mpt->verbose > 1) {
1525 "SPI Target %d Page 1: RParams %x Config %x",
1526 tgt, mpt->mpt_dev_page1[tgt].RequestedParameters,
1527 mpt->mpt_dev_page1[tgt].Configuration);