aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/firewire/sbp.c
diff options
context:
space:
mode:
authorHidetoshi Shimokawa <simokawa@FreeBSD.org>2003-04-17 03:38:03 +0000
committerHidetoshi Shimokawa <simokawa@FreeBSD.org>2003-04-17 03:38:03 +0000
commit77ee030b5fe6848e5c50ae2f0013bf43f6ad0c28 (patch)
tree11114a8420b3e8fd28f1d77e46ddae593b132e23 /sys/dev/firewire/sbp.c
parentf770d2d3ddaa6d10eb3806ae6d722a20dad2d72d (diff)
Notes
Diffstat (limited to 'sys/dev/firewire/sbp.c')
-rw-r--r--sys/dev/firewire/sbp.c632
1 files changed, 315 insertions, 317 deletions
diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c
index 307b46607022..90783cf88d9e 100644
--- a/sys/dev/firewire/sbp.c
+++ b/sys/dev/firewire/sbp.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 1998,1999,2000,2001 Katsushi Kobayashi and Hidetosh Shimokawa
+ * Copyright (c) 2003 Hidetosh Shimokawa
+ * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetosh Shimokawa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -60,11 +61,9 @@
#include <sys/kernel.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
#include <dev/firewire/firewire.h>
#include <dev/firewire/firewirereg.h>
+#include <dev/firewire/fwdma.h>
#include <dev/firewire/iec13213.h>
#define ccb_sdev_ptr spriv_ptr0
@@ -72,8 +71,11 @@
#define SBP_NUM_TARGETS 8 /* MAX 64 */
#define SBP_NUM_LUNS 8 /* limited by CAM_SCSI2_MAXLUN in cam_xpt.c */
-#define SBP_QUEUE_LEN 4
+#define SBP_DMA_SIZE PAGE_SIZE
+#define SBP_LOGIN_SIZE sizeof(struct sbp_login_res)
+#define SBP_QUEUE_LEN ((SBP_DMA_SIZE - SBP_LOGIN_SIZE) / sizeof(struct sbp_ocb))
#define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS)
+
#define SBP_INITIATOR 7
#define LOGIN_DELAY 2
@@ -168,20 +170,29 @@ SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, max_speed, CTLFLAG_RW, &max_speed, 0,
struct ind_ptr {
u_int32_t hi,lo;
};
-#define SBP_IND_MAX 0x20
+#define SBP_SEG_MAX rounddown(0xffff, PAGE_SIZE)
+#ifdef __sparc64__ /* iommu */
+#define SBP_IND_MAX howmany(MAXPHYS, SBP_SEG_MAX)
+#else
+#define SBP_IND_MAX howmany(MAXPHYS, PAGE_SIZE)
+#endif
struct sbp_ocb {
STAILQ_ENTRY(sbp_ocb) ocb;
union ccb *ccb;
+ bus_addr_t bus_addr;
volatile u_int32_t orb[8];
+#define IND_PTR_OFFSET (8*sizeof(u_int32_t))
volatile struct ind_ptr ind_ptr[SBP_IND_MAX];
struct sbp_dev *sdev;
- int flags;
+ int flags; /* XXX should be removed */
bus_dmamap_t dmamap;
};
+
#define OCB_ACT_MGM 0
#define OCB_ACT_CMD 1
-#define OCB_MATCH(o,s) (vtophys(&(o)->orb[0]) == ntohl((s)->orb_lo))
+#define OCB_MATCH(o,s) ((o)->bus_addr == ntohl((s)->orb_lo))
+#define SBP_RECV_LEN (16 + 32) /* header + payload */
struct sbp_login_res{
u_int16_t len;
@@ -193,11 +204,18 @@ struct sbp_login_res{
u_int16_t recon_hold;
};
struct sbp_status{
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int8_t src:2,
+ resp:2,
+ dead:1,
+ len:3;
+#else
u_int8_t len:3,
dead:1,
resp:2,
src:2;
- u_int8_t status:8;
+#endif
+ u_int8_t status;
u_int16_t orb_hi;
u_int32_t orb_lo;
u_int32_t data[6];
@@ -205,6 +223,15 @@ struct sbp_status{
struct sbp_cmd_status{
#define SBP_SFMT_CURR 0
#define SBP_SFMT_DEFER 1
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int8_t sfmt:2,
+ status:6;
+ u_int8_t valid:1,
+ mark:1,
+ eom:1,
+ ill_len:1,
+ s_key:4;
+#else
u_int8_t status:6,
sfmt:2;
u_int8_t s_key:4,
@@ -212,13 +239,21 @@ struct sbp_cmd_status{
eom:1,
mark:1,
valid:1;
+#endif
u_int8_t s_code;
u_int8_t s_qlfr;
u_int32_t info;
u_int32_t cdb;
+
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int32_t s_keydep:24,
+ fru:8;
+#else
u_int32_t fru:8,
s_keydep:24;
+#endif
u_int32_t vend[2];
+
};
struct sbp_dev{
@@ -240,9 +275,12 @@ struct sbp_dev{
int freeze;
struct cam_path *path;
struct sbp_target *target;
- struct sbp_login_res login;
+ struct fwdma_alloc dma;
+ struct sbp_login_res *login;
struct callout login_callout;
+ struct sbp_ocb *ocb;
STAILQ_HEAD(, sbp_ocb) ocbs;
+ STAILQ_HEAD(, sbp_ocb) free_ocbs;
char vendor[32];
char product[32];
char revision[10];
@@ -260,6 +298,8 @@ struct sbp_target {
struct callout mgm_ocb_timeout;
#define SCAN_DELAY 2
struct callout scan_callout;
+ STAILQ_HEAD(, fw_xfer) xferlist;
+ int n_xfer;
};
struct sbp_softc {
@@ -268,8 +308,6 @@ struct sbp_softc {
struct cam_path *path;
struct sbp_target targets[SBP_NUM_TARGETS];
struct fw_bind fwb;
- STAILQ_HEAD(, sbp_ocb) free_ocbs;
- struct sbp_ocb *ocb;
bus_dma_tag_t dmat;
#define SBP_RESOURCE_SHORTAGE 0x10
unsigned char flags;
@@ -280,11 +318,11 @@ static void sbp_login_callback __P((struct fw_xfer *));
static void sbp_cmd_callback __P((struct fw_xfer *));
static void sbp_orb_pointer __P((struct sbp_dev *, struct sbp_ocb *));
static void sbp_execute_ocb __P((void *, bus_dma_segment_t *, int, int));
-static void sbp_free_ocb __P((struct sbp_softc *, struct sbp_ocb *));
+static void sbp_free_ocb __P((struct sbp_dev *, struct sbp_ocb *));
static void sbp_abort_ocb __P((struct sbp_ocb *, int));
static void sbp_abort_all_ocbs __P((struct sbp_dev *, int));
static struct fw_xfer * sbp_write_cmd __P((struct sbp_dev *, int, int));
-static struct sbp_ocb * sbp_get_ocb __P((struct sbp_softc *));
+static struct sbp_ocb * sbp_get_ocb __P((struct sbp_dev *));
static struct sbp_ocb * sbp_enqueue_ocb __P((struct sbp_dev *, struct sbp_ocb *));
static struct sbp_ocb * sbp_dequeue_ocb __P((struct sbp_dev *, struct sbp_status *));
static void sbp_cam_detach_target __P((struct sbp_target *));
@@ -500,6 +538,8 @@ END_DEBUG
SBP_DEBUG(1)
printf("target:%d mgm_port: %x\n", i, target->mgm_lo);
END_DEBUG
+ STAILQ_INIT(&target->xferlist);
+ target->n_xfer = 0;
STAILQ_INIT(&target->mgm_ocb_queue);
CALLOUT_INIT(&target->mgm_ocb_timeout);
CALLOUT_INIT(&target->scan_callout);
@@ -546,8 +586,38 @@ END_DEBUG
printf("too large lun %d\n", lun);
continue;
}
- target->luns[lun].status = SBP_DEV_RESET;
- target->luns[lun].type = (reg->val & 0xf0000) >> 16;
+ sdev = &target->luns[lun];
+ sdev->status = SBP_DEV_RESET;
+ sdev->type = (reg->val & 0xf0000) >> 16;
+
+ fwdma_malloc(sbp->fd.fc,
+ /* alignment */ sizeof(u_int32_t),
+ SBP_DMA_SIZE, &sdev->dma, BUS_DMA_NOWAIT);
+ if (sdev->dma.v_addr == NULL) {
+ printf("%s: dma space allocation failed\n",
+ __FUNCTION__);
+ return (NULL);
+ }
+ sdev->login = (struct sbp_login_res *) sdev->dma.v_addr;
+ sdev->ocb = (struct sbp_ocb *)
+ ((char *)sdev->dma.v_addr + SBP_LOGIN_SIZE);
+ bzero((char *)sdev->ocb,
+ sizeof (struct sbp_ocb) * SBP_QUEUE_LEN);
+
+ STAILQ_INIT(&sdev->free_ocbs);
+ for (i = 0; i < SBP_QUEUE_LEN; i++) {
+ struct sbp_ocb *ocb;
+ ocb = &sdev->ocb[i];
+ ocb->bus_addr = sdev->dma.bus_addr
+ + SBP_LOGIN_SIZE
+ + sizeof(struct sbp_ocb) * i
+ + offsetof(struct sbp_ocb, orb[0]);
+ if (bus_dmamap_create(sbp->dmat, 0, &ocb->dmamap)) {
+ printf("sbp_attach: cannot create dmamap\n");
+ return (NULL);
+ }
+ sbp_free_ocb(sdev, ocb);
+ }
crom_next(&cc);
}
return target;
@@ -644,23 +714,15 @@ END_DEBUG
sbp_probe_lun(sdev);
SBP_DEBUG(0)
sbp_show_sdev_info(sdev,
-#if 0
- (sdev->status == SBP_DEV_TOATTACH));
-#else
(sdev->status == SBP_DEV_RESET));
-#endif
END_DEBUG
sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET);
switch (sdev->status) {
case SBP_DEV_RESET:
/* new or revived target */
- if (auto_login) {
-#if 0
- sdev->status = SBP_DEV_TOATTACH;
-#endif
+ if (auto_login)
sbp_login(sdev);
- }
break;
case SBP_DEV_TOATTACH:
case SBP_DEV_PROBE:
@@ -699,6 +761,17 @@ END_DEBUG
}
static void
+sbp_post_busreset(void *arg)
+{
+ struct sbp_softc *sbp;
+
+ sbp = (struct sbp_softc *)arg;
+SBP_DEBUG(0)
+ printf("sbp_post_busreset\n");
+END_DEBUG
+}
+
+static void
sbp_post_explore(void *arg)
{
struct sbp_softc *sbp = (struct sbp_softc *)arg;
@@ -767,25 +840,39 @@ END_DEBUG
}
sbp_probe_target((void *)target);
}
-#if 0
- timeout(sbp_release_queue, (caddr_t)sbp, bus_reset_rest * hz / 1000);
-#endif
}
#if NEED_RESPONSE
static void
sbp_loginres_callback(struct fw_xfer *xfer){
-SBP_DEBUG(1)
+ int s;
struct sbp_dev *sdev;
sdev = (struct sbp_dev *)xfer->sc;
+SBP_DEBUG(1)
sbp_show_sdev_info(sdev, 2);
printf("sbp_loginres_callback\n");
END_DEBUG
- fw_xfer_free(xfer);
+ /* recycle */
+ s = splfw();
+ STAILQ_INSERT_TAIL(&sdev->target->sbp->fwb.xferlist, xfer, link);
+ splx(s);
return;
}
#endif
+static __inline void
+sbp_xfer_free(struct fw_xfer *xfer)
+{
+ struct sbp_dev *sdev;
+ int s;
+
+ sdev = (struct sbp_dev *)xfer->sc;
+ fw_xfer_unload(xfer);
+ s = splfw();
+ STAILQ_INSERT_TAIL(&sdev->target->xferlist, xfer, link);
+ splx(s);
+}
+
static void
sbp_login_callback(struct fw_xfer *xfer)
{
@@ -795,7 +882,7 @@ SBP_DEBUG(1)
sbp_show_sdev_info(sdev, 2);
printf("sbp_login_callback\n");
END_DEBUG
- fw_xfer_free(xfer);
+ sbp_xfer_free(xfer);
return;
}
@@ -808,7 +895,7 @@ SBP_DEBUG(2)
sbp_show_sdev_info(sdev, 2);
printf("sbp_cmd_callback\n");
END_DEBUG
- fw_xfer_free(xfer);
+ sbp_xfer_free(xfer);
return;
}
@@ -895,101 +982,6 @@ END_DEBUG
sdev->freeze = 1;
}
-
-#if 0
-static void
-sbp_ping_unit_callback(struct cam_periph *periph, union ccb *ccb)
-{
- struct sbp_dev *sdev;
- sdev = (struct sbp_dev *) ccb->ccb_h.ccb_sdev_ptr;
-SBP_DEBUG(0)
- sbp_show_sdev_info(sdev, 2);
- printf("sbp_ping_unit_callback\n");
-END_DEBUG
- if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- if (--ccb->ccb_h.retry_count == 0) {
- sbp_show_sdev_info(sdev, 2);
- printf("sbp_ping_unit_callback: "
- "retry count exceeded\n");
- sdev->status = SBP_DEV_RETRY;
- free(ccb, M_SBP);
- } else {
- /* requeue */
- xpt_action(ccb);
- xpt_release_devq(sdev->path, sdev->freeze, TRUE);
- sdev->freeze = 1; /* we will freeze */
- }
- } else {
- free(ccb->csio.data_ptr, M_SBP);
- free(ccb, M_SBP);
- sdev->status = SBP_DEV_ATTACHED;
- xpt_release_devq(sdev->path, sdev->freeze, TRUE);
- sdev->freeze = 0;
- }
-}
-
-/*
- * XXX Some devices need to execute inquiry or read_capacity
- * after bus_rest during busy transfer.
- * Otherwise they return incorrect result for READ(and WRITE?)
- * command without any SBP-II/SCSI error.
- *
- * e.g. Maxtor 3000XT, Yano A-dish.
- */
-static void
-sbp_ping_unit(struct sbp_dev *sdev)
-{
- union ccb *ccb;
- struct scsi_inquiry_data *inq_buf;
-
-
- ccb = malloc(sizeof(union ccb), M_SBP, M_NOWAIT | M_ZERO);
- if (ccb == NULL) {
- printf("sbp_ping_unit: malloc failed\n");
- return;
- }
-
- inq_buf = (struct scsi_inquiry_data *)
- malloc(sizeof(*inq_buf), M_SBP, M_NOWAIT);
- if (inq_buf == NULL) {
- free(ccb, M_SBP);
- printf("sbp_ping_unit: malloc failed\n");
- return;
- }
-
-SBP_DEBUG(0)
- sbp_show_sdev_info(sdev, 2);
- printf("sbp_ping_unit\n");
-END_DEBUG
-
- /*
- * We need to execute this command before any other queued command.
- * Make priority 0 and freeze the queue after execution for retry.
- * cam's scan_lun command doesn't provide this feature.
- */
- xpt_setup_ccb(&ccb->ccb_h, sdev->path, 0/*priority (high)*/);
- scsi_inquiry(
- &ccb->csio,
- /*retries*/ 5,
- sbp_ping_unit_callback,
- MSG_SIMPLE_Q_TAG,
- (u_int8_t *)inq_buf,
- SHORT_INQUIRY_LENGTH,
- /*evpd*/FALSE,
- /*page_code*/0,
- SSD_MIN_SIZE,
- /*timeout*/60000
- );
- ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
- ccb->ccb_h.ccb_sdev_ptr = sdev;
- xpt_action(ccb);
- if (sdev->status != SBP_DEV_ATTACHED)
- sdev->status = SBP_DEV_PROBE;
- xpt_release_devq(sdev->path, sdev->freeze, TRUE);
- sdev->freeze = 1; /* We will freeze the queue */
-}
-#endif
-
static __inline void
sbp_scan_dev(struct sbp_dev *sdev)
{
@@ -1012,7 +1004,7 @@ SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);
printf("sbp_do_attach\n");
END_DEBUG
- fw_xfer_free(xfer);
+ sbp_xfer_free(xfer);
if (sdev->path == NULL)
xpt_create_path(&sdev->path, xpt_periph,
@@ -1043,7 +1035,7 @@ SBP_DEBUG(1)
sbp_show_sdev_info(sdev, 2);
printf("sbp_cmd_callback\n");
END_DEBUG
- fw_xfer_free(xfer);
+ sbp_xfer_free(xfer);
if (sdev->path) {
xpt_release_devq(sdev->path, sdev->freeze, TRUE);
sdev->freeze = 0;
@@ -1083,7 +1075,7 @@ SBP_DEBUG(1)
sbp_show_sdev_info(sdev, 2);
printf("sbp_busy_timeout_callback\n");
END_DEBUG
- fw_xfer_free(xfer);
+ sbp_xfer_free(xfer);
sbp_agent_reset(sdev);
}
@@ -1100,8 +1092,8 @@ END_DEBUG
xfer->act.hand = sbp_busy_timeout_callback;
fp = (struct fw_pkt *)xfer->send.buf;
- fp->mode.wreqq.dest_hi = htons(0xffff);
- fp->mode.wreqq.dest_lo = htonl(0xf0000000 | BUSY_TIMEOUT);
+ fp->mode.wreqq.dest_hi = 0xffff;
+ fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT;
fp->mode.wreqq.data = htonl((1 << (13+12)) | 0xf);
fw_asyreq(xfer->fc, -1, xfer);
}
@@ -1121,8 +1113,8 @@ END_DEBUG
xfer->act.hand = sbp_busy_timeout;
fp = (struct fw_pkt *)xfer->send.buf;
- fp->mode.wreqq.dest_hi = htons(0xffff);
- fp->mode.wreqq.dest_lo = htonl(0xf0000000 | RESET_START);
+ fp->mode.wreqq.dest_hi = 0xffff;
+ fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START;
fp->mode.wreqq.data = htonl(0xf);
fw_asyreq(xfer->fc, -1, xfer);
}
@@ -1144,14 +1136,14 @@ END_DEBUG
xfer->act.hand = sbp_cmd_callback;
fp = (struct fw_pkt *)xfer->send.buf;
- fp->mode.wreqb.len = htons(8);
+ fp->mode.wreqb.len = 8;
fp->mode.wreqb.extcode = 0;
fp->mode.wreqb.payload[0] =
htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16));
- fp->mode.wreqb.payload[1] = htonl(vtophys(&ocb->orb[0]));
+ fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr);
if(fw_asyreq(xfer->fc, -1, xfer) != 0){
- fw_xfer_free(xfer);
+ sbp_xfer_free(xfer);
ocb->ccb->ccb_h.status = CAM_REQ_INVALID;
xpt_done(ocb->ccb);
}
@@ -1183,36 +1175,55 @@ sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
{
struct fw_xfer *xfer;
struct fw_pkt *fp;
+ struct sbp_target *target;
+ int s, new = 0;
- xfer = fw_xfer_alloc(M_SBP);
- if(xfer == NULL){
- return NULL;
+ target = sdev->target;
+ s = splfw();
+ xfer = STAILQ_FIRST(&target->xferlist);
+ if (xfer == NULL) {
+ if (target->n_xfer > 5 /* XXX */) {
+ printf("sbp: no more xfer for this target\n");
+ splx(s);
+ return(NULL);
+ }
+ xfer = fw_xfer_alloc_buf(M_SBP, 24, 12);
+ if(xfer == NULL){
+ printf("sbp: fw_xfer_alloc_buf failed\n");
+ splx(s);
+ return NULL;
+ }
+ target->n_xfer ++;
+ if (debug)
+ printf("sbp: alloc %d xfer\n", target->n_xfer);
+ new = 1;
+ } else {
+ STAILQ_REMOVE_HEAD(&target->xferlist, link);
}
+ splx(s);
+
+ microtime(&xfer->tv);
+
if (tcode == FWTCODE_WREQQ)
xfer->send.len = 16;
else
xfer->send.len = 24;
+ xfer->recv.len = 12;
- xfer->send.buf = malloc(xfer->send.len, M_FW, M_NOWAIT);
- if(xfer->send.buf == NULL){
- fw_xfer_free(xfer);
- return NULL;
+ if (new) {
+ xfer->spd = min(sdev->target->fwdev->speed, max_speed);
+ xfer->fc = sdev->target->sbp->fd.fc;
+ xfer->retry_req = fw_asybusy;
}
-
- xfer->send.off = 0;
- xfer->spd = min(sdev->target->fwdev->speed, max_speed);
xfer->sc = (caddr_t)sdev;
- xfer->fc = sdev->target->sbp->fd.fc;
- xfer->retry_req = fw_asybusy;
-
fp = (struct fw_pkt *)xfer->send.buf;
- fp->mode.wreqq.dest_hi = htons(sdev->login.cmd_hi);
- fp->mode.wreqq.dest_lo = htonl(sdev->login.cmd_lo + offset);
+ fp->mode.wreqq.dest_hi = sdev->login->cmd_hi;
+ fp->mode.wreqq.dest_lo = sdev->login->cmd_lo + offset;
fp->mode.wreqq.tlrt = 0;
fp->mode.wreqq.tcode = tcode;
fp->mode.wreqq.pri = 0;
xfer->dst = FWLOCALBUS | sdev->target->fwdev->dst;
- fp->mode.wreqq.dst = htons(xfer->dst);
+ fp->mode.wreqq.dst = xfer->dst;
return xfer;
@@ -1240,8 +1251,7 @@ sbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb)
STAILQ_REMOVE_HEAD(&target->mgm_ocb_queue, ocb);
goto start;
}
- if ((ocb = sbp_get_ocb(target->sbp)) == NULL) {
- target->sbp->flags |= SBP_RESOURCE_SHORTAGE;
+ if ((ocb = sbp_get_ocb(sdev)) == NULL) {
splx(s);
return;
}
@@ -1262,20 +1272,21 @@ END_DEBUG
switch (func) {
case ORB_FUN_LGI:
ocb->orb[2] = htonl(nid << 16);
- ocb->orb[3] = htonl(vtophys(&sdev->login));
+ ocb->orb[3] = htonl(sdev->dma.bus_addr);
ocb->orb[4] = htonl(ORB_NOTIFY | ORB_EXV | sdev->lun_id);
- ocb->orb[5] = htonl(sizeof(struct sbp_login_res));
+ ocb->orb[5] = htonl(SBP_LOGIN_SIZE);
+ fwdma_sync(&sdev->dma, BUS_DMASYNC_PREREAD);
break;
case ORB_FUN_ATA:
ocb->orb[0] = htonl((0 << 16) | 0);
- ocb->orb[1] = htonl(vtophys(&aocb->orb[0]));
+ ocb->orb[1] = htonl(aocb->bus_addr & 0xffffffff);
/* fall through */
case ORB_FUN_RCN:
case ORB_FUN_LGO:
case ORB_FUN_LUR:
case ORB_FUN_RST:
case ORB_FUN_ATS:
- ocb->orb[4] = htonl(ORB_NOTIFY | func | sdev->login.id);
+ ocb->orb[4] = htonl(ORB_NOTIFY | func | sdev->login->id);
break;
}
@@ -1298,12 +1309,12 @@ start:
xfer->act.hand = sbp_login_callback;
fp = (struct fw_pkt *)xfer->send.buf;
- fp->mode.wreqb.dest_hi = htons(sdev->target->mgm_hi);
- fp->mode.wreqb.dest_lo = htonl(sdev->target->mgm_lo);
- fp->mode.wreqb.len = htons(8);
+ fp->mode.wreqb.dest_hi = sdev->target->mgm_hi;
+ fp->mode.wreqb.dest_lo = sdev->target->mgm_lo;
+ fp->mode.wreqb.len = 8;
fp->mode.wreqb.extcode = 0;
fp->mode.wreqb.payload[0] = htonl(nid << 16);
- fp->mode.wreqb.payload[1] = htonl(vtophys(&ocb->orb[0]));
+ fp->mode.wreqb.payload[1] = htonl(ocb->bus_addr);
fw_asyreq(xfer->fc, -1, xfer);
}
@@ -1348,7 +1359,7 @@ SBP_DEBUG(0)
sbp_print_scsi_cmd(ocb);
/* XXX need decode status */
sbp_show_sdev_info(ocb->sdev, 2);
- printf("SCSI status %x sfmt %x valid %x key %x code %x qlfr %x len %d",
+ printf("SCSI status %x sfmt %x valid %x key %x code %x qlfr %x len %d\n",
sbp_cmd_status->status,
sbp_cmd_status->sfmt,
sbp_cmd_status->valid,
@@ -1357,20 +1368,6 @@ SBP_DEBUG(0)
sbp_cmd_status->s_qlfr,
sbp_status->len
);
-#if 0 /* XXX */
- if (sbp_cmd_status->status == SCSI_STATUS_CHECK_COND) {
- printf(" %s\n", scsi_sense_key_text[sbp_cmd_status->s_key]);
- scsi_sense_desc(
- sbp_cmd_status->s_code,
- sbp_cmd_status->s_qlfr,
- ocb->ccb->ccb_h.path->device->inq_data
- )
- } else {
- printf("\n");
- }
-#else
- printf("\n");
-#endif
END_DEBUG
switch (sbp_cmd_status->status) {
@@ -1485,7 +1482,8 @@ END_DEBUG
}
static void
-sbp_recv1(struct fw_xfer *xfer){
+sbp_recv1(struct fw_xfer *xfer)
+{
struct fw_pkt *rfp;
#if NEED_RESPONSE
struct fw_pkt *sfp;
@@ -1506,25 +1504,24 @@ printf("sbp %x %d %d %08x %08x %08x %08x\n",
printf("sbp %08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7]));
printf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), ntohl(ld[11]));
*/
+
+ sbp = (struct sbp_softc *)xfer->sc;
if(xfer->resp != 0){
printf("sbp_recv: xfer->resp != 0\n");
- fw_xfer_free( xfer);
- return;
+ goto done0;
}
if(xfer->recv.buf == NULL){
printf("sbp_recv: xfer->recv.buf == NULL\n");
- fw_xfer_free( xfer);
- return;
+ goto done0;
}
sbp = (struct sbp_softc *)xfer->sc;
rfp = (struct fw_pkt *)xfer->recv.buf;
if(rfp->mode.wreqb.tcode != FWTCODE_WREQB){
printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode);
- fw_xfer_free( xfer);
- return;
+ goto done0;
}
sbp_status = (struct sbp_status *)rfp->mode.wreqb.payload;
- addr = ntohl(rfp->mode.wreqb.dest_lo);
+ addr = rfp->mode.wreqb.dest_lo;
SBP_DEBUG(2)
printf("received address 0x%x\n", addr);
END_DEBUG
@@ -1532,16 +1529,14 @@ END_DEBUG
if (t >= SBP_NUM_TARGETS) {
device_printf(sbp->fd.dev,
"sbp_recv1: invalid target %d\n", t);
- fw_xfer_free(xfer);
- return;
+ goto done0;
}
target = &sbp->targets[t];
l = SBP_ADDR2LUN(addr);
if (l >= target->num_lun) {
device_printf(sbp->fd.dev,
"sbp_recv1: invalid lun %d (target=%d)\n", l, t);
- fw_xfer_free(xfer);
- return;
+ goto done0;
}
sdev = &target->luns[l];
@@ -1648,7 +1643,8 @@ END_DEBUG
orb_fun = ntohl(ocb->orb[4]) & ORB_FUN_MSK;
switch(orb_fun) {
case ORB_FUN_LGI:
- login_res = &sdev->login;
+ fwdma_sync(&sdev->dma, BUS_DMASYNC_POSTREAD);
+ login_res = sdev->login;
login_res->len = ntohs(login_res->len);
login_res->id = ntohs(login_res->id);
login_res->cmd_hi = ntohs(login_res->cmd_hi);
@@ -1658,14 +1654,7 @@ SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);
printf("login: len %d, ID %d, cmd %08x%08x, recon_hold %d\n", login_res->len, login_res->id, login_res->cmd_hi, login_res->cmd_lo, ntohs(login_res->recon_hold));
END_DEBUG
-#if 0
- sdev->status = SBP_DEV_TOATTACH;
-#endif
-#if 1
sbp_busy_timeout(sdev);
-#else
- sbp_mgm_orb(sdev, ORB_FUN_ATS, NULL);
-#endif
} else {
/* forgot logout? */
sbp_show_sdev_info(sdev, 2);
@@ -1674,7 +1663,7 @@ END_DEBUG
}
break;
case ORB_FUN_RCN:
- login_res = &sdev->login;
+ login_res = sdev->login;
if (status_valid) {
SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);
@@ -1749,11 +1738,12 @@ printf("len %d\n", sbp_status->len);
}
}
- sbp_free_ocb(sbp, ocb);
+ sbp_free_ocb(sdev, ocb);
done:
if (reset_agent)
sbp_agent_reset(sdev);
+done0:
/* The received packet is usually small enough to be stored within
* the buffer. In that case, the controller return ack_complete and
* no respose is necessary.
@@ -1762,12 +1752,10 @@ done:
* ack_complete or ack_pending to upper driver.
*/
#if NEED_RESPONSE
- xfer->send.buf = malloc(12, M_SBP, M_NOWAIT | M_ZERO);
- xfer->send.len = 12;
xfer->send.off = 0;
sfp = (struct fw_pkt *)xfer->send.buf;
sfp->mode.wres.dst = rfp->mode.wreqb.src;
- xfer->dst = ntohs(sfp->mode.wres.dst);
+ xfer->dst = sfp->mode.wres.dst;
xfer->spd = min(sdev->target->fwdev->speed, max_speed);
xfer->act.hand = sbp_loginres_callback;
xfer->retry_req = fw_asybusy;
@@ -1779,7 +1767,9 @@ done:
fw_asyreq(xfer->fc, -1, xfer);
#else
- fw_xfer_free(xfer);
+ /* recycle */
+ xfer->recv.len = SBP_RECV_LEN;
+ STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link);
#endif
return;
@@ -1816,8 +1806,9 @@ END_DEBUG
bzero(sbp, sizeof(struct sbp_softc));
sbp->fd.dev = dev;
sbp->fd.fc = device_get_ivars(dev);
-#define SBP_SEG_MAX 0x8000
- error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1,
+ error = bus_dma_tag_create(/*parent*/sbp->fd.fc->dmat,
+ /* XXX shoud be 4 for sane backend? */
+ /*alignment*/1,
/*boundary*/0,
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
/*highaddr*/BUS_SPACE_MAXADDR,
@@ -1852,20 +1843,6 @@ END_DEBUG
return (ENXIO);
}
- sbp->ocb = (struct sbp_ocb *) contigmalloc(
- sizeof (struct sbp_ocb) * SBP_NUM_OCB,
- M_SBP, M_NOWAIT, 0x10000, 0xffffffff, PAGE_SIZE, 0ul);
- bzero(sbp->ocb, sizeof (struct sbp_ocb) * SBP_NUM_OCB);
-
- if (sbp->ocb == NULL) {
- printf("sbp0: ocb alloction failure\n");
- return (ENOMEM);
- }
-
- STAILQ_INIT(&sbp->free_ocbs);
- for (i = 0; i < SBP_NUM_OCB; i++) {
- sbp_free_ocb(sbp, &sbp->ocb[i]);
- }
if (xpt_bus_register(sbp->sim, /*bus*/0) != CAM_SUCCESS)
goto fail;
@@ -1874,21 +1851,31 @@ END_DEBUG
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
goto fail;
- xfer = fw_xfer_alloc(M_SBP);
- xfer->act.hand = sbp_recv;
- xfer->act_type = FWACT_XFER;
-#if NEED_RESPONSE
- xfer->fc = sbp->fd.fc;
-#endif
- xfer->sc = (caddr_t)sbp;
-
sbp->fwb.start_hi = SBP_BIND_HI;
sbp->fwb.start_lo = SBP_DEV2ADDR(device_get_unit(sbp->fd.dev), 0, 0);
/* We reserve 16 bit space (4 bytes X 64 targets X 256 luns) */
sbp->fwb.addrlen = 0xffff;
- sbp->fwb.xfer = xfer;
+ sbp->fwb.act_type = FWACT_XFER;
+ /* pre-allocate xfer */
+ STAILQ_INIT(&sbp->fwb.xferlist);
+ for (i = 0; i < SBP_NUM_OCB/2; i ++) {
+ xfer = fw_xfer_alloc_buf(M_SBP,
+#if NEED_RESPONSE
+ /* send */12,
+#else
+ /* send */0,
+#endif
+ /* recv */SBP_RECV_LEN);
+ xfer->act.hand = sbp_recv;
+#if NEED_RESPONSE
+ xfer->fc = sbp->fd.fc;
+#endif
+ xfer->sc = (caddr_t)sbp;
+ STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link);
+ }
fw_bindadd(sbp->fd.fc, &sbp->fwb);
+ sbp->fd.post_busreset = sbp_post_busreset;
sbp->fd.post_explore = sbp_post_explore;
if (sbp->fd.fc->status != -1) {
@@ -1900,7 +1887,6 @@ END_DEBUG
return (0);
fail:
cam_sim_free(sbp->sim, /*free_devq*/TRUE);
- contigfree(sbp->ocb, sizeof (struct sbp_ocb) * SBP_NUM_OCB, M_SBP);
return (ENXIO);
}
@@ -1920,11 +1906,13 @@ END_DEBUG
continue;
for (j = 0; j < target->num_lun; j++) {
sdev = &target->luns[j];
+ callout_stop(&sdev->login_callout);
if (sdev->status >= SBP_DEV_TOATTACH &&
sdev->status <= SBP_DEV_ATTACHED)
sbp_mgm_orb(sdev, ORB_FUN_LGO, NULL);
}
}
+
return 0;
}
@@ -1942,33 +1930,56 @@ sbp_detach(device_t dev)
{
struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev));
struct firewire_comm *fc = sbp->fd.fc;
- int i;
+ struct sbp_target *target;
+ struct sbp_dev *sdev;
+ struct fw_xfer *xfer, *next;
+ int i, j;
SBP_DEBUG(0)
printf("sbp_detach\n");
END_DEBUG
-#if 0
- /* bus reset for logout */
- sbp->fd.post_explore = NULL;
- fc->ibr(fc);
-#endif
-
+
for (i = 0; i < SBP_NUM_TARGETS; i ++)
sbp_cam_detach_target(&sbp->targets[i]);
xpt_free_path(sbp->path);
xpt_bus_deregister(cam_sim_path(sbp->sim));
sbp_logout_all(sbp);
+
/* XXX wait for logout completion */
tsleep(&i, FWPRI, "sbpdtc", hz/2);
+ for (i = 0 ; i < SBP_NUM_TARGETS ; i ++) {
+ target = &sbp->targets[i];
+ if (target->luns == NULL)
+ continue;
+ callout_stop(&target->mgm_ocb_timeout);
+ for (j = 0; j < target->num_lun; j++) {
+ sdev = &target->luns[j];
+ if (sdev->status != SBP_DEV_DEAD) {
+ for (i = 0; i < SBP_QUEUE_LEN; i++)
+ bus_dmamap_destroy(sbp->dmat,
+ sdev->ocb[i].dmamap);
+ fwdma_free(sbp->fd.fc, &sdev->dma);
+ }
+ }
+ for (xfer = STAILQ_FIRST(&target->xferlist);
+ xfer != NULL; xfer = next) {
+ next = STAILQ_NEXT(xfer, link);
+ fw_xfer_free(xfer);
+ }
+ free(target->luns, M_SBP);
+ }
+
+ for (xfer = STAILQ_FIRST(&sbp->fwb.xferlist);
+ xfer != NULL; xfer = next) {
+ next = STAILQ_NEXT(xfer, link);
+ fw_xfer_free(xfer);
+ }
+ STAILQ_INIT(&sbp->fwb.xferlist);
fw_bindremove(fc, &sbp->fwb);
- contigfree(sbp->ocb, sizeof (struct sbp_ocb) * SBP_NUM_OCB, M_SBP);
- bus_dma_tag_destroy(sbp->dmat);
- for (i = 0; i < SBP_NUM_TARGETS; i ++)
- if (sbp->targets[i].luns != NULL)
- free(sbp->targets[i].luns, M_SBP);
+ bus_dma_tag_destroy(sbp->dmat);
return (0);
}
@@ -1976,20 +1987,19 @@ END_DEBUG
static void
sbp_cam_detach_target(struct sbp_target *target)
{
- int i;
struct sbp_dev *sdev;
+ int i;
if (target->luns != NULL) {
SBP_DEBUG(0)
printf("sbp_detach_target %d\n", target->target_id);
END_DEBUG
callout_stop(&target->scan_callout);
- callout_stop(&target->mgm_ocb_timeout);
for (i = 0; i < target->num_lun; i++) {
sdev = &target->luns[i];
- callout_stop(&sdev->login_callout);
- if (sdev->status == SBP_DEV_RESET ||
- sdev->status == SBP_DEV_DEAD)
+ if (sdev->status == SBP_DEV_DEAD)
+ continue;
+ if (sdev->status == SBP_DEV_RESET)
continue;
if (sdev->path) {
xpt_async(AC_LOST_DEVICE, sdev->path, NULL);
@@ -2014,7 +2024,7 @@ sbp_timeout(void *arg)
printf("management ORB\n");
/* XXX just ignore for now */
sdev->target->mgm_ocb_cur = NULL;
- sbp_free_ocb(sdev->target->sbp, ocb);
+ sbp_free_ocb(sdev, ocb);
sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL);
return;
}
@@ -2023,17 +2033,8 @@ sbp_timeout(void *arg)
sdev->freeze ++;
sbp_abort_all_ocbs(sdev, CAM_CMD_TIMEOUT);
if (sdev->flags & SBP_DEV_TIMEOUT) {
-#if 0
- struct firewire_comm *fc;
-
- printf("bus reset\n");
- fc = sdev->target->sbp->fd.fc;
- fc->ibr(fc);
- sdev->status == SBP_DEV_RETRY;
-#else
printf("target reset\n");
sbp_mgm_orb(sdev, ORB_FUN_RST, NULL);
-#endif
sdev->flags &= ~SBP_DEV_TIMEOUT;
} else {
printf("agent reset\n");
@@ -2122,7 +2123,7 @@ END_DEBUG
{
struct ccb_scsiio *csio;
struct sbp_ocb *ocb;
- int s, speed;
+ int speed;
void *cdb;
csio = &ccb->csio;
@@ -2166,12 +2167,9 @@ END_DEBUG
}
}
#endif
- if ((ocb = sbp_get_ocb(sbp)) == NULL) {
- s = splfw();
- sbp->flags |= SBP_RESOURCE_SHORTAGE;
- splx(s);
+ if ((ocb = sbp_get_ocb(sdev)) == NULL)
return;
- }
+
ocb->flags = OCB_ACT_CMD;
ocb->sdev = sdev;
ocb->ccb = ccb;
@@ -2179,7 +2177,7 @@ END_DEBUG
ocb->orb[0] = htonl(1 << 31);
ocb->orb[1] = 0;
ocb->orb[2] = htonl(((sbp->fd.fc->nodeid | FWLOCALBUS )<< 16) );
- ocb->orb[3] = htonl(vtophys(ocb->ind_ptr));
+ ocb->orb[3] = htonl(ocb->bus_addr + IND_PTR_OFFSET);
speed = min(target->fwdev->speed, max_speed);
ocb->orb[4] = htonl(ORB_NOTIFY | ORB_CMD_SPD(speed)
| ORB_CMD_MAXP(speed + 7));
@@ -2204,15 +2202,10 @@ printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[0]), ntohl(ocb->orb[1]), ntoh
printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntohl(ocb->orb[6]), ntohl(ocb->orb[7]));
*/
if (ccb->csio.dxfer_len > 0) {
- int s;
-
- if (bus_dmamap_create(sbp->dmat, 0, &ocb->dmamap)) {
- printf("sbp_action1: cannot create dmamap\n");
- break;
- }
+ int s, error;
s = splsoftvm();
- bus_dmamap_load(/*dma tag*/sbp->dmat,
+ error = bus_dmamap_load(/*dma tag*/sbp->dmat,
/*dma map*/ocb->dmamap,
ccb->csio.data_ptr,
ccb->csio.dxfer_len,
@@ -2220,6 +2213,8 @@ printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntoh
ocb,
/*flags*/0);
splx(s);
+ if (error)
+ printf("sbp: bus_dmamap_load error %d\n", error);
} else
sbp_execute_ocb(ocb, NULL, 0, 0);
break;
@@ -2348,13 +2343,25 @@ sbp_execute_ocb(void *arg, bus_dma_segment_t *segments, int seg, int error)
int i;
struct sbp_ocb *ocb;
struct sbp_ocb *prev;
- union ccb *ccb;
bus_dma_segment_t *s;
if (error)
printf("sbp_execute_ocb: error=%d\n", error);
ocb = (struct sbp_ocb *)arg;
+
+SBP_DEBUG(1)
+ printf("sbp_execute_ocb: seg %d", seg);
+ for (i = 0; i < seg; i++)
+#if __FreeBSD_version >= 500000
+ printf(", %tx:%zd", segments[i].ds_addr,
+#else
+ printf(", %x:%d", segments[i].ds_addr,
+#endif
+ segments[i].ds_len);
+ printf("\n");
+END_DEBUG
+
if (seg == 1) {
/* direct pointer */
s = &segments[0];
@@ -2364,17 +2371,6 @@ sbp_execute_ocb(void *arg, bus_dma_segment_t *segments, int seg, int error)
ocb->orb[4] |= htonl(s->ds_len);
} else if(seg > 1) {
/* page table */
-SBP_DEBUG(1)
- printf("sbp_execute_ocb: seg %d", seg);
- for (i = 0; i < seg; i++)
-#if __FreeBSD_version >= 500000
- printf(", %tx:%zd", segments[i].ds_addr,
-#else
- printf(", %x:%d", segments[i].ds_addr,
-#endif
- segments[i].ds_len);
- printf("\n");
-END_DEBUG
for (i = 0; i < seg; i++) {
s = &segments[i];
SBP_DEBUG(0)
@@ -2396,8 +2392,12 @@ END_DEBUG
ocb->orb[4] |= htonl(ORB_CMD_PTBL | seg);
}
- ccb = ocb->ccb;
+ if (seg > 0)
+ bus_dmamap_sync(ocb->sdev->target->sbp->dmat, ocb->dmamap,
+ (ntohl(ocb->orb[4]) & ORB_CMD_IN) ?
+ BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
prev = sbp_enqueue_ocb(ocb->sdev, ocb);
+ fwdma_sync(&ocb->sdev->dma, BUS_DMASYNC_PREWRITE);
if (prev == NULL)
sbp_orb_pointer(ocb->sdev, ocb);
}
@@ -2426,7 +2426,7 @@ SBP_DEBUG(1)
#else
printf("orb: 0x%x next: 0x%lx, flags %x\n",
#endif
- vtophys(&ocb->orb[0]), ntohl(ocb->orb[1]), flags);
+ ocb->bus_addr, ntohl(ocb->orb[1]), flags);
END_DEBUG
if (OCB_MATCH(ocb, sbp_status)) {
/* found */
@@ -2434,10 +2434,14 @@ END_DEBUG
if (ocb->ccb != NULL)
untimeout(sbp_timeout, (caddr_t)ocb,
ocb->ccb->ccb_h.timeout_ch);
- if (ocb->dmamap != NULL) {
- bus_dmamap_destroy(sdev->target->sbp->dmat,
- ocb->dmamap);
- ocb->dmamap = NULL;
+ if (ntohl(ocb->orb[4]) & 0xffff) {
+ bus_dmamap_sync(sdev->target->sbp->dmat,
+ ocb->dmamap,
+ (ntohl(ocb->orb[4]) & ORB_CMD_IN) ?
+ BUS_DMASYNC_POSTREAD :
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sdev->target->sbp->dmat,
+ ocb->dmamap);
}
if (next != NULL && sbp_status->src == 1)
sbp_orb_pointer(sdev, next);
@@ -2464,9 +2468,9 @@ sbp_enqueue_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb)
SBP_DEBUG(2)
sbp_show_sdev_info(sdev, 2);
#if __FreeBSD_version >= 500000
- printf("sbp_enqueue_ocb orb=0x%tx in physical memory\n", vtophys(&ocb->orb[0]));
+ printf("sbp_enqueue_ocb orb=0x%tx in physical memory\n", ocb->bus_addr);
#else
- printf("sbp_enqueue_ocb orb=0x%x in physical memory\n", vtophys(&ocb->orb[0]));
+ printf("sbp_enqueue_ocb orb=0x%x in physical memory\n", ocb->bus_addr);
#endif
END_DEBUG
prev = STAILQ_LAST(&sdev->ocbs, sbp_ocb, ocb);
@@ -2479,13 +2483,13 @@ END_DEBUG
if (prev != NULL ) {
SBP_DEBUG(1)
#if __FreeBSD_version >= 500000
- printf("linking chain 0x%tx -> 0x%tx\n", vtophys(&prev->orb[0]),
+ printf("linking chain 0x%tx -> 0x%tx\n", prev->bus_addr,
#else
- printf("linking chain 0x%x -> 0x%x\n", vtophys(&prev->orb[0]),
+ printf("linking chain 0x%x -> 0x%x\n", prev->bus_addr,
#endif
- vtophys(&ocb->orb[0]));
+ ocb->bus_addr);
END_DEBUG
- prev->orb[1] = htonl(vtophys(&ocb->orb[0]));
+ prev->orb[1] = htonl(ocb->bus_addr);
prev->orb[0] = 0;
}
splx(s);
@@ -2494,37 +2498,27 @@ END_DEBUG
}
static struct sbp_ocb *
-sbp_get_ocb(struct sbp_softc *sbp)
+sbp_get_ocb(struct sbp_dev *sdev)
{
struct sbp_ocb *ocb;
int s = splfw();
- ocb = STAILQ_FIRST(&sbp->free_ocbs);
+ ocb = STAILQ_FIRST(&sdev->free_ocbs);
if (ocb == NULL) {
printf("ocb shortage!!!\n");
return NULL;
}
- STAILQ_REMOVE_HEAD(&sbp->free_ocbs, ocb);
+ STAILQ_REMOVE_HEAD(&sdev->free_ocbs, ocb);
splx(s);
ocb->ccb = NULL;
return (ocb);
}
static void
-sbp_free_ocb(struct sbp_softc *sbp, struct sbp_ocb *ocb)
+sbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb)
{
-#if 0 /* XXX make sure that ocb has ccb */
- if ((sbp->flags & SBP_RESOURCE_SHORTAGE) != 0 &&
- (ocb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
- ocb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
- sbp->flags &= ~SBP_RESOURCE_SHORTAGE;
- }
-#else
- if ((sbp->flags & SBP_RESOURCE_SHORTAGE) != 0)
- sbp->flags &= ~SBP_RESOURCE_SHORTAGE;
-#endif
ocb->flags = 0;
ocb->ccb = NULL;
- STAILQ_INSERT_TAIL(&sbp->free_ocbs, ocb, ocb);
+ STAILQ_INSERT_TAIL(&sdev->free_ocbs, ocb, ocb);
}
static void
@@ -2533,28 +2527,32 @@ sbp_abort_ocb(struct sbp_ocb *ocb, int status)
struct sbp_dev *sdev;
sdev = ocb->sdev;
-SBP_DEBUG(1)
+SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);
#if __FreeBSD_version >= 500000
printf("sbp_abort_ocb 0x%tx\n",
#else
printf("sbp_abort_ocb 0x%x\n",
#endif
- vtophys(&ocb->orb[0]));
+ ocb->bus_addr);
+END_DEBUG
+SBP_DEBUG(1)
if (ocb->ccb != NULL)
sbp_print_scsi_cmd(ocb);
END_DEBUG
+ if (ntohl(ocb->orb[4]) & 0xffff) {
+ bus_dmamap_sync(sdev->target->sbp->dmat, ocb->dmamap,
+ (ntohl(ocb->orb[4]) & ORB_CMD_IN) ?
+ BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sdev->target->sbp->dmat, ocb->dmamap);
+ }
if (ocb->ccb != NULL) {
untimeout(sbp_timeout, (caddr_t)ocb,
ocb->ccb->ccb_h.timeout_ch);
ocb->ccb->ccb_h.status = status;
xpt_done(ocb->ccb);
}
- if (ocb->dmamap != NULL) {
- bus_dmamap_destroy(sdev->target->sbp->dmat, ocb->dmamap);
- ocb->dmamap = NULL;
- }
- sbp_free_ocb(sdev->target->sbp, ocb);
+ sbp_free_ocb(sdev, ocb);
}
static void