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 $
34 * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.c,v 1.23 2005/12/04 02:12:40 ru Exp $
35 * $DragonFly: src/sys/dev/disk/aic7xxx/aic79xx_osm.c,v 1.24 2008/03/06 20:01:29 pavalos Exp $
38 #include "aic79xx_osm.h"
39 #include "aic79xx_inline.h"
41 #include <sys/kthread.h>
48 #ifndef AHD_TMODE_ENABLE
49 #define AHD_TMODE_ENABLE 0
52 #include "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_MPSAFE
, ahd_platform_intr
, ahd
,
99 &ahd
->platform_data
->ih
, NULL
);
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
;
115 struct cam_path
*path
;
122 * Create a thread to perform all recovery.
124 if (ahd_spawn_recovery_thread(ahd
) != 0)
127 ahd_controller_info(ahd
, ahd_info
);
128 kprintf("%s\n", ahd_info
);
132 * Construct our SIM entry
134 sim
= cam_sim_alloc(ahd_action
, ahd_poll
, "ahd", ahd
,
135 device_get_unit(ahd
->dev_softc
),
136 1, AHD_MAX_QUEUE
, NULL
);
140 if (xpt_bus_register(sim
, /*bus_id*/0) != CAM_SUCCESS
) {
146 if (xpt_create_path(&path
, /*periph*/NULL
,
147 cam_sim_path(sim
), CAM_TARGET_WILDCARD
,
148 CAM_LUN_WILDCARD
) != CAM_REQ_CMP
) {
149 xpt_bus_deregister(cam_sim_path(sim
));
155 xpt_setup_ccb(&csa
.ccb_h
, path
, /*priority*/5);
156 csa
.ccb_h
.func_code
= XPT_SASYNC_CB
;
157 csa
.event_enable
= AC_LOST_DEVICE
;
158 csa
.callback
= ahd_async
;
159 csa
.callback_arg
= sim
;
160 xpt_action((union ccb
*)&csa
);
164 ahd
->platform_data
->sim
= sim
;
165 ahd
->platform_data
->path
= path
;
168 /* We have to wait until after any system dumps... */
169 ahd
->platform_data
->eh
=
170 EVENTHANDLER_REGISTER(shutdown_post_sync
, ahd_shutdown
,
171 ahd
, SHUTDOWN_PRI_DRIVER
);
172 ahd_intr_enable(ahd
, TRUE
);
179 * Catch an interrupt from the adapter
182 ahd_platform_intr(void *arg
)
184 struct ahd_softc
*ahd
;
186 ahd
= (struct ahd_softc
*)arg
;
193 * We have an scb which has been processed by the
194 * adaptor, now we look to see how the operation
198 ahd_done(struct ahd_softc
*ahd
, struct scb
*scb
)
202 CAM_DEBUG(scb
->io_ctx
->ccb_h
.path
, CAM_DEBUG_TRACE
,
203 ("ahd_done - scb %d\n", SCB_GET_TAG(scb
)));
206 LIST_REMOVE(scb
, pending_links
);
207 if ((scb
->flags
& SCB_TIMEDOUT
) != 0)
208 LIST_REMOVE(scb
, timedout_links
);
210 callout_stop(&scb
->io_timer
);
212 if ((ccb
->ccb_h
.flags
& CAM_DIR_MASK
) != CAM_DIR_NONE
) {
215 if ((ccb
->ccb_h
.flags
& CAM_DIR_MASK
) == CAM_DIR_IN
)
216 op
= BUS_DMASYNC_POSTREAD
;
218 op
= BUS_DMASYNC_POSTWRITE
;
219 bus_dmamap_sync(ahd
->buffer_dmat
, scb
->dmamap
, op
);
220 bus_dmamap_unload(ahd
->buffer_dmat
, scb
->dmamap
);
223 #ifdef AHD_TARGET_MODE
224 if (ccb
->ccb_h
.func_code
== XPT_CONT_TARGET_IO
) {
225 struct cam_path
*ccb_path
;
228 * If we have finally disconnected, clean up our
229 * pending device state.
230 * XXX - There may be error states that cause where
231 * we will remain connected.
233 ccb_path
= ccb
->ccb_h
.path
;
234 if (ahd
->pending_device
!= NULL
235 && xpt_path_comp(ahd
->pending_device
->path
, ccb_path
) == 0) {
237 if ((ccb
->ccb_h
.flags
& CAM_SEND_STATUS
) != 0) {
238 ahd
->pending_device
= NULL
;
240 xpt_print_path(ccb
->ccb_h
.path
);
241 kprintf("Still disconnected\n");
246 if (aic_get_transaction_status(scb
) == CAM_REQ_INPROG
)
247 ccb
->ccb_h
.status
|= CAM_REQ_CMP
;
248 ccb
->ccb_h
.status
&= ~CAM_SIM_QUEUED
;
249 ahd_free_scb(ahd
, scb
);
255 if ((scb
->flags
& SCB_RECOVERY_SCB
) != 0) {
256 struct scb
*list_scb
;
258 ahd
->scb_data
.recovery_scbs
--;
260 if (aic_get_transaction_status(scb
) == CAM_BDR_SENT
261 || aic_get_transaction_status(scb
) == CAM_REQ_ABORTED
)
262 aic_set_transaction_status(scb
, CAM_CMD_TIMEOUT
);
264 if (ahd
->scb_data
.recovery_scbs
== 0) {
266 * All recovery actions have completed successfully,
267 * so reinstate the timeouts for all other pending
270 LIST_FOREACH(list_scb
,
271 &ahd
->pending_scbs
, pending_links
) {
273 aic_scb_timer_reset(list_scb
,
274 aic_get_timeout(scb
));
277 ahd_print_path(ahd
, scb
);
278 kprintf("no longer in timeout, status = %x\n",
283 /* Don't clobber any existing error state */
284 if (aic_get_transaction_status(scb
) == CAM_REQ_INPROG
) {
285 ccb
->ccb_h
.status
|= CAM_REQ_CMP
;
286 } else if ((scb
->flags
& SCB_SENSE
) != 0) {
288 * We performed autosense retrieval.
290 * Zero any sense not transferred by the
291 * device. The SCSI spec mandates that any
292 * untransfered data should be assumed to be
293 * zero. Complete the 'bounce' of sense information
294 * through buffers accessible via bus-space by
295 * copying it into the clients csio.
297 memset(&ccb
->csio
.sense_data
, 0, sizeof(ccb
->csio
.sense_data
));
298 memcpy(&ccb
->csio
.sense_data
,
299 ahd_get_sense_buf(ahd
, scb
),
300 /* XXX What size do we want to use??? */
301 sizeof(ccb
->csio
.sense_data
)
302 - ccb
->csio
.sense_resid
);
303 scb
->io_ctx
->ccb_h
.status
|= CAM_AUTOSNS_VALID
;
304 } else if ((scb
->flags
& SCB_PKT_SENSE
) != 0) {
305 struct scsi_status_iu_header
*siu
;
309 * Copy only the sense data into the provided buffer.
311 siu
= (struct scsi_status_iu_header
*)scb
->sense_data
;
312 sense_len
= MIN(scsi_4btoul(siu
->sense_length
),
313 sizeof(ccb
->csio
.sense_data
));
314 memset(&ccb
->csio
.sense_data
, 0, sizeof(ccb
->csio
.sense_data
));
315 memcpy(&ccb
->csio
.sense_data
,
316 ahd_get_sense_buf(ahd
, scb
) + SIU_SENSE_OFFSET(siu
),
319 if ((ahd_debug
& AHD_SHOW_SENSE
) != 0) {
320 uint8_t *sense_data
= (uint8_t *)&ccb
->csio
.sense_data
;
323 kprintf("Copied %d bytes of sense data offset %d:",
324 sense_len
, SIU_SENSE_OFFSET(siu
));
325 for (i
= 0; i
< sense_len
; i
++)
326 kprintf(" 0x%x", *sense_data
++);
330 scb
->io_ctx
->ccb_h
.status
|= CAM_AUTOSNS_VALID
;
332 ccb
->ccb_h
.status
&= ~CAM_SIM_QUEUED
;
333 ahd_free_scb(ahd
, scb
);
338 ahd_action(struct cam_sim
*sim
, union ccb
*ccb
)
340 struct ahd_softc
*ahd
;
341 #ifdef AHD_TARGET_MODE
342 struct ahd_tmode_lstate
*lstate
;
347 CAM_DEBUG(ccb
->ccb_h
.path
, CAM_DEBUG_TRACE
, ("ahd_action\n"));
349 ahd
= (struct ahd_softc
*)cam_sim_softc(sim
);
351 target_id
= ccb
->ccb_h
.target_id
;
352 our_id
= SIM_SCSI_ID(ahd
, sim
);
354 switch (ccb
->ccb_h
.func_code
) {
355 /* Common cases first */
356 #ifdef AHD_TARGET_MODE
357 case XPT_ACCEPT_TARGET_IO
: /* Accept Host Target Mode CDB */
358 case XPT_CONT_TARGET_IO
:/* Continue Host Target I/O Connection*/
360 struct ahd_tmode_tstate
*tstate
;
363 status
= ahd_find_tmode_devs(ahd
, sim
, ccb
, &tstate
,
366 if (status
!= CAM_REQ_CMP
) {
367 if (ccb
->ccb_h
.func_code
== XPT_CONT_TARGET_IO
) {
368 /* Response from the black hole device */
370 lstate
= ahd
->black_hole
;
372 ccb
->ccb_h
.status
= status
;
377 if (ccb
->ccb_h
.func_code
== XPT_ACCEPT_TARGET_IO
) {
379 SLIST_INSERT_HEAD(&lstate
->accept_tios
, &ccb
->ccb_h
,
381 ccb
->ccb_h
.status
= CAM_REQ_INPROG
;
382 if ((ahd
->flags
& AHD_TQINFIFO_BLOCKED
) != 0)
383 ahd_run_tqinfifo(ahd
, /*paused*/FALSE
);
388 * The target_id represents the target we attempt to
389 * select. In target mode, this is the initiator of
390 * the original command.
393 target_id
= ccb
->csio
.init_id
;
397 case XPT_SCSI_IO
: /* Execute the requested I/O operation */
398 case XPT_RESET_DEV
: /* Bus Device Reset the specified SCSI device */
401 struct hardware_scb
*hscb
;
402 struct ahd_initiator_tinfo
*tinfo
;
403 struct ahd_tmode_tstate
*tstate
;
406 if ((ahd
->flags
& AHD_INITIATORROLE
) == 0
407 && (ccb
->ccb_h
.func_code
== XPT_SCSI_IO
408 || ccb
->ccb_h
.func_code
== XPT_RESET_DEV
)) {
409 ccb
->ccb_h
.status
= CAM_PROVIDE_FAIL
;
417 tinfo
= ahd_fetch_transinfo(ahd
, 'A', our_id
,
419 if ((ccb
->ccb_h
.flags
& CAM_TAG_ACTION_VALID
) == 0
420 || (tinfo
->curr
.ppr_options
& MSG_EXT_PPR_IU_REQ
) != 0
421 || ccb
->ccb_h
.func_code
== XPT_CONT_TARGET_IO
) {
422 col_idx
= AHD_NEVER_COL_IDX
;
424 col_idx
= AHD_BUILD_COL_IDX(target_id
,
425 ccb
->ccb_h
.target_lun
);
427 if ((scb
= ahd_get_scb(ahd
, col_idx
)) == NULL
) {
429 xpt_freeze_simq(sim
, /*count*/1);
430 ahd
->flags
|= AHD_RESOURCE_SHORTAGE
;
431 ccb
->ccb_h
.status
= CAM_REQUEUE_REQ
;
438 CAM_DEBUG(ccb
->ccb_h
.path
, CAM_DEBUG_SUBTRACE
,
439 ("start scb(%p)\n", scb
));
442 * So we can find the SCB when an abort is requested
444 ccb
->ccb_h
.ccb_scb_ptr
= scb
;
447 * Put all the arguments for the xfer in the scb
450 hscb
->scsiid
= BUILD_SCSIID(ahd
, sim
, target_id
, our_id
);
451 hscb
->lun
= ccb
->ccb_h
.target_lun
;
452 if (ccb
->ccb_h
.func_code
== XPT_RESET_DEV
) {
454 scb
->flags
|= SCB_DEVICE_RESET
;
455 hscb
->control
|= MK_MESSAGE
;
456 hscb
->task_management
= SIU_TASKMGMT_LUN_RESET
;
457 ahd_execute_scb(scb
, NULL
, 0, 0);
459 #ifdef AHD_TARGET_MODE
460 if (ccb
->ccb_h
.func_code
== XPT_CONT_TARGET_IO
) {
461 struct target_data
*tdata
;
463 tdata
= &hscb
->shared_data
.tdata
;
464 if (ahd
->pending_device
== lstate
)
465 scb
->flags
|= SCB_TARGET_IMMEDIATE
;
466 hscb
->control
|= TARGET_SCB
;
467 tdata
->target_phases
= 0;
468 if ((ccb
->ccb_h
.flags
& CAM_SEND_STATUS
) != 0) {
469 tdata
->target_phases
|= SPHASE_PENDING
;
471 ccb
->csio
.scsi_status
;
473 if (ccb
->ccb_h
.flags
& CAM_DIS_DISCONNECT
)
474 tdata
->target_phases
|= NO_DISCONNECT
;
476 tdata
->initiator_tag
=
477 ahd_htole16(ccb
->csio
.tag_id
);
480 hscb
->task_management
= 0;
481 if (ccb
->ccb_h
.flags
& CAM_TAG_ACTION_VALID
)
482 hscb
->control
|= ccb
->csio
.tag_action
;
484 ahd_setup_data(ahd
, sim
, &ccb
->csio
, scb
);
488 #ifdef AHD_TARGET_MODE
490 case XPT_IMMED_NOTIFY
:
492 struct ahd_tmode_tstate
*tstate
;
493 struct ahd_tmode_lstate
*lstate
;
496 status
= ahd_find_tmode_devs(ahd
, sim
, ccb
, &tstate
,
499 if (status
!= CAM_REQ_CMP
) {
500 ccb
->ccb_h
.status
= status
;
504 SLIST_INSERT_HEAD(&lstate
->immed_notifies
, &ccb
->ccb_h
,
506 ccb
->ccb_h
.status
= CAM_REQ_INPROG
;
507 ahd_send_lstate_events(ahd
, lstate
);
510 case XPT_EN_LUN
: /* Enable LUN as a target */
511 ahd_handle_en_lun(ahd
, sim
, ccb
);
515 case XPT_ABORT
: /* Abort the specified CCB */
517 ahd_abort_ccb(ahd
, sim
, ccb
);
520 case XPT_SET_TRAN_SETTINGS
:
522 ahd_set_tran_settings(ahd
, SIM_SCSI_ID(ahd
, sim
),
523 SIM_CHANNEL(ahd
, sim
), &ccb
->cts
);
527 case XPT_GET_TRAN_SETTINGS
:
528 /* Get default/user set transfer settings for the target */
530 ahd_get_tran_settings(ahd
, SIM_SCSI_ID(ahd
, sim
),
531 SIM_CHANNEL(ahd
, sim
), &ccb
->cts
);
535 case XPT_CALC_GEOMETRY
:
537 cam_calc_geometry(&ccb
->ccg
, ahd
->flags
& AHD_EXTENDED_TRANS_A
);
541 case XPT_RESET_BUS
: /* Reset the specified SCSI bus */
545 found
= ahd_reset_channel(ahd
, SIM_CHANNEL(ahd
, sim
),
546 /*initiate reset*/TRUE
);
548 xpt_print_path(SIM_PATH(ahd
, sim
));
549 kprintf("SCSI bus reset delivered. "
550 "%d SCBs aborted.\n", found
);
552 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
556 case XPT_TERM_IO
: /* Terminate the I/O process */
558 ccb
->ccb_h
.status
= CAM_REQ_INVALID
;
561 case XPT_PATH_INQ
: /* Path routing inquiry */
563 struct ccb_pathinq
*cpi
= &ccb
->cpi
;
565 cpi
->version_num
= 1; /* XXX??? */
566 cpi
->hba_inquiry
= PI_SDTR_ABLE
|PI_TAG_ABLE
;
567 if ((ahd
->features
& AHD_WIDE
) != 0)
568 cpi
->hba_inquiry
|= PI_WIDE_16
;
569 if ((ahd
->features
& AHD_TARGETMODE
) != 0) {
570 cpi
->target_sprt
= PIT_PROCESSOR
574 cpi
->target_sprt
= 0;
577 cpi
->hba_eng_cnt
= 0;
578 cpi
->max_target
= (ahd
->features
& AHD_WIDE
) ? 15 : 7;
579 cpi
->max_lun
= AHD_NUM_LUNS_NONPKT
- 1;
580 cpi
->initiator_id
= ahd
->our_id
;
581 if ((ahd
->flags
& AHD_RESET_BUS_A
) == 0) {
582 cpi
->hba_misc
|= PIM_NOBUSRESET
;
584 cpi
->bus_id
= cam_sim_bus(sim
);
585 cpi
->base_transfer_speed
= 3300;
586 strncpy(cpi
->sim_vid
, "FreeBSD", SIM_IDLEN
);
587 strncpy(cpi
->hba_vid
, "Adaptec", HBA_IDLEN
);
588 strncpy(cpi
->dev_name
, cam_sim_name(sim
), DEV_IDLEN
);
589 cpi
->unit_number
= cam_sim_unit(sim
);
590 cpi
->protocol
= PROTO_SCSI
;
591 cpi
->protocol_version
= SCSI_REV_2
;
592 cpi
->transport
= XPORT_SPI
;
593 cpi
->transport_version
= 2;
594 cpi
->xport_specific
.spi
.ppr_options
= SID_SPI_CLOCK_ST
;
595 cpi
->transport_version
= 4;
596 cpi
->xport_specific
.spi
.ppr_options
= SID_SPI_CLOCK_DT_ST
;
597 cpi
->ccb_h
.status
= CAM_REQ_CMP
;
602 ccb
->ccb_h
.status
= CAM_PROVIDE_FAIL
;
610 ahd_set_tran_settings(struct ahd_softc
*ahd
, int our_id
, char channel
,
611 struct ccb_trans_settings
*cts
)
613 struct ahd_devinfo devinfo
;
614 struct ccb_trans_settings_scsi
*scsi
;
615 struct ccb_trans_settings_spi
*spi
;
616 struct ahd_initiator_tinfo
*tinfo
;
617 struct ahd_tmode_tstate
*tstate
;
618 uint16_t *discenable
;
622 scsi
= &cts
->proto_specific
.scsi
;
623 spi
= &cts
->xport_specific
.spi
;
624 ahd_compile_devinfo(&devinfo
, SIM_SCSI_ID(ahd
, sim
),
625 cts
->ccb_h
.target_id
,
626 cts
->ccb_h
.target_lun
,
627 SIM_CHANNEL(ahd
, sim
),
629 tinfo
= ahd_fetch_transinfo(ahd
, devinfo
.channel
,
631 devinfo
.target
, &tstate
);
633 if (cts
->type
== CTS_TYPE_CURRENT_SETTINGS
) {
634 update_type
|= AHD_TRANS_GOAL
;
635 discenable
= &tstate
->discenable
;
636 tagenable
= &tstate
->tagenable
;
637 tinfo
->curr
.protocol_version
= cts
->protocol_version
;
638 tinfo
->curr
.transport_version
= cts
->transport_version
;
639 tinfo
->goal
.protocol_version
= cts
->protocol_version
;
640 tinfo
->goal
.transport_version
= cts
->transport_version
;
641 } else if (cts
->type
== CTS_TYPE_USER_SETTINGS
) {
642 update_type
|= AHD_TRANS_USER
;
643 discenable
= &ahd
->user_discenable
;
644 tagenable
= &ahd
->user_tagenable
;
645 tinfo
->user
.protocol_version
= cts
->protocol_version
;
646 tinfo
->user
.transport_version
= cts
->transport_version
;
648 cts
->ccb_h
.status
= CAM_REQ_INVALID
;
652 if ((spi
->valid
& CTS_SPI_VALID_DISC
) != 0) {
653 if ((spi
->flags
& CTS_SPI_FLAGS_DISC_ENB
) != 0)
654 *discenable
|= devinfo
.target_mask
;
656 *discenable
&= ~devinfo
.target_mask
;
659 if ((scsi
->valid
& CTS_SCSI_VALID_TQ
) != 0) {
660 if ((scsi
->flags
& CTS_SCSI_FLAGS_TAG_ENB
) != 0)
661 *tagenable
|= devinfo
.target_mask
;
663 *tagenable
&= ~devinfo
.target_mask
;
666 if ((spi
->valid
& CTS_SPI_VALID_BUS_WIDTH
) != 0) {
667 ahd_validate_width(ahd
, /*tinfo limit*/NULL
,
668 &spi
->bus_width
, ROLE_UNKNOWN
);
669 ahd_set_width(ahd
, &devinfo
, spi
->bus_width
,
670 update_type
, /*paused*/FALSE
);
673 if ((spi
->valid
& CTS_SPI_VALID_PPR_OPTIONS
) == 0) {
674 if (update_type
== AHD_TRANS_USER
)
675 spi
->ppr_options
= tinfo
->user
.ppr_options
;
677 spi
->ppr_options
= tinfo
->goal
.ppr_options
;
680 if ((spi
->valid
& CTS_SPI_VALID_SYNC_OFFSET
) == 0) {
681 if (update_type
== AHD_TRANS_USER
)
682 spi
->sync_offset
= tinfo
->user
.offset
;
684 spi
->sync_offset
= tinfo
->goal
.offset
;
687 if ((spi
->valid
& CTS_SPI_VALID_SYNC_RATE
) == 0) {
688 if (update_type
== AHD_TRANS_USER
)
689 spi
->sync_period
= tinfo
->user
.period
;
691 spi
->sync_period
= tinfo
->goal
.period
;
694 if (((spi
->valid
& CTS_SPI_VALID_SYNC_RATE
) != 0)
695 || ((spi
->valid
& CTS_SPI_VALID_SYNC_OFFSET
) != 0)) {
698 maxsync
= AHD_SYNCRATE_MAX
;
700 if (spi
->bus_width
!= MSG_EXT_WDTR_BUS_16_BIT
)
701 spi
->ppr_options
&= ~MSG_EXT_PPR_DT_REQ
;
703 if ((*discenable
& devinfo
.target_mask
) == 0)
704 spi
->ppr_options
&= ~MSG_EXT_PPR_IU_REQ
;
706 ahd_find_syncrate(ahd
, &spi
->sync_period
,
707 &spi
->ppr_options
, maxsync
);
708 ahd_validate_offset(ahd
, /*tinfo limit*/NULL
,
709 spi
->sync_period
, &spi
->sync_offset
,
710 spi
->bus_width
, ROLE_UNKNOWN
);
712 /* We use a period of 0 to represent async */
713 if (spi
->sync_offset
== 0) {
714 spi
->sync_period
= 0;
715 spi
->ppr_options
= 0;
718 ahd_set_syncrate(ahd
, &devinfo
, spi
->sync_period
,
719 spi
->sync_offset
, spi
->ppr_options
,
720 update_type
, /*paused*/FALSE
);
722 cts
->ccb_h
.status
= CAM_REQ_CMP
;
726 ahd_get_tran_settings(struct ahd_softc
*ahd
, int our_id
, char channel
,
727 struct ccb_trans_settings
*cts
)
729 struct ahd_devinfo devinfo
;
730 struct ccb_trans_settings_scsi
*scsi
;
731 struct ccb_trans_settings_spi
*spi
;
732 struct ahd_initiator_tinfo
*targ_info
;
733 struct ahd_tmode_tstate
*tstate
;
734 struct ahd_transinfo
*tinfo
;
736 scsi
= &cts
->proto_specific
.scsi
;
737 spi
= &cts
->xport_specific
.spi
;
738 ahd_compile_devinfo(&devinfo
, our_id
,
739 cts
->ccb_h
.target_id
,
740 cts
->ccb_h
.target_lun
,
741 channel
, ROLE_UNKNOWN
);
742 targ_info
= ahd_fetch_transinfo(ahd
, devinfo
.channel
,
744 devinfo
.target
, &tstate
);
746 if (cts
->type
== CTS_TYPE_CURRENT_SETTINGS
)
747 tinfo
= &targ_info
->curr
;
749 tinfo
= &targ_info
->user
;
751 scsi
->flags
&= ~CTS_SCSI_FLAGS_TAG_ENB
;
752 spi
->flags
&= ~CTS_SPI_FLAGS_DISC_ENB
;
753 if (cts
->type
== CTS_TYPE_USER_SETTINGS
) {
754 if ((ahd
->user_discenable
& devinfo
.target_mask
) != 0)
755 spi
->flags
|= CTS_SPI_FLAGS_DISC_ENB
;
757 if ((ahd
->user_tagenable
& devinfo
.target_mask
) != 0)
758 scsi
->flags
|= CTS_SCSI_FLAGS_TAG_ENB
;
760 if ((tstate
->discenable
& devinfo
.target_mask
) != 0)
761 spi
->flags
|= CTS_SPI_FLAGS_DISC_ENB
;
763 if ((tstate
->tagenable
& devinfo
.target_mask
) != 0)
764 scsi
->flags
|= CTS_SCSI_FLAGS_TAG_ENB
;
766 cts
->protocol_version
= tinfo
->protocol_version
;
767 cts
->transport_version
= tinfo
->transport_version
;
769 spi
->sync_period
= tinfo
->period
;
770 spi
->sync_offset
= tinfo
->offset
;
771 spi
->bus_width
= tinfo
->width
;
772 spi
->ppr_options
= tinfo
->ppr_options
;
774 cts
->protocol
= PROTO_SCSI
;
775 cts
->transport
= XPORT_SPI
;
776 spi
->valid
= CTS_SPI_VALID_SYNC_RATE
777 | CTS_SPI_VALID_SYNC_OFFSET
778 | CTS_SPI_VALID_BUS_WIDTH
779 | CTS_SPI_VALID_PPR_OPTIONS
;
781 if (cts
->ccb_h
.target_lun
!= CAM_LUN_WILDCARD
) {
782 scsi
->valid
= CTS_SCSI_VALID_TQ
;
783 spi
->valid
|= CTS_SPI_VALID_DISC
;
788 cts
->ccb_h
.status
= CAM_REQ_CMP
;
792 ahd_async(void *callback_arg
, uint32_t code
, struct cam_path
*path
, void *arg
)
794 struct ahd_softc
*ahd
;
797 sim
= (struct cam_sim
*)callback_arg
;
798 ahd
= (struct ahd_softc
*)cam_sim_softc(sim
);
802 struct ahd_devinfo devinfo
;
804 ahd_compile_devinfo(&devinfo
, SIM_SCSI_ID(ahd
, sim
),
805 xpt_path_target_id(path
),
806 xpt_path_lun_id(path
),
807 SIM_CHANNEL(ahd
, sim
),
811 * Revert to async/narrow transfers
812 * for the next device.
814 ahd_set_width(ahd
, &devinfo
, MSG_EXT_WDTR_BUS_8_BIT
,
815 AHD_TRANS_GOAL
|AHD_TRANS_CUR
, /*paused*/FALSE
);
816 ahd_set_syncrate(ahd
, &devinfo
, /*period*/0, /*offset*/0,
817 /*ppr_options*/0, AHD_TRANS_GOAL
|AHD_TRANS_CUR
,
827 ahd_execute_scb(void *arg
, bus_dma_segment_t
*dm_segs
, int nsegments
,
832 struct ahd_softc
*ahd
;
833 struct ahd_initiator_tinfo
*tinfo
;
834 struct ahd_tmode_tstate
*tstate
;
837 scb
= (struct scb
*)arg
;
839 ahd
= scb
->ahd_softc
;
843 aic_set_transaction_status(scb
, CAM_REQ_TOO_BIG
);
845 aic_set_transaction_status(scb
, CAM_REQ_CMP_ERR
);
847 bus_dmamap_unload(ahd
->buffer_dmat
, scb
->dmamap
);
848 ahd_free_scb(ahd
, scb
);
853 if (nsegments
!= 0) {
858 /* Copy the segments into our SG list */
859 for (i
= nsegments
, sg
= scb
->sg_list
; i
> 0; i
--) {
861 sg
= ahd_sg_setup(ahd
, scb
, sg
, dm_segs
->ds_addr
,
867 if ((ccb
->ccb_h
.flags
& CAM_DIR_MASK
) == CAM_DIR_IN
)
868 op
= BUS_DMASYNC_PREREAD
;
870 op
= BUS_DMASYNC_PREWRITE
;
872 bus_dmamap_sync(ahd
->buffer_dmat
, scb
->dmamap
, op
);
874 if (ccb
->ccb_h
.func_code
== XPT_CONT_TARGET_IO
) {
875 struct target_data
*tdata
;
877 tdata
= &scb
->hscb
->shared_data
.tdata
;
878 tdata
->target_phases
|= DPHASE_PENDING
;
879 if ((ccb
->ccb_h
.flags
& CAM_DIR_MASK
) == CAM_DIR_OUT
)
880 tdata
->data_phase
= P_DATAOUT
;
882 tdata
->data_phase
= P_DATAIN
;
887 * Last time we need to check if this SCB needs to
890 if (aic_get_transaction_status(scb
) != CAM_REQ_INPROG
) {
892 bus_dmamap_unload(ahd
->buffer_dmat
,
894 ahd_free_scb(ahd
, scb
);
899 tinfo
= ahd_fetch_transinfo(ahd
, SCSIID_CHANNEL(ahd
, scb
->hscb
->scsiid
),
900 SCSIID_OUR_ID(scb
->hscb
->scsiid
),
901 SCSIID_TARGET(ahd
, scb
->hscb
->scsiid
),
904 mask
= SCB_GET_TARGET_MASK(ahd
, scb
);
906 if ((tstate
->discenable
& mask
) != 0
907 && (ccb
->ccb_h
.flags
& CAM_DIS_DISCONNECT
) == 0)
908 scb
->hscb
->control
|= DISCENB
;
910 if ((tinfo
->curr
.ppr_options
& MSG_EXT_PPR_IU_REQ
) != 0) {
911 scb
->flags
|= SCB_PACKETIZED
;
912 if (scb
->hscb
->task_management
!= 0)
913 scb
->hscb
->control
&= ~MK_MESSAGE
;
916 if ((ccb
->ccb_h
.flags
& CAM_NEGOTIATE
) != 0
917 && (tinfo
->goal
.width
!= 0
918 || tinfo
->goal
.period
!= 0
919 || tinfo
->goal
.ppr_options
!= 0)) {
920 scb
->flags
|= SCB_NEGOTIATE
;
921 scb
->hscb
->control
|= MK_MESSAGE
;
922 } else if ((tstate
->auto_negotiate
& mask
) != 0) {
923 scb
->flags
|= SCB_AUTO_NEGOTIATE
;
924 scb
->hscb
->control
|= MK_MESSAGE
;
927 LIST_INSERT_HEAD(&ahd
->pending_scbs
, scb
, pending_links
);
929 ccb
->ccb_h
.status
|= CAM_SIM_QUEUED
;
931 aic_scb_timer_start(scb
);
933 if ((scb
->flags
& SCB_TARGET_IMMEDIATE
) != 0) {
934 /* Define a mapping from our tag to the SCB. */
935 ahd
->scb_data
.scbindex
[SCB_GET_TAG(scb
)] = scb
;
937 ahd_set_scbptr(ahd
, SCB_GET_TAG(scb
));
938 ahd_outb(ahd
, RETURN_1
, CONT_MSG_LOOP_TARG
);
941 ahd_queue_scb(ahd
, scb
);
946 ahd_poll(struct cam_sim
*sim
)
948 ahd_intr(cam_sim_softc(sim
));
952 ahd_setup_data(struct ahd_softc
*ahd
, struct cam_sim
*sim
,
953 struct ccb_scsiio
*csio
, struct scb
*scb
)
955 struct hardware_scb
*hscb
;
956 struct ccb_hdr
*ccb_h
;
959 ccb_h
= &csio
->ccb_h
;
962 csio
->sense_resid
= 0;
963 if (ccb_h
->func_code
== XPT_SCSI_IO
) {
964 hscb
->cdb_len
= csio
->cdb_len
;
965 if ((ccb_h
->flags
& CAM_CDB_POINTER
) != 0) {
967 if (hscb
->cdb_len
> MAX_CDB_LEN
968 && (ccb_h
->flags
& CAM_CDB_PHYS
) == 0) {
971 * Should CAM start to support CDB sizes
972 * greater than 16 bytes, we could use
973 * the sense buffer to store the CDB.
975 aic_set_transaction_status(scb
,
977 ahd_free_scb(ahd
, scb
);
978 xpt_done((union ccb
*)csio
);
981 if ((ccb_h
->flags
& CAM_CDB_PHYS
) != 0) {
982 hscb
->shared_data
.idata
.cdb_from_host
.cdbptr
=
983 aic_htole64((uintptr_t)csio
->cdb_io
.cdb_ptr
);
984 hscb
->shared_data
.idata
.cdb_from_host
.cdblen
=
986 hscb
->cdb_len
|= SCB_CDB_LEN_PTR
;
988 memcpy(hscb
->shared_data
.idata
.cdb
,
989 csio
->cdb_io
.cdb_ptr
,
993 if (hscb
->cdb_len
> MAX_CDB_LEN
) {
995 aic_set_transaction_status(scb
,
997 ahd_free_scb(ahd
, scb
);
998 xpt_done((union ccb
*)csio
);
1001 memcpy(hscb
->shared_data
.idata
.cdb
,
1002 csio
->cdb_io
.cdb_bytes
, hscb
->cdb_len
);
1006 /* Only use S/G if there is a transfer */
1007 if ((ccb_h
->flags
& CAM_DIR_MASK
) != CAM_DIR_NONE
) {
1008 if ((ccb_h
->flags
& CAM_SCATTER_VALID
) == 0) {
1009 /* We've been given a pointer to a single buffer */
1010 if ((ccb_h
->flags
& CAM_DATA_PHYS
) == 0) {
1014 error
= bus_dmamap_load(ahd
->buffer_dmat
,
1020 if (error
== EINPROGRESS
) {
1022 * So as to maintain ordering,
1023 * freeze the controller queue
1024 * until our mapping is
1027 xpt_freeze_simq(sim
,
1029 scb
->io_ctx
->ccb_h
.status
|=
1034 struct bus_dma_segment seg
;
1036 /* Pointer to physical buffer */
1037 if (csio
->dxfer_len
> AHD_MAXTRANSFER_SIZE
)
1038 panic("ahd_setup_data - Transfer size "
1039 "larger than can device max");
1042 (bus_addr_t
)(vm_offset_t
)csio
->data_ptr
;
1043 seg
.ds_len
= csio
->dxfer_len
;
1044 ahd_execute_scb(scb
, &seg
, 1, 0);
1047 struct bus_dma_segment
*segs
;
1049 if ((ccb_h
->flags
& CAM_DATA_PHYS
) != 0)
1050 panic("ahd_setup_data - Physical segment "
1051 "pointers unsupported");
1053 if ((ccb_h
->flags
& CAM_SG_LIST_PHYS
) == 0)
1054 panic("ahd_setup_data - Virtual segment "
1055 "addresses unsupported");
1057 /* Just use the segments provided */
1058 segs
= (struct bus_dma_segment
*)csio
->data_ptr
;
1059 ahd_execute_scb(scb
, segs
, csio
->sglist_cnt
, 0);
1062 ahd_execute_scb(scb
, NULL
, 0, 0);
1067 ahd_abort_ccb(struct ahd_softc
*ahd
, struct cam_sim
*sim
, union ccb
*ccb
)
1069 union ccb
*abort_ccb
;
1071 abort_ccb
= ccb
->cab
.abort_ccb
;
1072 switch (abort_ccb
->ccb_h
.func_code
) {
1073 #ifdef AHD_TARGET_MODE
1074 case XPT_ACCEPT_TARGET_IO
:
1075 case XPT_IMMED_NOTIFY
:
1076 case XPT_CONT_TARGET_IO
:
1078 struct ahd_tmode_tstate
*tstate
;
1079 struct ahd_tmode_lstate
*lstate
;
1080 struct ccb_hdr_slist
*list
;
1083 status
= ahd_find_tmode_devs(ahd
, sim
, abort_ccb
, &tstate
,
1086 if (status
!= CAM_REQ_CMP
) {
1087 ccb
->ccb_h
.status
= status
;
1091 if (abort_ccb
->ccb_h
.func_code
== XPT_ACCEPT_TARGET_IO
)
1092 list
= &lstate
->accept_tios
;
1093 else if (abort_ccb
->ccb_h
.func_code
== XPT_IMMED_NOTIFY
)
1094 list
= &lstate
->immed_notifies
;
1099 struct ccb_hdr
*curelm
;
1102 curelm
= SLIST_FIRST(list
);
1104 if (curelm
== &abort_ccb
->ccb_h
) {
1106 SLIST_REMOVE_HEAD(list
, sim_links
.sle
);
1108 while(curelm
!= NULL
) {
1109 struct ccb_hdr
*nextelm
;
1112 SLIST_NEXT(curelm
, sim_links
.sle
);
1114 if (nextelm
== &abort_ccb
->ccb_h
) {
1127 abort_ccb
->ccb_h
.status
= CAM_REQ_ABORTED
;
1128 xpt_done(abort_ccb
);
1129 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
1131 xpt_print_path(abort_ccb
->ccb_h
.path
);
1132 kprintf("Not found\n");
1133 ccb
->ccb_h
.status
= CAM_PATH_INVALID
;
1141 /* XXX Fully implement the hard ones */
1142 ccb
->ccb_h
.status
= CAM_UA_ABORT
;
1145 ccb
->ccb_h
.status
= CAM_REQ_INVALID
;
1152 ahd_send_async(struct ahd_softc
*ahd
, char channel
, u_int target
,
1153 u_int lun
, ac_code code
, void *opt_arg
)
1155 struct ccb_trans_settings cts
;
1156 struct cam_path
*path
;
1161 error
= ahd_create_path(ahd
, channel
, target
, lun
, &path
);
1163 if (error
!= CAM_REQ_CMP
)
1167 case AC_TRANSFER_NEG
:
1169 struct ccb_trans_settings_scsi
*scsi
;
1171 cts
.type
= CTS_TYPE_CURRENT_SETTINGS
;
1172 scsi
= &cts
.proto_specific
.scsi
;
1173 cts
.ccb_h
.path
= path
;
1174 cts
.ccb_h
.target_id
= target
;
1175 cts
.ccb_h
.target_lun
= lun
;
1176 ahd_get_tran_settings(ahd
, ahd
->our_id
, channel
, &cts
);
1178 scsi
->valid
&= ~CTS_SCSI_VALID_TQ
;
1179 scsi
->flags
&= ~CTS_SCSI_FLAGS_TAG_ENB
;
1180 if (opt_arg
== NULL
)
1182 if (*((ahd_queue_alg
*)opt_arg
) == AHD_QUEUE_TAGGED
)
1183 scsi
->flags
|= ~CTS_SCSI_FLAGS_TAG_ENB
;
1184 scsi
->valid
|= CTS_SCSI_VALID_TQ
;
1191 panic("ahd_send_async: Unexpected async event");
1193 xpt_async(code
, path
, arg
);
1194 xpt_free_path(path
);
1198 ahd_platform_set_tags(struct ahd_softc
*ahd
,
1199 struct ahd_devinfo
*devinfo
, int enable
)
1204 ahd_platform_alloc(struct ahd_softc
*ahd
, void *platform_arg
)
1206 ahd
->platform_data
= kmalloc(sizeof(struct ahd_platform_data
), M_DEVBUF
,
1207 M_INTWAIT
| M_ZERO
);
1212 ahd_platform_free(struct ahd_softc
*ahd
)
1214 struct ahd_platform_data
*pdata
;
1216 pdata
= ahd
->platform_data
;
1217 if (pdata
!= NULL
) {
1218 if (pdata
->regs
[0] != NULL
)
1219 bus_release_resource(ahd
->dev_softc
,
1220 pdata
->regs_res_type
[0],
1221 pdata
->regs_res_id
[0],
1224 if (pdata
->regs
[1] != NULL
)
1225 bus_release_resource(ahd
->dev_softc
,
1226 pdata
->regs_res_type
[1],
1227 pdata
->regs_res_id
[1],
1230 if (pdata
->irq
!= NULL
)
1231 bus_release_resource(ahd
->dev_softc
,
1232 pdata
->irq_res_type
,
1235 if (pdata
->sim
!= NULL
) {
1236 xpt_async(AC_LOST_DEVICE
, pdata
->path
, NULL
);
1237 xpt_free_path(pdata
->path
);
1238 xpt_bus_deregister(cam_sim_path(pdata
->sim
));
1239 cam_sim_free(pdata
->sim
);
1241 if (pdata
->eh
!= NULL
)
1242 EVENTHANDLER_DEREGISTER(shutdown_post_sync
, pdata
->eh
);
1243 kfree(ahd
->platform_data
, M_DEVBUF
);
1248 ahd_softc_comp(struct ahd_softc
*lahd
, struct ahd_softc
*rahd
)
1250 /* We don't sort softcs under FreeBSD so report equal always */
1255 ahd_detach(device_t dev
)
1257 struct ahd_softc
*ahd
;
1259 device_printf(dev
, "detaching device\n");
1260 ahd
= device_get_softc(dev
);
1262 TAILQ_REMOVE(&ahd_tailq
, ahd
, links
);
1263 ahd_intr_enable(ahd
, FALSE
);
1264 bus_teardown_intr(dev
, ahd
->platform_data
->irq
, ahd
->platform_data
->ih
);
1272 ahd_dump_targcmd(struct target_cmd
*cmd
)
1278 byte
= &cmd
->initiator_channel
;
1279 /* Debugging info for received commands */
1280 last_byte
= &cmd
[1].initiator_channel
;
1283 while (byte
< last_byte
) {
1286 kprintf("%#x", *byte
++);
1299 ahd_modevent(module_t mod
, int type
, void *data
)
1301 /* XXX Deal with busy status on unload. */
1302 /* XXX Deal with unknown events */
1306 static moduledata_t ahd_mod
= {
1312 /********************************** DDB Hooks *********************************/
1314 static struct ahd_softc
*ahd_ddb_softc
;
1315 static int ahd_ddb_paused
;
1316 static int ahd_ddb_paused_on_entry
;
1317 DB_COMMAND(ahd_sunit
, ahd_ddb_sunit
)
1319 struct ahd_softc
*list_ahd
;
1321 ahd_ddb_softc
= NULL
;
1322 TAILQ_FOREACH(list_ahd
, &ahd_tailq
, links
) {
1323 if (list_ahd
->unit
== addr
)
1324 ahd_ddb_softc
= list_ahd
;
1326 if (ahd_ddb_softc
== NULL
)
1327 db_error("No matching softc found!\n");
1330 DB_COMMAND(ahd_pause
, ahd_ddb_pause
)
1332 if (ahd_ddb_softc
== NULL
) {
1333 db_error("Must set unit with ahd_sunit first!\n");
1336 if (ahd_ddb_paused
== 0) {
1338 if (ahd_is_paused(ahd_ddb_softc
)) {
1339 ahd_ddb_paused_on_entry
++;
1342 ahd_pause(ahd_ddb_softc
);
1346 DB_COMMAND(ahd_unpause
, ahd_ddb_unpause
)
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_ddb_paused_on_entry
)
1356 ahd_unpause(ahd_ddb_softc
);
1357 } else if (ahd_ddb_paused_on_entry
!= 0) {
1358 /* Two unpauses to clear a paused on entry. */
1359 ahd_ddb_paused_on_entry
= 0;
1360 ahd_unpause(ahd_ddb_softc
);
1364 DB_COMMAND(ahd_in
, ahd_ddb_in
)
1369 if (ahd_ddb_softc
== NULL
) {
1370 db_error("Must set unit with ahd_sunit first!\n");
1377 while ((c
= *modif
++) != '\0') {
1393 while (--count
>= 0) {
1394 db_printf("%04lx (M)%x: \t", (u_long
)addr
,
1395 ahd_inb(ahd_ddb_softc
, MODE_PTR
));
1398 db_printf("%02x\n", ahd_inb(ahd_ddb_softc
, addr
));
1401 db_printf("%04x\n", ahd_inw(ahd_ddb_softc
, addr
));
1404 db_printf("%08x\n", ahd_inl(ahd_ddb_softc
, addr
));
1410 DB_SET(ahd_out
, ahd_ddb_out
, db_cmd_set
, CS_MORE
, NULL
)
1412 db_expr_t old_value
;
1413 db_expr_t new_value
;
1416 if (ahd_ddb_softc
== NULL
) {
1417 db_error("Must set unit with ahd_sunit first!\n");
1433 db_error("Unknown size\n");
1437 while (db_expression(&new_value
)) {
1441 old_value
= ahd_inb(ahd_ddb_softc
, addr
);
1442 ahd_outb(ahd_ddb_softc
, addr
, new_value
);
1445 old_value
= ahd_inw(ahd_ddb_softc
, addr
);
1446 ahd_outw(ahd_ddb_softc
, addr
, new_value
);
1449 old_value
= ahd_inl(ahd_ddb_softc
, addr
);
1450 ahd_outl(ahd_ddb_softc
, addr
, new_value
);
1453 db_printf("%04lx (M)%x: \t0x%lx\t=\t0x%lx",
1454 (u_long
)addr
, ahd_inb(ahd_ddb_softc
, MODE_PTR
),
1455 (u_long
)old_value
, (u_long
)new_value
);
1461 DB_COMMAND(ahd_dump
, ahd_ddb_dump
)
1463 if (ahd_ddb_softc
== NULL
) {
1464 db_error("Must set unit with ahd_sunit first!\n");
1467 ahd_dump_card_state(ahd_ddb_softc
);
1473 DECLARE_MODULE(ahd
, ahd_mod
, SI_SUB_DRIVERS
, SI_ORDER_MIDDLE
);
1474 MODULE_DEPEND(ahd
, cam
, 1, 1, 1);
1475 MODULE_VERSION(ahd
, 1);