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.2 2003/06/17 04:28:28 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 <dev/mpt/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)
46 struct cam_devq *devq;
51 maxq = (mpt->mpt_global_credits < MPT_MAX_REQUESTS(mpt))?
52 mpt->mpt_global_credits : MPT_MAX_REQUESTS(mpt);
56 * Create the device queue for our SIM(s).
59 devq = cam_simq_alloc(maxq);
65 * Construct our SIM entry.
67 sim = cam_sim_alloc(mpt_action, mpt_poll, "mpt", mpt,
68 mpt->unit, 1, maxq, devq);
75 * Register exactly the bus.
78 if (xpt_bus_register(sim, 0) != CAM_SUCCESS) {
79 cam_sim_free(sim, TRUE);
83 if (xpt_create_path(&mpt->path, NULL, cam_sim_path(sim),
84 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
85 xpt_bus_deregister(cam_sim_path(sim));
86 cam_sim_free(sim, TRUE);
93 mpt_cam_detach(mpt_softc_t *mpt)
95 if (mpt->sim != NULL) {
96 xpt_free_path(mpt->path);
97 xpt_bus_deregister(cam_sim_path(mpt->sim));
98 cam_sim_free(mpt->sim, TRUE);
103 /* This routine is used after a system crash to dump core onto the
107 mpt_poll(struct cam_sim *sim)
109 mpt_softc_t *mpt = (mpt_softc_t *) cam_sim_softc(sim);
116 * This routine is called if the 9x9 does not return completion status
117 * for a command after a CAM specified time.
120 mpttimeout(void *arg)
123 union ccb *ccb = arg;
127 mpt = ccb->ccb_h.ccb_mpt_ptr;
129 req = ccb->ccb_h.ccb_req_ptr;
130 oseq = req->sequence;
133 if (req->sequence != oseq) {
134 device_printf(mpt->dev, "bullet missed in timeout\n");
138 device_printf(mpt->dev, "bullet U-turned in timeout: got us\n");
140 device_printf(mpt->dev,
141 "time out on request index = 0x%02x sequence = 0x%08x\n",
142 req->index, req->sequence);
143 mpt_check_doorbell(mpt);
144 device_printf(mpt->dev, "Status %08X; Mask %08X; Doorbell %08X\n",
145 mpt_read(mpt, MPT_OFFSET_INTR_STATUS),
146 mpt_read(mpt, MPT_OFFSET_INTR_MASK),
147 mpt_read(mpt, MPT_OFFSET_DOORBELL) );
148 printf("request state %s\n", mpt_req_state(req->debug));
149 if (ccb != req->ccb) {
150 printf("time out: ccb %p != req->ccb %p\n",
153 mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);
154 req->debug = REQ_TIMEOUT;
156 req->link.sle_next = (void *) mpt;
157 (void) timeout(mpttimeout2, (caddr_t)req, hz / 10);
158 ccb->ccb_h.status = CAM_CMD_TIMEOUT;
159 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
161 MPTLOCK_2_CAMLOCK(mpt);
163 CAMLOCK_2_MPTLOCK(mpt);
168 mpttimeout2(void *arg)
170 request_t *req = arg;
171 if (req->debug == REQ_TIMEOUT) {
172 mpt_softc_t *mpt = (mpt_softc_t *) req->link.sle_next;
174 mpt_free_request(mpt, req);
180 * Callback routine from "bus_dmamap_load" or in simple case called directly.
182 * Takes a list of physical segments and builds the SGL for SCSI IO command
183 * and forwards the commard to the IOC after one last check that CAM has not
184 * aborted the transaction.
187 mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
192 MSG_SCSI_IO_REQUEST *mpt_req;
195 req = (request_t *)arg;
198 mpt = ccb->ccb_h.ccb_mpt_ptr;
199 req = ccb->ccb_h.ccb_req_ptr;
200 mpt_req = req->req_vbuf;
202 if (error == 0 && nseg > MPT_SGL_MAX) {
208 device_printf(mpt->dev, "bus_dmamap_load returned %d\n",
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;
273 ce->NextChainOffset = 0;
275 ce->Length = ntodo * sizeof (SGE_SIMPLE32);
276 ce->Address = req->req_pbuf +
277 ((char *)se - (char *)mpt_req);
278 ce->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
279 for (i = 0; i < ntodo; i++, se++, dm_segs++) {
282 bzero(se, sizeof (*se));
283 se->Address = dm_segs->ds_addr;
284 MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
286 if (i == ntodo - 1) {
287 tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
288 if (ce->NextChainOffset == 0) {
290 MPI_SGE_FLAGS_END_OF_LIST |
291 MPI_SGE_FLAGS_END_OF_BUFFER;
294 MPI_pSGE_SET_FLAGS(se, tf);
300 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
301 op = BUS_DMASYNC_PREREAD;
303 op = BUS_DMASYNC_PREWRITE;
304 if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) {
305 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
307 } else if (nseg > 0) {
312 mpt_req->DataLength = ccb->csio.dxfer_len;
313 flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT;
314 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
315 flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
317 /* Copy the segments into our SG list */
318 se = (SGE_SIMPLE32 *) &mpt_req->SGL;
319 for (i = 0; i < nseg; i++, se++, dm_segs++) {
322 bzero(se, sizeof (*se));
323 se->Address = dm_segs->ds_addr;
324 MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
328 MPI_SGE_FLAGS_LAST_ELEMENT |
329 MPI_SGE_FLAGS_END_OF_BUFFER |
330 MPI_SGE_FLAGS_END_OF_LIST;
332 MPI_pSGE_SET_FLAGS(se, tf);
335 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
336 op = BUS_DMASYNC_PREREAD;
338 op = BUS_DMASYNC_PREWRITE;
339 if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) {
340 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
343 se = (SGE_SIMPLE32 *) &mpt_req->SGL;
345 * No data to transfer so we just make a single simple SGL
348 MPI_pSGE_SET_FLAGS(se,
349 (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
350 MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
354 * Last time we need to check if this CCB needs to be aborted.
356 if (ccb->ccb_h.status != CAM_REQ_INPROG) {
357 if (nseg && (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0)
358 bus_dmamap_unload(mpt->buffer_dmat, req->dmap);
359 CAMLOCK_2_MPTLOCK(mpt);
360 mpt_free_request(mpt, req);
361 MPTLOCK_2_CAMLOCK(mpt);
366 ccb->ccb_h.status |= CAM_SIM_QUEUED;
367 MPTLOCK_2_CAMLOCK(mpt);
368 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
369 ccb->ccb_h.timeout_ch =
370 timeout(mpttimeout, (caddr_t)ccb,
371 (ccb->ccb_h.timeout * hz) / 1000);
373 callout_handle_init(&ccb->ccb_h.timeout_ch);
375 if (mpt->verbose > 1)
376 mpt_print_scsi_io_request(mpt_req);
377 mpt_send_cmd(mpt, req);
378 MPTLOCK_2_CAMLOCK(mpt);
382 mpt_start(union ccb *ccb)
385 struct mpt_softc *mpt;
386 MSG_SCSI_IO_REQUEST *mpt_req;
387 struct ccb_scsiio *csio = &ccb->csio;
388 struct ccb_hdr *ccbh = &ccb->ccb_h;
390 /* Get the pointer for the physical addapter */
391 mpt = ccb->ccb_h.ccb_mpt_ptr;
393 CAMLOCK_2_MPTLOCK(mpt);
394 /* Get a request structure off the free list */
395 if ((req = mpt_get_request(mpt)) == NULL) {
396 if (mpt->outofbeer == 0) {
398 xpt_freeze_simq(mpt->sim, 1);
399 if (mpt->verbose > 1) {
400 device_printf(mpt->dev, "FREEZEQ\n");
403 MPTLOCK_2_CAMLOCK(mpt);
404 ccb->ccb_h.status = CAM_REQUEUE_REQ;
408 MPTLOCK_2_CAMLOCK(mpt);
410 /* Link the ccb and the request structure so we can find */
411 /* the other knowing either the request or the ccb */
413 ccb->ccb_h.ccb_req_ptr = req;
415 /* Now we build the command for the IOC */
416 mpt_req = req->req_vbuf;
417 bzero(mpt_req, sizeof *mpt_req);
419 mpt_req->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
420 mpt_req->Bus = mpt->bus;
422 mpt_req->SenseBufferLength =
423 (csio->sense_len < MPT_SENSE_SIZE) ?
424 csio->sense_len : MPT_SENSE_SIZE;
426 /* We use the message context to find the request structure when we */
427 /* Get the command competion interrupt from the FC IOC. */
428 mpt_req->MsgContext = req->index;
430 /* Which physical device to do the I/O on */
431 mpt_req->TargetID = ccb->ccb_h.target_id;
432 mpt_req->LUN[1] = ccb->ccb_h.target_lun;
434 /* Set the direction of the transfer */
435 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
436 mpt_req->Control = MPI_SCSIIO_CONTROL_READ;
437 else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
438 mpt_req->Control = MPI_SCSIIO_CONTROL_WRITE;
440 mpt_req->Control = MPI_SCSIIO_CONTROL_NODATATRANSFER;
442 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) {
443 switch(ccb->csio.tag_action) {
444 case MSG_HEAD_OF_Q_TAG:
445 mpt_req->Control |= MPI_SCSIIO_CONTROL_HEADOFQ;
448 mpt_req->Control |= MPI_SCSIIO_CONTROL_ACAQ;
450 case MSG_ORDERED_Q_TAG:
451 mpt_req->Control |= MPI_SCSIIO_CONTROL_ORDEREDQ;
453 case MSG_SIMPLE_Q_TAG:
455 mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
460 mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
462 mpt_req->Control |= MPI_SCSIIO_CONTROL_UNTAGGED;
465 if (mpt->is_fc == 0) {
466 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
467 mpt_req->Control |= MPI_SCSIIO_CONTROL_NO_DISCONNECT;
471 /* Copy the scsi command block into place */
472 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0)
473 bcopy(csio->cdb_io.cdb_ptr, mpt_req->CDB, csio->cdb_len);
475 bcopy(csio->cdb_io.cdb_bytes, mpt_req->CDB, csio->cdb_len);
477 mpt_req->CDBLength = csio->cdb_len;
478 mpt_req->DataLength = csio->dxfer_len;
479 mpt_req->SenseBufferLowAddr = req->sense_pbuf;
482 * If we have any data to send with this command,
483 * map it into bus space.
486 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
487 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {
489 * We've been given a pointer to a single buffer.
491 if ((ccbh->flags & CAM_DATA_PHYS) == 0) {
493 * Virtual address that needs to translated into
494 * one or more physical pages.
498 error = bus_dmamap_load(mpt->buffer_dmat,
499 req->dmap, csio->data_ptr, csio->dxfer_len,
500 mpt_execute_req, req, 0);
501 if (error == EINPROGRESS) {
503 * So as to maintain ordering,
504 * freeze the controller queue
505 * until our mapping is
508 xpt_freeze_simq(mpt->sim, 1);
509 ccbh->status |= CAM_RELEASE_SIMQ;
513 * We have been given a pointer to single
516 struct bus_dma_segment seg;
517 seg.ds_addr = (bus_addr_t)csio->data_ptr;
518 seg.ds_len = csio->dxfer_len;
519 mpt_execute_req(req, &seg, 1, 0);
523 * We have been given a list of addresses.
524 * These case could be easily done but they are not
525 * currently generated by the CAM subsystem so there
526 * is no point in wasting the time right now.
528 struct bus_dma_segment *segs;
529 if ((ccbh->flags & CAM_SG_LIST_PHYS) == 0) {
530 mpt_execute_req(req, NULL, 0, EFAULT);
532 /* Just use the segments provided */
533 segs = (struct bus_dma_segment *)csio->data_ptr;
534 mpt_execute_req(req, segs, csio->sglist_cnt,
535 (csio->sglist_cnt < MPT_SGL_MAX)?
540 mpt_execute_req(req, NULL, 0, 0);
545 mpt_bus_reset(union ccb *ccb)
550 MSG_SCSI_TASK_MGMT *reset_req;
552 /* Get the pointer for the physical adapter */
553 mpt = ccb->ccb_h.ccb_mpt_ptr;
555 /* Get a request structure off the free list */
556 if ((req = mpt_get_request(mpt)) == NULL) {
557 return (CAM_REQUEUE_REQ);
560 /* Link the ccb and the request structure so we can find */
561 /* the other knowing either the request or the ccb */
563 ccb->ccb_h.ccb_req_ptr = req;
565 reset_req = req->req_vbuf;
566 bzero(reset_req, sizeof *reset_req);
568 reset_req->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
569 reset_req->MsgContext = req->index;
570 reset_req->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
573 * Should really be TARGET_RESET_OPTION
575 reset_req->MsgFlags =
576 MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION;
578 /* Which physical device Reset */
579 reset_req->TargetID = ccb->ccb_h.target_id;
580 reset_req->LUN[1] = ccb->ccb_h.target_lun;
582 ccb->ccb_h.status |= CAM_SIM_QUEUED;
584 error = mpt_send_handshake_cmd(mpt,
585 sizeof (MSG_SCSI_TASK_MGMT), reset_req);
587 device_printf(mpt->dev,
588 "mpt_bus_reset: mpt_send_handshake return %d\n", error);
589 return (CAM_REQ_CMP_ERR);
591 return (CAM_REQ_CMP);
596 * Process an asynchronous event from the IOC.
598 static void mpt_ctlop(mpt_softc_t *, void *, u_int32_t);
599 static void mpt_event_notify_reply(mpt_softc_t *mpt, MSG_EVENT_NOTIFY_REPLY *);
602 mpt_ctlop(mpt_softc_t *mpt, void *vmsg, u_int32_t reply)
604 MSG_DEFAULT_REPLY *dmsg = vmsg;
606 if (dmsg->Function == MPI_FUNCTION_EVENT_NOTIFICATION) {
607 mpt_event_notify_reply(mpt, vmsg);
608 mpt_free_reply(mpt, (reply << 1));
609 } else if (dmsg->Function == MPI_FUNCTION_EVENT_ACK) {
610 mpt_free_reply(mpt, (reply << 1));
611 } else if (dmsg->Function == MPI_FUNCTION_PORT_ENABLE) {
612 MSG_PORT_ENABLE_REPLY *msg = vmsg;
613 int index = msg->MsgContext & ~0x80000000;
614 if (mpt->verbose > 1) {
615 device_printf(mpt->dev, "enable port reply idx %d\n",
618 if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) {
619 request_t *req = &mpt->request_pool[index];
620 req->debug = REQ_DONE;
622 mpt_free_reply(mpt, (reply << 1));
623 } else if (dmsg->Function == MPI_FUNCTION_CONFIG) {
624 MSG_CONFIG_REPLY *msg = vmsg;
625 int index = msg->MsgContext & ~0x80000000;
626 if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) {
627 request_t *req = &mpt->request_pool[index];
628 req->debug = REQ_DONE;
629 req->sequence = reply;
631 mpt_free_reply(mpt, (reply << 1));
634 device_printf(mpt->dev, "unknown mpt_ctlop: %x\n",
640 mpt_event_notify_reply(mpt_softc_t *mpt, MSG_EVENT_NOTIFY_REPLY *msg)
643 case MPI_EVENT_LOG_DATA:
644 /* Some error occured that LSI wants logged */
645 device_printf(mpt->dev,
646 "\tEvtLogData: IOCLogInfo: 0x%08x\n",
648 device_printf(mpt->dev, "\tEvtLogData: Event Data:");
651 for (i = 0; i < msg->EventDataLength; i++) {
652 device_printf(mpt->dev,
653 " %08X", msg->Data[i]);
656 device_printf(mpt->dev, "\n");
659 case MPI_EVENT_UNIT_ATTENTION:
660 device_printf(mpt->dev,
661 "Bus: 0x%02x TargetID: 0x%02x\n",
662 (msg->Data[0] >> 8) & 0xff, msg->Data[0] & 0xff);
665 case MPI_EVENT_IOC_BUS_RESET:
666 /* We generated a bus reset */
667 device_printf(mpt->dev, "IOC Bus Reset Port: %d\n",
668 (msg->Data[0] >> 8) & 0xff);
671 case MPI_EVENT_EXT_BUS_RESET:
672 /* Someone else generated a bus reset */
673 device_printf(mpt->dev, "Ext Bus Reset\n");
675 * These replies don't return EventData like the MPI
678 /* xpt_async(AC_BUS_RESET, path, NULL); */
681 case MPI_EVENT_RESCAN:
683 * In general this means a device has been added
686 device_printf(mpt->dev,
687 "Rescan Port: %d\n", (msg->Data[0] >> 8) & 0xff);
688 /* xpt_async(AC_FOUND_DEVICE, path, NULL); */
691 case MPI_EVENT_LINK_STATUS_CHANGE:
692 device_printf(mpt->dev, "Port %d: LinkState: %s\n",
693 (msg->Data[1] >> 8) & 0xff,
694 ((msg->Data[0] & 0xff) == 0)? "Failed" : "Active");
697 case MPI_EVENT_LOOP_STATE_CHANGE:
698 switch ((msg->Data[0] >> 16) & 0xff) {
700 device_printf(mpt->dev,
701 "Port 0x%x: FC LinkEvent: LIP(%02X,%02X) (Loop Initialization)\n",
702 (msg->Data[1] >> 8) & 0xff,
703 (msg->Data[0] >> 8) & 0xff,
704 (msg->Data[0] ) & 0xff);
705 switch ((msg->Data[0] >> 8) & 0xff) {
707 if ((msg->Data[0] & 0xff) == 0xF7) {
708 printf("Device needs AL_PA\n");
710 printf("Device %02X doesn't like FC performance\n",
711 msg->Data[0] & 0xFF);
715 if ((msg->Data[0] & 0xff) == 0xF7) {
716 printf("Device had loop failure at its receiver prior to acquiring AL_PA\n");
718 printf("Device %02X detected loop failure at its receiver\n",
719 msg->Data[0] & 0xFF);
723 printf("Device %02X requests that device %02X reset itself\n",
725 (msg->Data[0] >> 8) & 0xFF);
730 device_printf(mpt->dev, "Port 0x%x: FC LinkEvent: LPE(%02X,%02X) (Loop Port Enable)\n",
731 (msg->Data[1] >> 8) & 0xff, /* Port */
732 (msg->Data[0] >> 8) & 0xff, /* Character 3 */
733 (msg->Data[0] ) & 0xff /* Character 4 */
737 device_printf(mpt->dev, "Port 0x%x: FC LinkEvent: LPB(%02X,%02X) (Loop Port Bypass)\n",
738 (msg->Data[1] >> 8) & 0xff, /* Port */
739 (msg->Data[0] >> 8) & 0xff, /* Character 3 */
740 (msg->Data[0] ) & 0xff /* Character 4 */
744 device_printf(mpt->dev, "Port 0x%x: FC LinkEvent: Unknown FC event (%02X %02X %02X)\n",
745 (msg->Data[1] >> 8) & 0xff, /* Port */
746 (msg->Data[0] >> 16) & 0xff, /* Event */
747 (msg->Data[0] >> 8) & 0xff, /* Character 3 */
748 (msg->Data[0] ) & 0xff /* Character 4 */
753 case MPI_EVENT_LOGOUT:
754 device_printf(mpt->dev, "FC Logout Port: %d N_PortID: %02X\n",
755 (msg->Data[1] >> 8) & 0xff,
758 case MPI_EVENT_EVENT_CHANGE:
759 /* This is just an acknowledgement of our
760 mpt_send_event_request */
763 device_printf(mpt->dev, "Unknown event %X\n", msg->Event);
765 if (msg->AckRequired) {
768 if ((req = mpt_get_request(mpt)) == NULL) {
769 panic("unable to get request to acknowledge notify");
771 ackp = (MSG_EVENT_ACK *) req->req_vbuf;
772 bzero(ackp, sizeof *ackp);
773 ackp->Function = MPI_FUNCTION_EVENT_ACK;
774 ackp->Event = msg->Event;
775 ackp->EventContext = msg->EventContext;
776 ackp->MsgContext = req->index | 0x80000000;
777 mpt_check_doorbell(mpt);
778 mpt_send_cmd(mpt, req);
783 mpt_done(mpt_softc_t *mpt, u_int32_t reply)
788 MSG_REQUEST_HEADER *mpt_req;
789 MSG_SCSI_IO_REPLY *mpt_reply;
791 index = -1; /* Shutup the complier */
793 if ((reply & MPT_CONTEXT_REPLY) == 0) {
796 index = reply & MPT_CONTEXT_MASK;
800 bus_dmamap_sync(mpt->reply_dmat, mpt->reply_dmap,
801 BUS_DMASYNC_POSTREAD);
802 /* address reply (Error) */
803 mpt_reply = MPT_REPLY_PTOV(mpt, reply);
804 if (mpt->verbose > 1) {
805 pReply = (unsigned *) mpt_reply;
806 device_printf(mpt->dev, "Address Reply (index %u)\n",
807 mpt_reply->MsgContext & 0xffff);
808 device_printf(mpt->dev, "%08X %08X %08X %08X\n",
809 pReply[0], pReply[1], pReply[2], pReply[3]);
810 device_printf(mpt->dev, "%08X %08X %08X %08X\n",
811 pReply[4], pReply[5], pReply[6], pReply[7]);
812 device_printf(mpt->dev, "%08X %08X %08X %08X\n\n",
813 pReply[8], pReply[9], pReply[10], pReply[11]);
815 index = mpt_reply->MsgContext;
819 * Address reply with MessageContext high bit set
820 * This is most likely a notify message so we try
821 * to process it then free it
823 if ((index & 0x80000000) != 0) {
824 if (mpt_reply != NULL) {
825 mpt_ctlop(mpt, mpt_reply, reply);
827 device_printf(mpt->dev,
828 "mpt_done: index 0x%x, NULL reply\n", index);
833 /* Did we end up with a valid index into the table? */
834 if (index < 0 || index >= MPT_MAX_REQUESTS(mpt)) {
835 printf("mpt_done: invalid index (%x) in reply\n", index);
839 req = &mpt->request_pool[index];
841 /* Make sure memory hasn't been trashed */
842 if (req->index != index) {
843 printf("mpt_done: corrupted request struct");
847 /* Short cut for task management replys; nothing more for us to do */
848 mpt_req = req->req_vbuf;
849 if (mpt_req->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
850 if (mpt->verbose > 1) {
851 device_printf(mpt->dev, "mpt_done: TASK MGMT\n");
856 if (mpt_req->Function == MPI_FUNCTION_PORT_ENABLE) {
861 * At this point it better be a SCSI IO command, but don't
864 if (mpt_req->Function != MPI_FUNCTION_SCSI_IO_REQUEST) {
868 /* Recover the CAM control block from the request structure */
871 /* Can't have had a SCSI command with out a CAM control block */
872 if (ccb == NULL || (ccb->ccb_h.status & CAM_SIM_QUEUED) == 0) {
873 device_printf(mpt->dev,
874 "mpt_done: corrupted ccb, index = 0x%02x seq = 0x%08x",
875 req->index, req->sequence);
876 printf(" request state %s\nmpt_request:\n",
877 mpt_req_state(req->debug));
878 mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);
880 if (mpt_reply != NULL) {
881 printf("\nmpt_done: reply:\n");
882 mpt_print_reply(MPT_REPLY_PTOV(mpt, reply));
884 printf("\nmpt_done: context reply: 0x%08x\n", reply);
889 untimeout(mpttimeout, ccb, ccb->ccb_h.timeout_ch);
891 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
894 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
895 op = BUS_DMASYNC_POSTREAD;
897 op = BUS_DMASYNC_POSTWRITE;
899 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
900 bus_dmamap_unload(mpt->buffer_dmat, req->dmap);
904 if (mpt_reply == NULL) {
905 /* Context reply; report that the command was successfull */
906 ccb->ccb_h.status = CAM_REQ_CMP;
907 ccb->csio.scsi_status = SCSI_STATUS_OK;
908 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
909 if (mpt->outofbeer) {
910 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
912 if (mpt->verbose > 1) {
913 device_printf(mpt->dev, "THAWQ\n");
916 MPTLOCK_2_CAMLOCK(mpt);
918 CAMLOCK_2_MPTLOCK(mpt);
922 ccb->csio.scsi_status = mpt_reply->SCSIStatus;
923 switch(mpt_reply->IOCStatus) {
924 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
925 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
928 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
930 * Yikes, Tagged queue full comes through this path!
932 * So we'll change it to a status error and anything
933 * that returns status should probably be a status
937 ccb->csio.dxfer_len - mpt_reply->TransferCount;
938 if (mpt_reply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) {
939 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
943 device_printf(mpt->dev, "underrun, scsi status is %x\n", ccb->csio.scsi_status);
944 ccb->csio.scsi_status = SCSI_STATUS_QUEUE_FULL;
947 case MPI_IOCSTATUS_SUCCESS:
948 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:
949 switch (ccb->csio.scsi_status) {
951 ccb->ccb_h.status = CAM_REQ_CMP;
954 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
958 case MPI_IOCSTATUS_BUSY:
959 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
960 ccb->ccb_h.status = CAM_BUSY;
963 case MPI_IOCSTATUS_SCSI_INVALID_BUS:
964 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
965 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
966 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
969 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
970 ccb->ccb_h.status = CAM_DATA_RUN_ERR;
973 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:
974 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:
975 ccb->ccb_h.status = CAM_UNCOR_PARITY;
978 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
979 ccb->ccb_h.status = CAM_REQ_CMP;
982 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
983 ccb->ccb_h.status = CAM_UA_TERMIO;
986 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
987 ccb->ccb_h.status = CAM_REQ_TERMIO;
990 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
991 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
995 ccb->ccb_h.status = CAM_UNREC_HBA_ERROR;
999 if ((mpt_reply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) != 0) {
1000 if (ccb->ccb_h.flags & (CAM_SENSE_PHYS | CAM_SENSE_PTR)) {
1001 ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
1003 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
1004 ccb->csio.sense_resid = mpt_reply->SenseCount;
1005 bcopy(req->sense_vbuf, &ccb->csio.sense_data,
1006 ccb->csio.sense_len);
1008 } else if (mpt_reply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
1009 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1010 ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
1013 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1014 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1015 ccb->ccb_h.status |= CAM_DEV_QFRZN;
1016 xpt_freeze_devq(ccb->ccb_h.path, 1);
1021 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1022 if (mpt->outofbeer) {
1023 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1025 if (mpt->verbose > 1) {
1026 device_printf(mpt->dev, "THAWQ\n");
1029 MPTLOCK_2_CAMLOCK(mpt);
1031 CAMLOCK_2_MPTLOCK(mpt);
1034 /* If IOC done with this request free it up */
1035 if (mpt_reply == NULL || (mpt_reply->MsgFlags & 0x80) == 0)
1036 mpt_free_request(mpt, req);
1038 /* If address reply; give the buffer back to the IOC */
1039 if (mpt_reply != NULL)
1040 mpt_free_reply(mpt, (reply << 1));
1044 mpt_action(struct cam_sim *sim, union ccb *ccb)
1048 struct ccb_trans_settings *cts;
1050 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mpt_action\n"));
1052 mpt = (mpt_softc_t *)cam_sim_softc(sim);
1054 ccb->ccb_h.ccb_mpt_ptr = mpt;
1056 switch (ccb->ccb_h.func_code) {
1058 if (mpt->verbose > 1)
1059 device_printf(mpt->dev, "XPT_RESET_BUS\n");
1060 CAMLOCK_2_MPTLOCK(mpt);
1061 error = mpt_bus_reset(ccb);
1063 case CAM_REQ_INPROG:
1064 MPTLOCK_2_CAMLOCK(mpt);
1066 case CAM_REQUEUE_REQ:
1067 if (mpt->outofbeer == 0) {
1069 xpt_freeze_simq(sim, 1);
1070 if (mpt->verbose > 1) {
1071 device_printf(mpt->dev, "FREEZEQ\n");
1074 ccb->ccb_h.status = CAM_REQUEUE_REQ;
1075 MPTLOCK_2_CAMLOCK(mpt);
1080 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1081 ccb->ccb_h.status |= CAM_REQ_CMP;
1082 if (mpt->outofbeer) {
1083 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1085 if (mpt->verbose > 1) {
1086 device_printf(mpt->dev, "THAWQ\n");
1089 MPTLOCK_2_CAMLOCK(mpt);
1094 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1095 MPTLOCK_2_CAMLOCK(mpt);
1100 case XPT_SCSI_IO: /* Execute the requested I/O operation */
1102 * Do a couple of preliminary checks...
1104 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1105 if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
1106 ccb->ccb_h.status = CAM_REQ_INVALID;
1111 /* Max supported CDB length is 16 bytes */
1112 if (ccb->csio.cdb_len >
1113 sizeof (((PTR_MSG_SCSI_IO_REQUEST)0)->CDB)) {
1114 ccb->ccb_h.status = CAM_REQ_INVALID;
1118 ccb->csio.scsi_status = SCSI_STATUS_OK;
1124 * XXX: Need to implement
1126 ccb->ccb_h.status = CAM_UA_ABORT;
1130 #ifdef CAM_NEW_TRAN_CODE
1131 #define IS_CURRENT_SETTINGS(c) (c->type == CTS_TYPE_CURRENT_SETTINGS)
1133 #define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS)
1135 #define DP_DISC_ENABLE 0x1
1136 #define DP_DISC_DISABL 0x2
1137 #define DP_DISC (DP_DISC_ENABLE|DP_DISC_DISABL)
1139 #define DP_TQING_ENABLE 0x4
1140 #define DP_TQING_DISABL 0x8
1141 #define DP_TQING (DP_TQING_ENABLE|DP_TQING_DISABL)
1143 #define DP_WIDE 0x10
1144 #define DP_NARROW 0x20
1145 #define DP_WIDTH (DP_WIDE|DP_NARROW)
1147 #define DP_SYNC 0x40
1149 case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */
1151 if (!IS_CURRENT_SETTINGS(cts)) {
1152 ccb->ccb_h.status = CAM_REQ_INVALID;
1156 tgt = cts->ccb_h.target_id;
1157 if (mpt->is_fc == 0) {
1159 u_int period = 0, offset = 0;
1160 #ifndef CAM_NEW_TRAN_CODE
1161 if (cts->valid & CCB_TRANS_DISC_VALID) {
1162 dval |= DP_DISC_ENABLE;
1164 if (cts->valid & CCB_TRANS_TQ_VALID) {
1165 dval |= DP_TQING_ENABLE;
1167 if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
1174 * Any SYNC RATE of nonzero and SYNC_OFFSET
1175 * of nonzero will cause us to go to the
1176 * selected (from NVRAM) maximum value for
1177 * this device. At a later point, we'll
1178 * allow finer control.
1180 if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
1181 (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)) {
1183 period = cts->sync_period;
1184 offset = cts->sync_offset;
1187 struct ccb_trans_settings_scsi *scsi =
1188 &cts->proto_specific.scsi;
1189 struct ccb_trans_settings_spi *spi =
1190 &cts->xport_specific.spi;
1192 if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
1193 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
1194 dval |= DP_DISC_ENABLE;
1196 dval |= DP_DISC_DISABL;
1199 if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
1200 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
1201 dval |= DP_TQING_ENABLE;
1203 dval |= DP_TQING_DISABL;
1206 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
1207 if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT)
1213 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) &&
1214 (spi->valid & CTS_SPI_VALID_SYNC_RATE) &&
1215 (spi->sync_period && spi->sync_offset)) {
1217 period = spi->sync_period;
1218 offset = spi->sync_offset;
1221 CAMLOCK_2_MPTLOCK(mpt);
1222 if (dval & DP_DISC_ENABLE) {
1223 mpt->mpt_disc_enable |= (1 << tgt);
1224 } else if (dval & DP_DISC_DISABL) {
1225 mpt->mpt_disc_enable &= ~(1 << tgt);
1227 if (dval & DP_TQING_ENABLE) {
1228 mpt->mpt_tag_enable |= (1 << tgt);
1229 } else if (dval & DP_TQING_DISABL) {
1230 mpt->mpt_tag_enable &= ~(1 << tgt);
1232 if (dval & DP_WIDTH) {
1233 if (mpt_setwidth(mpt, tgt, dval & DP_WIDE)) {
1234 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1235 MPTLOCK_2_CAMLOCK(mpt);
1240 if (dval & DP_SYNC) {
1241 if (mpt_setsync(mpt, tgt, period, offset)) {
1242 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1243 MPTLOCK_2_CAMLOCK(mpt);
1248 MPTLOCK_2_CAMLOCK(mpt);
1249 if (mpt->verbose > 1) {
1250 device_printf(mpt->dev,
1251 "SET tgt %d flags %x period %x off %x\n",
1252 tgt, dval, period, offset);
1255 ccb->ccb_h.status = CAM_REQ_CMP;
1259 case XPT_GET_TRAN_SETTINGS:
1261 tgt = cts->ccb_h.target_id;
1263 #ifndef CAM_NEW_TRAN_CODE
1265 * a lot of normal SCSI things don't make sense.
1267 cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
1268 cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
1270 * How do you measure the width of a high
1271 * speed serial bus? Well, in bytes.
1273 * Offset and period make no sense, though, so we set
1274 * (above) a 'base' transfer speed to be gigabit.
1276 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1278 struct ccb_trans_settings_fc *fc =
1279 &cts->xport_specific.fc;
1281 cts->protocol = PROTO_SCSI;
1282 cts->protocol_version = SCSI_REV_2;
1283 cts->transport = XPORT_FC;
1284 cts->transport_version = 0;
1286 fc->valid = CTS_FC_VALID_SPEED;
1287 fc->bitrate = 100000; /* XXX: Need for 2Gb/s */
1288 /* XXX: need a port database for each target */
1291 #ifdef CAM_NEW_TRAN_CODE
1292 struct ccb_trans_settings_scsi *scsi =
1293 &cts->proto_specific.scsi;
1294 struct ccb_trans_settings_spi *spi =
1295 &cts->xport_specific.spi;
1297 u_int8_t dval, pval, oval;
1300 * We aren't going off of Port PAGE2 params for
1301 * tagged queuing or disconnect capabilities
1302 * for current settings. For goal settings,
1303 * we assert all capabilities- we've had some
1304 * problems with reading NVRAM data.
1306 if (IS_CURRENT_SETTINGS(cts)) {
1307 fCONFIG_PAGE_SCSI_DEVICE_0 tmp;
1310 tmp = mpt->mpt_dev_page0[tgt];
1311 CAMLOCK_2_MPTLOCK(mpt);
1312 if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) {
1313 device_printf(mpt->dev,
1314 "cannot get target %d DP0\n", tgt);
1316 if (mpt->verbose > 1) {
1317 device_printf(mpt->dev,
1318 "SPI Tgt %d Page 0: NParms %x Information %x\n",
1320 tmp.NegotiatedParameters,
1324 MPTLOCK_2_CAMLOCK(mpt);
1326 if (tmp.NegotiatedParameters &
1327 MPI_SCSIDEVPAGE0_NP_WIDE)
1330 if (mpt->mpt_disc_enable & (1 << tgt)) {
1331 dval |= DP_DISC_ENABLE;
1333 if (mpt->mpt_tag_enable & (1 << tgt)) {
1334 dval |= DP_TQING_ENABLE;
1336 oval = (tmp.NegotiatedParameters >> 16) & 0xff;
1337 pval = (tmp.NegotiatedParameters >> 8) & 0xff;
1340 * XXX: Fix wrt NVRAM someday. Attempts
1341 * XXX: to read port page2 device data
1342 * XXX: just returns zero in these areas.
1344 dval = DP_WIDE|DP_DISC|DP_TQING;
1345 oval = (mpt->mpt_port_page0.Capabilities >> 16);
1346 pval = (mpt->mpt_port_page0.Capabilities >> 8);
1348 #ifndef CAM_NEW_TRAN_CODE
1349 cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
1350 if (dval & DP_DISC_ENABLE) {
1351 cts->flags |= CCB_TRANS_DISC_ENB;
1353 if (dval & DP_TQING_ENABLE) {
1354 cts->flags |= CCB_TRANS_TAG_ENB;
1356 if (dval & DP_WIDE) {
1357 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1359 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1361 cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
1362 CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
1364 cts->sync_period = pval;
1365 cts->sync_offset = oval;
1367 CCB_TRANS_SYNC_RATE_VALID |
1368 CCB_TRANS_SYNC_OFFSET_VALID;
1371 cts->protocol = PROTO_SCSI;
1372 cts->protocol_version = SCSI_REV_2;
1373 cts->transport = XPORT_SPI;
1374 cts->transport_version = 2;
1376 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
1377 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
1378 if (dval & DP_DISC_ENABLE) {
1379 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
1381 if (dval & DP_TQING_ENABLE) {
1382 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
1385 spi->sync_offset = oval;
1386 spi->sync_period = pval;
1387 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
1388 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
1390 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
1391 if (dval & DP_WIDE) {
1392 spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1394 spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1396 if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
1397 scsi->valid = CTS_SCSI_VALID_TQ;
1398 spi->valid |= CTS_SPI_VALID_DISC;
1403 if (mpt->verbose > 1) {
1404 device_printf(mpt->dev,
1405 "GET %s tgt %d flags %x period %x off %x\n",
1406 IS_CURRENT_SETTINGS(cts)? "ACTIVE" :
1407 "NVRAM", tgt, dval, pval, oval);
1410 ccb->ccb_h.status = CAM_REQ_CMP;
1414 case XPT_CALC_GEOMETRY:
1416 struct ccb_calc_geometry *ccg;
1417 u_int32_t secs_per_cylinder;
1421 if (ccg->block_size == 0) {
1422 ccb->ccb_h.status = CAM_REQ_INVALID;
1427 size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
1428 if (size_mb > 1024) {
1430 ccg->secs_per_track = 63;
1433 ccg->secs_per_track = 32;
1435 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
1436 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
1437 ccb->ccb_h.status = CAM_REQ_CMP;
1441 case XPT_PATH_INQ: /* Path routing inquiry */
1443 struct ccb_pathinq *cpi = &ccb->cpi;
1445 cpi->version_num = 1;
1446 cpi->target_sprt = 0;
1447 cpi->hba_eng_cnt = 0;
1449 cpi->bus_id = cam_sim_bus(sim);
1451 cpi->max_target = 255;
1452 cpi->hba_misc = PIM_NOBUSRESET;
1453 cpi->initiator_id = cpi->max_target + 1;
1454 cpi->base_transfer_speed = 100000;
1455 cpi->hba_inquiry = PI_TAG_ABLE;
1457 cpi->initiator_id = mpt->mpt_ini_id;
1458 cpi->base_transfer_speed = 3300;
1459 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
1461 cpi->max_target = 15;
1464 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1465 strncpy(cpi->hba_vid, "LSI", HBA_IDLEN);
1466 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1467 cpi->unit_number = cam_sim_unit(sim);
1468 cpi->ccb_h.status = CAM_REQ_CMP;
1473 ccb->ccb_h.status = CAM_REQ_INVALID;
1480 mpt_setwidth(mpt_softc_t *mpt, int tgt, int onoff)
1482 fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
1483 tmp = mpt->mpt_dev_page1[tgt];
1485 tmp.RequestedParameters |= MPI_SCSIDEVPAGE1_RP_WIDE;
1487 tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_WIDE;
1489 if (mpt_write_cfg_page(mpt, tgt, &tmp.Header)) {
1492 if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) {
1495 mpt->mpt_dev_page1[tgt] = tmp;
1496 if (mpt->verbose > 1) {
1497 device_printf(mpt->dev,
1498 "SPI Target %d Page 1: RequestedParameters %x Config %x\n",
1499 tgt, mpt->mpt_dev_page1[tgt].RequestedParameters,
1500 mpt->mpt_dev_page1[tgt].Configuration);
1506 mpt_setsync(mpt_softc_t *mpt, int tgt, int period, int offset)
1508 fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
1509 tmp = mpt->mpt_dev_page1[tgt];
1510 tmp.RequestedParameters &=
1511 ~MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
1512 tmp.RequestedParameters &=
1513 ~MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
1514 tmp.RequestedParameters &=
1515 ~MPI_SCSIDEVPAGE1_RP_DT;
1516 tmp.RequestedParameters &=
1517 ~MPI_SCSIDEVPAGE1_RP_QAS;
1518 tmp.RequestedParameters &=
1519 ~MPI_SCSIDEVPAGE1_RP_IU;
1521 * XXX: For now, we're ignoring specific settings
1523 if (period && offset) {
1524 int factor, offset, np;
1525 factor = (mpt->mpt_port_page0.Capabilities >> 8) & 0xff;
1526 offset = (mpt->mpt_port_page0.Capabilities >> 16) & 0xff;
1529 np |= MPI_SCSIDEVPAGE1_RP_QAS;
1530 np |= MPI_SCSIDEVPAGE1_RP_IU;
1533 np |= MPI_SCSIDEVPAGE1_RP_DT;
1535 np |= (factor << 8) | (offset << 16);
1536 tmp.RequestedParameters |= np;
1538 if (mpt_write_cfg_page(mpt, tgt, &tmp.Header)) {
1541 if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) {
1544 mpt->mpt_dev_page1[tgt] = tmp;
1545 if (mpt->verbose > 1) {
1546 device_printf(mpt->dev,
1547 "SPI Target %d Page 1: RParams %x Config %x\n",
1548 tgt, mpt->mpt_dev_page1[tgt].RequestedParameters,
1549 mpt->mpt_dev_page1[tgt].Configuration);