2 * Bus independent FreeBSD shim for the aic79xx based Adaptec SCSI controllers
4 * Copyright (c) 1994-2002, 2004 Justin T. Gibbs.
5 * Copyright (c) 2001-2002 Adaptec Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions, and the following disclaimer,
13 * without modification.
14 * 2. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * Alternatively, this software may be distributed under the terms of the
18 * GNU Public License ("GPL").
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.c#35 $
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
38 #include <dev/aic7xxx/aic79xx_osm.h>
39 #include <dev/aic7xxx/aic79xx_inline.h>
41 #include <sys/kthread.h>
48 #ifndef AHD_TMODE_ENABLE
49 #define AHD_TMODE_ENABLE 0
52 #include <dev/aic7xxx/aic_osm_lib.c>
54 #define ccb_scb_ptr spriv_ptr0
57 static void ahd_dump_targcmd(struct target_cmd *cmd);
59 static int ahd_modevent(module_t mod, int type, void *data);
60 static void ahd_action(struct cam_sim *sim, union ccb *ccb);
61 static void ahd_set_tran_settings(struct ahd_softc *ahd,
62 int our_id, char channel,
63 struct ccb_trans_settings *cts);
64 static void ahd_get_tran_settings(struct ahd_softc *ahd,
65 int our_id, char channel,
66 struct ccb_trans_settings *cts);
67 static void ahd_async(void *callback_arg, uint32_t code,
68 struct cam_path *path, void *arg);
69 static void ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
70 int nsegments, int error);
71 static void ahd_poll(struct cam_sim *sim);
72 static void ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
73 struct ccb_scsiio *csio, struct scb *scb);
74 static void ahd_abort_ccb(struct ahd_softc *ahd, struct cam_sim *sim,
76 static int ahd_create_path(struct ahd_softc *ahd,
77 char channel, u_int target, u_int lun,
78 struct cam_path **path);
81 ahd_create_path(struct ahd_softc *ahd, char channel, u_int target,
82 u_int lun, struct cam_path **path)
86 path_id = cam_sim_path(ahd->platform_data->sim);
87 return (xpt_create_path(path, /*periph*/NULL,
88 path_id, target, lun));
92 ahd_map_int(struct ahd_softc *ahd)
96 /* Hook up our interrupt handler */
97 error = bus_setup_intr(ahd->dev_softc, ahd->platform_data->irq,
98 INTR_TYPE_CAM|INTR_MPSAFE, NULL,
99 ahd_platform_intr, ahd, &ahd->platform_data->ih);
101 device_printf(ahd->dev_softc, "bus_setup_intr() failed: %d\n",
107 * Attach all the sub-devices we can find
110 ahd_attach(struct ahd_softc *ahd)
113 struct ccb_setasync csa;
114 struct cam_devq *devq;
116 struct cam_path *path;
124 * Create a thread to perform all recovery.
126 if (ahd_spawn_recovery_thread(ahd) != 0)
129 ahd_controller_info(ahd, ahd_info);
130 printf("%s\n", ahd_info);
134 * Create the device queue for our SIM(s).
136 devq = cam_simq_alloc(AHD_MAX_QUEUE);
141 * Construct our SIM entry
143 sim = cam_sim_alloc(ahd_action, ahd_poll, "ahd", ahd,
144 device_get_unit(ahd->dev_softc),
145 &ahd->platform_data->mtx, 1, /*XXX*/256, devq);
151 if (xpt_bus_register(sim, ahd->dev_softc, /*bus_id*/0) != CAM_SUCCESS) {
152 cam_sim_free(sim, /*free_devq*/TRUE);
157 if (xpt_create_path(&path, /*periph*/NULL,
158 cam_sim_path(sim), CAM_TARGET_WILDCARD,
159 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
160 xpt_bus_deregister(cam_sim_path(sim));
161 cam_sim_free(sim, /*free_devq*/TRUE);
166 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
167 csa.ccb_h.func_code = XPT_SASYNC_CB;
168 csa.event_enable = AC_LOST_DEVICE;
169 csa.callback = ahd_async;
170 csa.callback_arg = sim;
171 xpt_action((union ccb *)&csa);
175 ahd->platform_data->sim = sim;
176 ahd->platform_data->path = path;
179 /* We have to wait until after any system dumps... */
180 ahd->platform_data->eh =
181 EVENTHANDLER_REGISTER(shutdown_final, ahd_shutdown,
182 ahd, SHUTDOWN_PRI_DEFAULT);
183 ahd_intr_enable(ahd, TRUE);
191 * Catch an interrupt from the adapter
194 ahd_platform_intr(void *arg)
196 struct ahd_softc *ahd;
198 ahd = (struct ahd_softc *)arg;
205 * We have an scb which has been processed by the
206 * adaptor, now we look to see how the operation
210 ahd_done(struct ahd_softc *ahd, struct scb *scb)
214 CAM_DEBUG(scb->io_ctx->ccb_h.path, CAM_DEBUG_TRACE,
215 ("ahd_done - scb %d\n", SCB_GET_TAG(scb)));
218 LIST_REMOVE(scb, pending_links);
219 if ((scb->flags & SCB_TIMEDOUT) != 0)
220 LIST_REMOVE(scb, timedout_links);
222 callout_stop(&scb->io_timer);
224 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
227 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
228 op = BUS_DMASYNC_POSTREAD;
230 op = BUS_DMASYNC_POSTWRITE;
231 bus_dmamap_sync(ahd->buffer_dmat, scb->dmamap, op);
232 bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap);
235 #ifdef AHD_TARGET_MODE
236 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
237 struct cam_path *ccb_path;
240 * If we have finally disconnected, clean up our
241 * pending device state.
242 * XXX - There may be error states that cause where
243 * we will remain connected.
245 ccb_path = ccb->ccb_h.path;
246 if (ahd->pending_device != NULL
247 && xpt_path_comp(ahd->pending_device->path, ccb_path) == 0) {
249 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
250 ahd->pending_device = NULL;
252 xpt_print_path(ccb->ccb_h.path);
253 printf("Still disconnected\n");
258 if (aic_get_transaction_status(scb) == CAM_REQ_INPROG)
259 ccb->ccb_h.status |= CAM_REQ_CMP;
260 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
261 ahd_free_scb(ahd, scb);
267 if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
268 struct scb *list_scb;
270 ahd->scb_data.recovery_scbs--;
272 if (aic_get_transaction_status(scb) == CAM_BDR_SENT
273 || aic_get_transaction_status(scb) == CAM_REQ_ABORTED)
274 aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
276 if (ahd->scb_data.recovery_scbs == 0) {
278 * All recovery actions have completed successfully,
279 * so reinstate the timeouts for all other pending
282 LIST_FOREACH(list_scb,
283 &ahd->pending_scbs, pending_links) {
285 aic_scb_timer_reset(list_scb,
286 aic_get_timeout(scb));
289 ahd_print_path(ahd, scb);
290 printf("no longer in timeout, status = %x\n",
295 /* Don't clobber any existing error state */
296 if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) {
297 ccb->ccb_h.status |= CAM_REQ_CMP;
298 } else if ((scb->flags & SCB_SENSE) != 0) {
300 * We performed autosense retrieval.
302 * Zero any sense not transferred by the
303 * device. The SCSI spec mandates that any
304 * untransfered data should be assumed to be
305 * zero. Complete the 'bounce' of sense information
306 * through buffers accessible via bus-space by
307 * copying it into the clients csio.
309 memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
310 memcpy(&ccb->csio.sense_data,
311 ahd_get_sense_buf(ahd, scb),
312 /* XXX What size do we want to use??? */
313 sizeof(ccb->csio.sense_data)
314 - ccb->csio.sense_resid);
315 scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID;
316 } else if ((scb->flags & SCB_PKT_SENSE) != 0) {
317 struct scsi_status_iu_header *siu;
321 * Copy only the sense data into the provided buffer.
323 siu = (struct scsi_status_iu_header *)scb->sense_data;
324 sense_len = MIN(scsi_4btoul(siu->sense_length),
325 sizeof(ccb->csio.sense_data));
326 memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
327 memcpy(&ccb->csio.sense_data,
328 ahd_get_sense_buf(ahd, scb) + SIU_SENSE_OFFSET(siu),
331 if ((ahd_debug & AHD_SHOW_SENSE) != 0) {
332 uint8_t *sense_data = (uint8_t *)&ccb->csio.sense_data;
335 printf("Copied %d bytes of sense data offset %d:",
336 sense_len, SIU_SENSE_OFFSET(siu));
337 for (i = 0; i < sense_len; i++)
338 printf(" 0x%x", *sense_data++);
342 scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID;
344 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
345 ahd_free_scb(ahd, scb);
350 ahd_action(struct cam_sim *sim, union ccb *ccb)
352 struct ahd_softc *ahd;
353 #ifdef AHD_TARGET_MODE
354 struct ahd_tmode_lstate *lstate;
359 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahd_action\n"));
361 ahd = (struct ahd_softc *)cam_sim_softc(sim);
363 target_id = ccb->ccb_h.target_id;
364 our_id = SIM_SCSI_ID(ahd, sim);
366 switch (ccb->ccb_h.func_code) {
367 /* Common cases first */
368 #ifdef AHD_TARGET_MODE
369 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
370 case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/
372 struct ahd_tmode_tstate *tstate;
375 status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate,
378 if (status != CAM_REQ_CMP) {
379 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
380 /* Response from the black hole device */
382 lstate = ahd->black_hole;
384 ccb->ccb_h.status = status;
389 if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
391 SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
393 ccb->ccb_h.status = CAM_REQ_INPROG;
394 if ((ahd->flags & AHD_TQINFIFO_BLOCKED) != 0)
395 ahd_run_tqinfifo(ahd, /*paused*/FALSE);
400 * The target_id represents the target we attempt to
401 * select. In target mode, this is the initiator of
402 * the original command.
405 target_id = ccb->csio.init_id;
409 case XPT_SCSI_IO: /* Execute the requested I/O operation */
410 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
413 struct hardware_scb *hscb;
414 struct ahd_initiator_tinfo *tinfo;
415 struct ahd_tmode_tstate *tstate;
418 if ((ahd->flags & AHD_INITIATORROLE) == 0
419 && (ccb->ccb_h.func_code == XPT_SCSI_IO
420 || ccb->ccb_h.func_code == XPT_RESET_DEV)) {
421 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
429 tinfo = ahd_fetch_transinfo(ahd, 'A', our_id,
431 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0
432 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0
433 || ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
434 col_idx = AHD_NEVER_COL_IDX;
436 col_idx = AHD_BUILD_COL_IDX(target_id,
437 ccb->ccb_h.target_lun);
439 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
441 xpt_freeze_simq(sim, /*count*/1);
442 ahd->flags |= AHD_RESOURCE_SHORTAGE;
443 ccb->ccb_h.status = CAM_REQUEUE_REQ;
450 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE,
451 ("start scb(%p)\n", scb));
454 * So we can find the SCB when an abort is requested
456 ccb->ccb_h.ccb_scb_ptr = scb;
459 * Put all the arguments for the xfer in the scb
462 hscb->scsiid = BUILD_SCSIID(ahd, sim, target_id, our_id);
463 hscb->lun = ccb->ccb_h.target_lun;
464 if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
466 scb->flags |= SCB_DEVICE_RESET;
467 hscb->control |= MK_MESSAGE;
468 hscb->task_management = SIU_TASKMGMT_LUN_RESET;
469 ahd_execute_scb(scb, NULL, 0, 0);
471 #ifdef AHD_TARGET_MODE
472 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
473 struct target_data *tdata;
475 tdata = &hscb->shared_data.tdata;
476 if (ahd->pending_device == lstate)
477 scb->flags |= SCB_TARGET_IMMEDIATE;
478 hscb->control |= TARGET_SCB;
479 tdata->target_phases = 0;
480 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
481 tdata->target_phases |= SPHASE_PENDING;
483 ccb->csio.scsi_status;
485 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT)
486 tdata->target_phases |= NO_DISCONNECT;
488 tdata->initiator_tag =
489 ahd_htole16(ccb->csio.tag_id);
492 hscb->task_management = 0;
493 if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID)
494 hscb->control |= ccb->csio.tag_action;
496 ahd_setup_data(ahd, sim, &ccb->csio, scb);
500 #ifdef AHD_TARGET_MODE
502 case XPT_IMMED_NOTIFY:
504 struct ahd_tmode_tstate *tstate;
505 struct ahd_tmode_lstate *lstate;
508 status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate,
511 if (status != CAM_REQ_CMP) {
512 ccb->ccb_h.status = status;
516 SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h,
518 ccb->ccb_h.status = CAM_REQ_INPROG;
519 ahd_send_lstate_events(ahd, lstate);
522 case XPT_EN_LUN: /* Enable LUN as a target */
523 ahd_handle_en_lun(ahd, sim, ccb);
527 case XPT_ABORT: /* Abort the specified CCB */
529 ahd_abort_ccb(ahd, sim, ccb);
532 case XPT_SET_TRAN_SETTINGS:
534 ahd_set_tran_settings(ahd, SIM_SCSI_ID(ahd, sim),
535 SIM_CHANNEL(ahd, sim), &ccb->cts);
539 case XPT_GET_TRAN_SETTINGS:
540 /* Get default/user set transfer settings for the target */
542 ahd_get_tran_settings(ahd, SIM_SCSI_ID(ahd, sim),
543 SIM_CHANNEL(ahd, sim), &ccb->cts);
547 case XPT_CALC_GEOMETRY:
549 aic_calc_geometry(&ccb->ccg, ahd->flags & AHD_EXTENDED_TRANS_A);
553 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
557 found = ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
558 /*initiate reset*/TRUE);
560 xpt_print_path(SIM_PATH(ahd, sim));
561 printf("SCSI bus reset delivered. "
562 "%d SCBs aborted.\n", found);
564 ccb->ccb_h.status = CAM_REQ_CMP;
568 case XPT_TERM_IO: /* Terminate the I/O process */
570 ccb->ccb_h.status = CAM_REQ_INVALID;
573 case XPT_PATH_INQ: /* Path routing inquiry */
575 struct ccb_pathinq *cpi = &ccb->cpi;
577 cpi->version_num = 1; /* XXX??? */
578 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
579 if ((ahd->features & AHD_WIDE) != 0)
580 cpi->hba_inquiry |= PI_WIDE_16;
581 if ((ahd->features & AHD_TARGETMODE) != 0) {
582 cpi->target_sprt = PIT_PROCESSOR
586 cpi->target_sprt = 0;
589 cpi->hba_eng_cnt = 0;
590 cpi->max_target = (ahd->features & AHD_WIDE) ? 15 : 7;
591 cpi->max_lun = AHD_NUM_LUNS_NONPKT - 1;
592 cpi->initiator_id = ahd->our_id;
593 if ((ahd->flags & AHD_RESET_BUS_A) == 0) {
594 cpi->hba_misc |= PIM_NOBUSRESET;
596 cpi->bus_id = cam_sim_bus(sim);
597 cpi->base_transfer_speed = 3300;
598 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
599 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
600 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
601 cpi->unit_number = cam_sim_unit(sim);
602 cpi->protocol = PROTO_SCSI;
603 cpi->protocol_version = SCSI_REV_2;
604 cpi->transport = XPORT_SPI;
605 cpi->transport_version = 4;
606 cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_DT_ST
609 cpi->ccb_h.status = CAM_REQ_CMP;
614 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
622 ahd_set_tran_settings(struct ahd_softc *ahd, int our_id, char channel,
623 struct ccb_trans_settings *cts)
625 struct ahd_devinfo devinfo;
626 struct ccb_trans_settings_scsi *scsi;
627 struct ccb_trans_settings_spi *spi;
628 struct ahd_initiator_tinfo *tinfo;
629 struct ahd_tmode_tstate *tstate;
630 uint16_t *discenable;
634 scsi = &cts->proto_specific.scsi;
635 spi = &cts->xport_specific.spi;
636 ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim),
637 cts->ccb_h.target_id,
638 cts->ccb_h.target_lun,
639 SIM_CHANNEL(ahd, sim),
641 tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
643 devinfo.target, &tstate);
645 if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
646 update_type |= AHD_TRANS_GOAL;
647 discenable = &tstate->discenable;
648 tagenable = &tstate->tagenable;
649 tinfo->curr.protocol_version = cts->protocol_version;
650 tinfo->curr.transport_version = cts->transport_version;
651 tinfo->goal.protocol_version = cts->protocol_version;
652 tinfo->goal.transport_version = cts->transport_version;
653 } else if (cts->type == CTS_TYPE_USER_SETTINGS) {
654 update_type |= AHD_TRANS_USER;
655 discenable = &ahd->user_discenable;
656 tagenable = &ahd->user_tagenable;
657 tinfo->user.protocol_version = cts->protocol_version;
658 tinfo->user.transport_version = cts->transport_version;
660 cts->ccb_h.status = CAM_REQ_INVALID;
664 if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
665 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
666 *discenable |= devinfo.target_mask;
668 *discenable &= ~devinfo.target_mask;
671 if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
672 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
673 *tagenable |= devinfo.target_mask;
675 *tagenable &= ~devinfo.target_mask;
678 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
679 ahd_validate_width(ahd, /*tinfo limit*/NULL,
680 &spi->bus_width, ROLE_UNKNOWN);
681 ahd_set_width(ahd, &devinfo, spi->bus_width,
682 update_type, /*paused*/FALSE);
685 if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) {
686 if (update_type == AHD_TRANS_USER)
687 spi->ppr_options = tinfo->user.ppr_options;
689 spi->ppr_options = tinfo->goal.ppr_options;
692 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) {
693 if (update_type == AHD_TRANS_USER)
694 spi->sync_offset = tinfo->user.offset;
696 spi->sync_offset = tinfo->goal.offset;
699 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) {
700 if (update_type == AHD_TRANS_USER)
701 spi->sync_period = tinfo->user.period;
703 spi->sync_period = tinfo->goal.period;
706 if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0)
707 || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) {
710 maxsync = AHD_SYNCRATE_MAX;
712 if (spi->bus_width != MSG_EXT_WDTR_BUS_16_BIT)
713 spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ;
715 if ((*discenable & devinfo.target_mask) == 0)
716 spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ;
718 ahd_find_syncrate(ahd, &spi->sync_period,
719 &spi->ppr_options, maxsync);
720 ahd_validate_offset(ahd, /*tinfo limit*/NULL,
721 spi->sync_period, &spi->sync_offset,
722 spi->bus_width, ROLE_UNKNOWN);
724 /* We use a period of 0 to represent async */
725 if (spi->sync_offset == 0) {
726 spi->sync_period = 0;
727 spi->ppr_options = 0;
730 ahd_set_syncrate(ahd, &devinfo, spi->sync_period,
731 spi->sync_offset, spi->ppr_options,
732 update_type, /*paused*/FALSE);
734 cts->ccb_h.status = CAM_REQ_CMP;
738 ahd_get_tran_settings(struct ahd_softc *ahd, int our_id, char channel,
739 struct ccb_trans_settings *cts)
741 struct ahd_devinfo devinfo;
742 struct ccb_trans_settings_scsi *scsi;
743 struct ccb_trans_settings_spi *spi;
744 struct ahd_initiator_tinfo *targ_info;
745 struct ahd_tmode_tstate *tstate;
746 struct ahd_transinfo *tinfo;
748 scsi = &cts->proto_specific.scsi;
749 spi = &cts->xport_specific.spi;
750 ahd_compile_devinfo(&devinfo, our_id,
751 cts->ccb_h.target_id,
752 cts->ccb_h.target_lun,
753 channel, ROLE_UNKNOWN);
754 targ_info = ahd_fetch_transinfo(ahd, devinfo.channel,
756 devinfo.target, &tstate);
758 if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
759 tinfo = &targ_info->curr;
761 tinfo = &targ_info->user;
763 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
764 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
765 if (cts->type == CTS_TYPE_USER_SETTINGS) {
766 if ((ahd->user_discenable & devinfo.target_mask) != 0)
767 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
769 if ((ahd->user_tagenable & devinfo.target_mask) != 0)
770 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
772 if ((tstate->discenable & devinfo.target_mask) != 0)
773 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
775 if ((tstate->tagenable & devinfo.target_mask) != 0)
776 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
778 cts->protocol_version = tinfo->protocol_version;
779 cts->transport_version = tinfo->transport_version;
781 spi->sync_period = tinfo->period;
782 spi->sync_offset = tinfo->offset;
783 spi->bus_width = tinfo->width;
784 spi->ppr_options = tinfo->ppr_options;
786 cts->protocol = PROTO_SCSI;
787 cts->transport = XPORT_SPI;
788 spi->valid = CTS_SPI_VALID_SYNC_RATE
789 | CTS_SPI_VALID_SYNC_OFFSET
790 | CTS_SPI_VALID_BUS_WIDTH
791 | CTS_SPI_VALID_PPR_OPTIONS;
793 if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
794 scsi->valid = CTS_SCSI_VALID_TQ;
795 spi->valid |= CTS_SPI_VALID_DISC;
800 cts->ccb_h.status = CAM_REQ_CMP;
804 ahd_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
806 struct ahd_softc *ahd;
809 sim = (struct cam_sim *)callback_arg;
810 ahd = (struct ahd_softc *)cam_sim_softc(sim);
814 struct ahd_devinfo devinfo;
816 ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim),
817 xpt_path_target_id(path),
818 xpt_path_lun_id(path),
819 SIM_CHANNEL(ahd, sim),
823 * Revert to async/narrow transfers
824 * for the next device.
826 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
827 AHD_TRANS_GOAL|AHD_TRANS_CUR, /*paused*/FALSE);
828 ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
829 /*ppr_options*/0, AHD_TRANS_GOAL|AHD_TRANS_CUR,
839 ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
844 struct ahd_softc *ahd;
845 struct ahd_initiator_tinfo *tinfo;
846 struct ahd_tmode_tstate *tstate;
849 scb = (struct scb *)arg;
851 ahd = scb->ahd_softc;
855 aic_set_transaction_status(scb, CAM_REQ_TOO_BIG);
857 aic_set_transaction_status(scb, CAM_REQ_CMP_ERR);
859 bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap);
860 ahd_free_scb(ahd, scb);
865 if (nsegments != 0) {
870 /* Copy the segments into our SG list */
871 for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
873 sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
879 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
880 op = BUS_DMASYNC_PREREAD;
882 op = BUS_DMASYNC_PREWRITE;
884 bus_dmamap_sync(ahd->buffer_dmat, scb->dmamap, op);
886 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
887 struct target_data *tdata;
889 tdata = &scb->hscb->shared_data.tdata;
890 tdata->target_phases |= DPHASE_PENDING;
891 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
892 tdata->data_phase = P_DATAOUT;
894 tdata->data_phase = P_DATAIN;
899 * Last time we need to check if this SCB needs to
902 if (aic_get_transaction_status(scb) != CAM_REQ_INPROG) {
904 bus_dmamap_unload(ahd->buffer_dmat,
906 ahd_free_scb(ahd, scb);
911 tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
912 SCSIID_OUR_ID(scb->hscb->scsiid),
913 SCSIID_TARGET(ahd, scb->hscb->scsiid),
916 mask = SCB_GET_TARGET_MASK(ahd, scb);
918 if ((tstate->discenable & mask) != 0
919 && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
920 scb->hscb->control |= DISCENB;
922 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
923 scb->flags |= SCB_PACKETIZED;
924 if (scb->hscb->task_management != 0)
925 scb->hscb->control &= ~MK_MESSAGE;
928 if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0
929 && (tinfo->goal.width != 0
930 || tinfo->goal.period != 0
931 || tinfo->goal.ppr_options != 0)) {
932 scb->flags |= SCB_NEGOTIATE;
933 scb->hscb->control |= MK_MESSAGE;
934 } else if ((tstate->auto_negotiate & mask) != 0) {
935 scb->flags |= SCB_AUTO_NEGOTIATE;
936 scb->hscb->control |= MK_MESSAGE;
939 LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
941 ccb->ccb_h.status |= CAM_SIM_QUEUED;
943 aic_scb_timer_start(scb);
945 if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
946 /* Define a mapping from our tag to the SCB. */
947 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
949 ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
950 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
953 ahd_queue_scb(ahd, scb);
959 ahd_poll(struct cam_sim *sim)
961 ahd_intr(cam_sim_softc(sim));
965 ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
966 struct ccb_scsiio *csio, struct scb *scb)
968 struct hardware_scb *hscb;
969 struct ccb_hdr *ccb_h;
972 ccb_h = &csio->ccb_h;
975 csio->sense_resid = 0;
976 if (ccb_h->func_code == XPT_SCSI_IO) {
977 hscb->cdb_len = csio->cdb_len;
978 if ((ccb_h->flags & CAM_CDB_POINTER) != 0) {
980 if (hscb->cdb_len > MAX_CDB_LEN
981 && (ccb_h->flags & CAM_CDB_PHYS) == 0) {
984 * Should CAM start to support CDB sizes
985 * greater than 16 bytes, we could use
986 * the sense buffer to store the CDB.
988 aic_set_transaction_status(scb,
990 ahd_free_scb(ahd, scb);
991 xpt_done((union ccb *)csio);
994 if ((ccb_h->flags & CAM_CDB_PHYS) != 0) {
995 hscb->shared_data.idata.cdb_from_host.cdbptr =
996 aic_htole64((uintptr_t)csio->cdb_io.cdb_ptr);
997 hscb->shared_data.idata.cdb_from_host.cdblen =
999 hscb->cdb_len |= SCB_CDB_LEN_PTR;
1001 memcpy(hscb->shared_data.idata.cdb,
1002 csio->cdb_io.cdb_ptr,
1006 if (hscb->cdb_len > MAX_CDB_LEN) {
1008 aic_set_transaction_status(scb,
1010 ahd_free_scb(ahd, scb);
1011 xpt_done((union ccb *)csio);
1014 memcpy(hscb->shared_data.idata.cdb,
1015 csio->cdb_io.cdb_bytes, hscb->cdb_len);
1019 /* Only use S/G if there is a transfer */
1020 if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1021 if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) {
1022 /* We've been given a pointer to a single buffer */
1023 if ((ccb_h->flags & CAM_DATA_PHYS) == 0) {
1028 error = bus_dmamap_load(ahd->buffer_dmat,
1034 if (error == EINPROGRESS) {
1036 * So as to maintain ordering,
1037 * freeze the controller queue
1038 * until our mapping is
1041 xpt_freeze_simq(sim,
1043 scb->io_ctx->ccb_h.status |=
1048 struct bus_dma_segment seg;
1050 /* Pointer to physical buffer */
1051 if (csio->dxfer_len > AHD_MAXTRANSFER_SIZE)
1052 panic("ahd_setup_data - Transfer size "
1053 "larger than can device max");
1056 (bus_addr_t)(vm_offset_t)csio->data_ptr;
1057 seg.ds_len = csio->dxfer_len;
1058 ahd_execute_scb(scb, &seg, 1, 0);
1061 struct bus_dma_segment *segs;
1063 if ((ccb_h->flags & CAM_DATA_PHYS) != 0)
1064 panic("ahd_setup_data - Physical segment "
1065 "pointers unsupported");
1067 if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0)
1068 panic("ahd_setup_data - Virtual segment "
1069 "addresses unsupported");
1071 /* Just use the segments provided */
1072 segs = (struct bus_dma_segment *)csio->data_ptr;
1073 ahd_execute_scb(scb, segs, csio->sglist_cnt, 0);
1076 ahd_execute_scb(scb, NULL, 0, 0);
1081 ahd_abort_ccb(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
1083 union ccb *abort_ccb;
1085 abort_ccb = ccb->cab.abort_ccb;
1086 switch (abort_ccb->ccb_h.func_code) {
1087 #ifdef AHD_TARGET_MODE
1088 case XPT_ACCEPT_TARGET_IO:
1089 case XPT_IMMED_NOTIFY:
1090 case XPT_CONT_TARGET_IO:
1092 struct ahd_tmode_tstate *tstate;
1093 struct ahd_tmode_lstate *lstate;
1094 struct ccb_hdr_slist *list;
1097 status = ahd_find_tmode_devs(ahd, sim, abort_ccb, &tstate,
1100 if (status != CAM_REQ_CMP) {
1101 ccb->ccb_h.status = status;
1105 if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO)
1106 list = &lstate->accept_tios;
1107 else if (abort_ccb->ccb_h.func_code == XPT_IMMED_NOTIFY)
1108 list = &lstate->immed_notifies;
1113 struct ccb_hdr *curelm;
1116 curelm = SLIST_FIRST(list);
1118 if (curelm == &abort_ccb->ccb_h) {
1120 SLIST_REMOVE_HEAD(list, sim_links.sle);
1122 while(curelm != NULL) {
1123 struct ccb_hdr *nextelm;
1126 SLIST_NEXT(curelm, sim_links.sle);
1128 if (nextelm == &abort_ccb->ccb_h) {
1141 abort_ccb->ccb_h.status = CAM_REQ_ABORTED;
1142 xpt_done(abort_ccb);
1143 ccb->ccb_h.status = CAM_REQ_CMP;
1145 xpt_print_path(abort_ccb->ccb_h.path);
1146 printf("Not found\n");
1147 ccb->ccb_h.status = CAM_PATH_INVALID;
1155 /* XXX Fully implement the hard ones */
1156 ccb->ccb_h.status = CAM_UA_ABORT;
1159 ccb->ccb_h.status = CAM_REQ_INVALID;
1166 ahd_send_async(struct ahd_softc *ahd, char channel, u_int target,
1167 u_int lun, ac_code code, void *opt_arg)
1169 struct ccb_trans_settings cts;
1170 struct cam_path *path;
1175 error = ahd_create_path(ahd, channel, target, lun, &path);
1177 if (error != CAM_REQ_CMP)
1181 case AC_TRANSFER_NEG:
1183 struct ccb_trans_settings_scsi *scsi;
1185 cts.type = CTS_TYPE_CURRENT_SETTINGS;
1186 scsi = &cts.proto_specific.scsi;
1187 cts.ccb_h.path = path;
1188 cts.ccb_h.target_id = target;
1189 cts.ccb_h.target_lun = lun;
1190 ahd_get_tran_settings(ahd, ahd->our_id, channel, &cts);
1192 scsi->valid &= ~CTS_SCSI_VALID_TQ;
1193 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
1194 if (opt_arg == NULL)
1196 if (*((ahd_queue_alg *)opt_arg) == AHD_QUEUE_TAGGED)
1197 scsi->flags |= ~CTS_SCSI_FLAGS_TAG_ENB;
1198 scsi->valid |= CTS_SCSI_VALID_TQ;
1205 panic("ahd_send_async: Unexpected async event");
1207 xpt_async(code, path, arg);
1208 xpt_free_path(path);
1212 ahd_platform_set_tags(struct ahd_softc *ahd,
1213 struct ahd_devinfo *devinfo, int enable)
1218 ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
1220 ahd->platform_data = malloc(sizeof(struct ahd_platform_data), M_DEVBUF,
1222 if (ahd->platform_data == NULL)
1228 ahd_platform_free(struct ahd_softc *ahd)
1230 struct ahd_platform_data *pdata;
1232 pdata = ahd->platform_data;
1233 if (pdata != NULL) {
1234 if (pdata->regs[0] != NULL)
1235 bus_release_resource(ahd->dev_softc,
1236 pdata->regs_res_type[0],
1237 pdata->regs_res_id[0],
1240 if (pdata->regs[1] != NULL)
1241 bus_release_resource(ahd->dev_softc,
1242 pdata->regs_res_type[1],
1243 pdata->regs_res_id[1],
1246 if (pdata->irq != NULL)
1247 bus_release_resource(ahd->dev_softc,
1248 pdata->irq_res_type,
1251 if (pdata->sim != NULL) {
1252 xpt_async(AC_LOST_DEVICE, pdata->path, NULL);
1253 xpt_free_path(pdata->path);
1254 xpt_bus_deregister(cam_sim_path(pdata->sim));
1255 cam_sim_free(pdata->sim, /*free_devq*/TRUE);
1257 if (pdata->eh != NULL)
1258 EVENTHANDLER_DEREGISTER(shutdown_final, pdata->eh);
1259 free(ahd->platform_data, M_DEVBUF);
1264 ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
1266 /* We don't sort softcs under FreeBSD so report equal always */
1271 ahd_detach(device_t dev)
1273 struct ahd_softc *ahd;
1275 device_printf(dev, "detaching device\n");
1276 ahd = device_get_softc(dev);
1278 TAILQ_REMOVE(&ahd_tailq, ahd, links);
1279 ahd_intr_enable(ahd, FALSE);
1280 bus_teardown_intr(dev, ahd->platform_data->irq, ahd->platform_data->ih);
1288 ahd_dump_targcmd(struct target_cmd *cmd)
1294 byte = &cmd->initiator_channel;
1295 /* Debugging info for received commands */
1296 last_byte = &cmd[1].initiator_channel;
1299 while (byte < last_byte) {
1302 printf("%#x", *byte++);
1315 ahd_modevent(module_t mod, int type, void *data)
1317 /* XXX Deal with busy status on unload. */
1318 /* XXX Deal with unknown events */
1322 static moduledata_t ahd_mod = {
1328 /********************************** DDB Hooks *********************************/
1330 static struct ahd_softc *ahd_ddb_softc;
1331 static int ahd_ddb_paused;
1332 static int ahd_ddb_paused_on_entry;
1333 DB_COMMAND(ahd_sunit, ahd_ddb_sunit)
1335 struct ahd_softc *list_ahd;
1337 ahd_ddb_softc = NULL;
1338 TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
1339 if (list_ahd->unit == addr)
1340 ahd_ddb_softc = list_ahd;
1342 if (ahd_ddb_softc == NULL)
1343 db_error("No matching softc found!\n");
1346 DB_COMMAND(ahd_pause, ahd_ddb_pause)
1348 if (ahd_ddb_softc == NULL) {
1349 db_error("Must set unit with ahd_sunit first!\n");
1352 if (ahd_ddb_paused == 0) {
1354 if (ahd_is_paused(ahd_ddb_softc)) {
1355 ahd_ddb_paused_on_entry++;
1358 ahd_pause(ahd_ddb_softc);
1362 DB_COMMAND(ahd_unpause, ahd_ddb_unpause)
1364 if (ahd_ddb_softc == NULL) {
1365 db_error("Must set unit with ahd_sunit first!\n");
1368 if (ahd_ddb_paused != 0) {
1370 if (ahd_ddb_paused_on_entry)
1372 ahd_unpause(ahd_ddb_softc);
1373 } else if (ahd_ddb_paused_on_entry != 0) {
1374 /* Two unpauses to clear a paused on entry. */
1375 ahd_ddb_paused_on_entry = 0;
1376 ahd_unpause(ahd_ddb_softc);
1380 DB_COMMAND(ahd_in, ahd_ddb_in)
1385 if (ahd_ddb_softc == NULL) {
1386 db_error("Must set unit with ahd_sunit first!\n");
1393 while ((c = *modif++) != '\0') {
1409 while (--count >= 0) {
1410 db_printf("%04lx (M)%x: \t", (u_long)addr,
1411 ahd_inb(ahd_ddb_softc, MODE_PTR));
1414 db_printf("%02x\n", ahd_inb(ahd_ddb_softc, addr));
1417 db_printf("%04x\n", ahd_inw(ahd_ddb_softc, addr));
1420 db_printf("%08x\n", ahd_inl(ahd_ddb_softc, addr));
1426 DB_FUNC(ahd_out, ahd_ddb_out, db_cmd_table, CS_MORE, NULL)
1428 db_expr_t old_value;
1429 db_expr_t new_value;
1432 if (ahd_ddb_softc == NULL) {
1433 db_error("Must set unit with ahd_sunit first!\n");
1449 db_error("Unknown size\n");
1453 while (db_expression(&new_value)) {
1457 old_value = ahd_inb(ahd_ddb_softc, addr);
1458 ahd_outb(ahd_ddb_softc, addr, new_value);
1461 old_value = ahd_inw(ahd_ddb_softc, addr);
1462 ahd_outw(ahd_ddb_softc, addr, new_value);
1465 old_value = ahd_inl(ahd_ddb_softc, addr);
1466 ahd_outl(ahd_ddb_softc, addr, new_value);
1469 db_printf("%04lx (M)%x: \t0x%lx\t=\t0x%lx",
1470 (u_long)addr, ahd_inb(ahd_ddb_softc, MODE_PTR),
1471 (u_long)old_value, (u_long)new_value);
1477 DB_COMMAND(ahd_dump, ahd_ddb_dump)
1479 if (ahd_ddb_softc == NULL) {
1480 db_error("Must set unit with ahd_sunit first!\n");
1483 ahd_dump_card_state(ahd_ddb_softc);
1489 DECLARE_MODULE(ahd, ahd_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
1490 MODULE_DEPEND(ahd, cam, 1, 1, 1);
1491 MODULE_VERSION(ahd, 1);