summaryrefslogtreecommitdiffstats
path: root/sys/dev/amr
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2007-12-12 05:55:03 +0000
committerscottl <scottl@FreeBSD.org>2007-12-12 05:55:03 +0000
commit08536bf15543e6d8bffef1874897e7b7f7145865 (patch)
treec6052c69e3483520de68c4fa40ccdc4fe660fc59 /sys/dev/amr
parent5929e7ecb673101b3cb117fc8af4281cc71b3d0d (diff)
downloadFreeBSD-src-08536bf15543e6d8bffef1874897e7b7f7145865.zip
FreeBSD-src-08536bf15543e6d8bffef1874897e7b7f7145865.tar.gz
Rewrite the DMA code paths from being an impenitrable maze of special cases
to a much saner and simplier unified code path. Along the way, fix various CAM nits and bugs so that the passthrough works correctly for all cases.
Diffstat (limited to 'sys/dev/amr')
-rw-r--r--sys/dev/amr/amr.c488
-rw-r--r--sys/dev/amr/amr_cam.c91
-rw-r--r--sys/dev/amr/amr_pci.c93
-rw-r--r--sys/dev/amr/amrvar.h24
4 files changed, 260 insertions, 436 deletions
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
index c864d63..d65cdc1 100644
--- a/sys/dev/amr/amr.c
+++ b/sys/dev/amr/amr.c
@@ -140,9 +140,9 @@ static int amr_mapcmd(struct amr_command *ac);
static void amr_unmapcmd(struct amr_command *ac);
static int amr_start(struct amr_command *ac);
static void amr_complete(void *context, int pending);
-static void amr_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error);
-static void amr_setup_dma64map(void *arg, bus_dma_segment_t *segs, int nsegments, int error);
-static void amr_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error);
+static void amr_setup_sg(void *arg, bus_dma_segment_t *segs, int nsegments, int error);
+static void amr_setup_data(void *arg, bus_dma_segment_t *segs, int nsegments, int error);
+static void amr_setup_ccb(void *arg, bus_dma_segment_t *segs, int nsegments, int error);
/*
* Status monitoring
@@ -572,9 +572,6 @@ amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag,
adapter = (ali.ui.fcs.adapno) ^ 'm' << 8;
- ap = malloc(sizeof(struct amr_passthrough),
- M_AMR, M_WAITOK | M_ZERO);
-
mb = (void *)&ali.mbox[0];
if ((ali.mbox[0] == FC_DEL_LOGDRV && ali.mbox[2] == OP_DEL_LOGDRV) || /* delete */
@@ -587,6 +584,12 @@ amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag,
}
if (ali.mbox[0] == AMR_CMD_PASS) {
+ mtx_lock(&sc->amr_list_lock);
+ while ((ac = amr_alloccmd(sc)) == NULL)
+ msleep(sc, &sc->amr_list_lock, PPAUSE, "amrioc", hz);
+ mtx_unlock(&sc->amr_list_lock);
+ ap = &ac->ac_ccb->ccb_pthru;
+
error = copyin((void *)(uintptr_t)mb->mb_physaddr, ap,
sizeof(struct amr_passthrough));
if (error)
@@ -603,21 +606,16 @@ amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag,
break;
}
- mtx_lock(&sc->amr_list_lock);
- while ((ac = amr_alloccmd(sc)) == NULL)
- msleep(sc, &sc->amr_list_lock, PPAUSE, "amrioc", hz);
-
- ac_flags = AMR_CMD_DATAIN|AMR_CMD_DATAOUT|AMR_CMD_CCB_DATAIN|AMR_CMD_CCB_DATAOUT;
+ ac_flags = AMR_CMD_DATAIN|AMR_CMD_DATAOUT|AMR_CMD_CCB;
bzero(&ac->ac_mailbox, sizeof(ac->ac_mailbox));
ac->ac_mailbox.mb_command = AMR_CMD_PASS;
ac->ac_flags = ac_flags;
- ac->ac_data = ap;
- ac->ac_length = sizeof(struct amr_passthrough);
- ac->ac_ccb_data = dp;
- ac->ac_ccb_length = ap->ap_data_transfer_length;
+ ac->ac_data = dp;
+ ac->ac_length = ap->ap_data_transfer_length;
temp = (void *)(uintptr_t)ap->ap_data_transfer_address;
+ mtx_lock(&sc->amr_list_lock);
error = amr_wait_command(ac);
mtx_unlock(&sc->amr_list_lock);
if (error)
@@ -706,8 +704,6 @@ amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag,
mtx_unlock(&sc->amr_list_lock);
if (dp != NULL)
free(dp, M_AMR);
- if (ap != NULL)
- free(ap, M_AMR);
return(error);
}
@@ -729,7 +725,7 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
unsigned long au_length;
unsigned char *au_cmd;
int *au_statusp, au_direction;
- int error, ac_flags = 0;
+ int error;
struct amr_passthrough *ap; /* 60 bytes */
int logical_drives_changed = 0;
@@ -832,8 +828,6 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
}
/* Allocate this now before the mutex gets held */
- if (au_cmd[0] == AMR_CMD_PASS)
- ap = malloc(sizeof(struct amr_passthrough), M_AMR, M_WAITOK|M_ZERO);
mtx_lock(&sc->amr_list_lock);
while ((ac = amr_alloccmd(sc)) == NULL)
@@ -843,6 +837,9 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
if (au_cmd[0] == AMR_CMD_PASS) {
int len;
+ ap = &ac->ac_ccb->ccb_pthru;
+ bzero(ap, sizeof(struct amr_passthrough));
+
/* copy cdb */
len = au_cmd[2];
ap->ap_cdb_length = len;
@@ -860,13 +857,8 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
/* XXX what about the request-sense area? does the caller want it? */
/* build command */
- ac->ac_data = ap;
- ac->ac_length = sizeof(struct amr_passthrough);
- ac->ac_ccb_data = dp;
- ac->ac_ccb_length = au_length;
-
ac->ac_mailbox.mb_command = AMR_CMD_PASS;
- ac_flags = AMR_CMD_DATAIN|AMR_CMD_DATAOUT|AMR_CMD_CCB_DATAIN|AMR_CMD_CCB_DATAOUT;
+ ac->ac_flags = AMR_CMD_CCB;
} else {
/* direct command to controller */
@@ -878,14 +870,13 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
mbi->mb_param = au_cmd[2];
mbi->mb_pad[0] = au_cmd[3];
mbi->mb_drive = au_cmd[4];
-
- /* build the command */
- ac->ac_data = dp;
- ac->ac_length = au_length;
- ac_flags = AMR_CMD_DATAIN|AMR_CMD_DATAOUT;
+ ac->ac_flags = 0;
}
- ac->ac_flags = ac_flags;
+ /* build the command */
+ ac->ac_data = dp;
+ ac->ac_length = au_length;
+ ac->ac_flags |= AMR_CMD_DATAIN|AMR_CMD_DATAOUT;
/* run the command */
error = amr_wait_command(ac);
@@ -899,7 +890,7 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
}
debug(2, "copyout %ld bytes from %p -> %p", au_length, dp, au_buffer);
if (dp != NULL)
- debug(2, "%jd", (uintptr_t)dp);
+ debug(2, "%p status 0x%x", dp, ac->ac_status);
*au_statusp = ac->ac_status;
out:
@@ -913,8 +904,6 @@ out:
mtx_unlock(&sc->amr_list_lock);
if (dp != NULL)
free(dp, M_AMR);
- if (ap != NULL)
- free(ap, M_AMR);
#ifndef LSI
if (logical_drives_changed)
@@ -1420,21 +1409,24 @@ amr_setup_polled_dmamap(void *arg, bus_dma_segment_t *segs, int nsegs, int err)
{
struct amr_command *ac = arg;
struct amr_softc *sc = ac->ac_sc;
- int flags;
+ int mb_channel;
- flags = 0;
- if (ac->ac_flags & AMR_CMD_DATAIN)
- flags |= BUS_DMASYNC_PREREAD;
- if (ac->ac_flags & AMR_CMD_DATAOUT)
- flags |= BUS_DMASYNC_PREWRITE;
+ amr_setup_sg(arg, segs, nsegs, err);
+ /* for AMR_CMD_CONFIG Read/Write the s/g count goes elsewhere */
+ mb_channel = ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel;
+ if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG &&
+ ((mb_channel == AMR_CONFIG_READ_NVRAM_CONFIG) ||
+ (mb_channel == AMR_CONFIG_WRITE_NVRAM_CONFIG)))
+ ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param = ac->ac_nsegments;
+
+ ac->ac_mailbox.mb_nsgelem = ac->ac_nsegments;
+ ac->ac_mailbox.mb_physaddr = ac->ac_mb_physaddr;
if (AC_IS_SG64(ac)) {
- amr_setup_dma64map(arg, segs, nsegs, err);
- bus_dmamap_sync(sc->amr_buffer64_dmat,ac->ac_dma64map, flags);
- } else {
- amr_setup_dmamap(arg, segs, nsegs, err);
- bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap, flags);
+ ac->ac_sg64_hi = 0;
+ ac->ac_sg64_lo = ac->ac_sgbusaddr;
}
+
sc->amr_poll_command1(sc, ac);
}
@@ -1445,8 +1437,6 @@ amr_setup_polled_dmamap(void *arg, bus_dma_segment_t *segs, int nsegs, int err)
static int
amr_quartz_poll_command(struct amr_command *ac)
{
- bus_dma_tag_t tag;
- bus_dmamap_t datamap;
struct amr_softc *sc = ac->ac_sc;
int error;
@@ -1455,17 +1445,17 @@ amr_quartz_poll_command(struct amr_command *ac)
error = 0;
if (AC_IS_SG64(ac)) {
- tag = sc->amr_buffer64_dmat;
- datamap = ac->ac_dma64map;
+ ac->ac_tag = sc->amr_buffer64_dmat;
+ ac->ac_datamap = ac->ac_dma64map;
} else {
- tag = sc->amr_buffer_dmat;
- datamap = ac->ac_dmamap;
+ ac->ac_tag = sc->amr_buffer_dmat;
+ ac->ac_datamap = ac->ac_dmamap;
}
/* now we have a slot, we can map the command (unmapped in amr_complete) */
if (ac->ac_data != 0) {
- if (bus_dmamap_load(tag, datamap, ac->ac_data, ac->ac_length,
- amr_setup_polled_dmamap, ac, BUS_DMA_NOWAIT) != 0) {
+ if (bus_dmamap_load(ac->ac_tag, ac->ac_datamap, ac->ac_data,
+ ac->ac_length, amr_setup_polled_dmamap, ac, BUS_DMA_NOWAIT) != 0) {
error = 1;
}
} else {
@@ -1494,10 +1484,7 @@ amr_quartz_poll_command1(struct amr_softc *sc, struct amr_command *ac)
device_printf(sc->amr_dev, "adapter is busy\n");
mtx_unlock(&sc->amr_hw_lock);
if (ac->ac_data != NULL) {
- if (AC_IS_SG64(ac))
- bus_dmamap_unload(sc->amr_buffer64_dmat, ac->ac_dma64map);
- else
- bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap);
+ bus_dmamap_unload(ac->ac_tag, ac->ac_datamap);
}
ac->ac_status=0;
return(1);
@@ -1535,17 +1522,12 @@ amr_quartz_poll_command1(struct amr_softc *sc, struct amr_command *ac)
/* unmap the command's data buffer */
if (ac->ac_flags & AMR_CMD_DATAIN) {
- bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap,
- BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(ac->ac_tag, ac->ac_datamap, BUS_DMASYNC_POSTREAD);
}
if (ac->ac_flags & AMR_CMD_DATAOUT) {
- bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap,
- BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_sync(ac->ac_tag, ac->ac_datamap, BUS_DMASYNC_POSTWRITE);
}
- if (AC_IS_SG64(ac))
- bus_dmamap_unload(sc->amr_buffer64_dmat, ac->ac_dma64map);
- else
- bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap);
+ bus_dmamap_unload(ac->ac_tag, ac->ac_datamap);
return(error);
}
@@ -1574,289 +1556,141 @@ amr_freeslot(struct amr_command *ac)
* These functions may be safely called multiple times on a given command.
*/
static void
-amr_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
+amr_setup_sg(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
{
struct amr_command *ac = (struct amr_command *)arg;
struct amr_sgentry *sg;
- int i;
- u_int8_t *sgc;
+ struct amr_sg64entry *sg64;
+ int flags, i;
debug_called(3);
- /* get base address of s/g table */
- sg = ac->ac_sg.sg32;
-
- /* save data physical address */
-
- /* for AMR_CMD_CONFIG Read/Write the s/g count goes elsewhere */
- if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG && (
- ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel == AMR_CONFIG_READ_NVRAM_CONFIG ||
- ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel == AMR_CONFIG_WRITE_NVRAM_CONFIG)) {
- sgc = &(((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param);
- } else {
- sgc = &ac->ac_mailbox.mb_nsgelem;
- }
-
- /* decide whether we need to populate the s/g table */
- if (nsegments < 2) {
- *sgc = 0;
- ac->ac_mailbox.mb_nsgelem = 0;
- ac->ac_mailbox.mb_physaddr = segs[0].ds_addr;
- } else {
- ac->ac_mailbox.mb_nsgelem = nsegments;
- *sgc = nsegments;
- /* XXX Setting these to 0 might not be needed. */
- ac->ac_sg64_lo = 0;
- ac->ac_sg64_hi = 0;
- ac->ac_mailbox.mb_physaddr = ac->ac_sgbusaddr;
- for (i = 0; i < nsegments; i++, sg++) {
- sg->sg_addr = segs[i].ds_addr;
- sg->sg_count = segs[i].ds_len;
- }
- }
-
-}
-
-static void
-amr_setup_dma64map(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
-{
- struct amr_command *ac = (struct amr_command *)arg;
- struct amr_sg64entry *sg;
- int i;
- u_int8_t *sgc;
-
- debug_called(3);
-
- /* get base address of s/g table */
- sg = ac->ac_sg.sg64;
-
- /* save data physical address */
-
- /* for AMR_CMD_CONFIG Read/Write the s/g count goes elsewhere */
- if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG && (
- ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel == AMR_CONFIG_READ_NVRAM_CONFIG ||
- ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel == AMR_CONFIG_WRITE_NVRAM_CONFIG)) {
- sgc = &(((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param);
- } else {
- sgc = &ac->ac_mailbox.mb_nsgelem;
- }
-
- ac->ac_mailbox.mb_nsgelem = nsegments;
- *sgc = nsegments;
- ac->ac_sg64_hi = 0;
- ac->ac_sg64_lo = ac->ac_sgbusaddr;
- ac->ac_mailbox.mb_physaddr = 0xffffffff;
- for (i = 0; i < nsegments; i++, sg++) {
- sg->sg_addr = segs[i].ds_addr;
- sg->sg_count = segs[i].ds_len;
- }
-}
-
-static void
-amr_setup_ccbmap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
-{
- struct amr_command *ac = (struct amr_command *)arg;
- struct amr_softc *sc = ac->ac_sc;
- struct amr_sgentry *sg;
- struct amr_passthrough *ap = (struct amr_passthrough *)ac->ac_data;
- struct amr_ext_passthrough *aep = (struct amr_ext_passthrough *)ac->ac_data;
- int i;
+ if (error)
+ printf("amr_setup_sg: error %d\n", error);
/* get base address of s/g table */
sg = ac->ac_sg.sg32;
+ sg64 = ac->ac_sg.sg64;
- /* decide whether we need to populate the s/g table */
- if( ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS ) {
- if (nsegments < 2) {
- aep->ap_no_sg_elements = 0;
- aep->ap_data_transfer_address = segs[0].ds_addr;
- } else {
- /* save s/g table information in passthrough */
- aep->ap_no_sg_elements = nsegments;
- aep->ap_data_transfer_address = ac->ac_sgbusaddr;
- /*
- * populate s/g table (overwrites previous call which mapped the
- * passthrough)
- */
- for (i = 0; i < nsegments; i++, sg++) {
- sg->sg_addr = segs[i].ds_addr;
- sg->sg_count = segs[i].ds_len;
- debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count);
- }
+ if (AC_IS_SG64(ac)) {
+ ac->ac_nsegments = nsegments;
+ ac->ac_mb_physaddr = 0xffffffff;
+ for (i = 0; i < nsegments; i++, sg64++) {
+ sg64->sg_addr = segs[i].ds_addr;
+ sg64->sg_count = segs[i].ds_len;
}
- debug(3, "slot %d %d segments at 0x%x\n", ac->ac_slot,
- aep->ap_no_sg_elements, aep->ap_data_transfer_address);
} else {
+ /* decide whether we need to populate the s/g table */
if (nsegments < 2) {
- ap->ap_no_sg_elements = 0;
- ap->ap_data_transfer_address = segs[0].ds_addr;
+ ac->ac_nsegments = 0;
+ ac->ac_mb_physaddr = segs[0].ds_addr;
} else {
- /* save s/g table information in passthrough */
- ap->ap_no_sg_elements = nsegments;
- ap->ap_data_transfer_address = ac->ac_sgbusaddr;
- /*
- * populate s/g table (overwrites previous call which mapped the
- * passthrough)
- */
+ ac->ac_nsegments = nsegments;
+ ac->ac_mb_physaddr = ac->ac_sgbusaddr;
for (i = 0; i < nsegments; i++, sg++) {
sg->sg_addr = segs[i].ds_addr;
sg->sg_count = segs[i].ds_len;
- debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count);
}
}
- debug(3, "slot %d %d segments at 0x%x\n", ac->ac_slot,
- ap->ap_no_sg_elements, ap->ap_data_transfer_address);
}
- if (ac->ac_flags & AMR_CMD_CCB_DATAIN)
- bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap,
- BUS_DMASYNC_PREREAD);
- if (ac->ac_flags & AMR_CMD_CCB_DATAOUT)
- bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap,
- BUS_DMASYNC_PREWRITE);
- if ((ac->ac_flags & (AMR_CMD_CCB_DATAIN | AMR_CMD_CCB_DATAOUT)) == 0)
- panic("no direction for ccb?\n");
+ flags = 0;
if (ac->ac_flags & AMR_CMD_DATAIN)
- bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap,BUS_DMASYNC_PREREAD);
+ flags |= BUS_DMASYNC_PREREAD;
if (ac->ac_flags & AMR_CMD_DATAOUT)
- bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap,BUS_DMASYNC_PREWRITE);
-
+ flags |= BUS_DMASYNC_PREWRITE;
+ bus_dmamap_sync(ac->ac_tag, ac->ac_datamap, flags);
ac->ac_flags |= AMR_CMD_MAPPED;
-
- if (sc->amr_submit_command(ac) == EBUSY) {
- amr_freeslot(ac);
- amr_requeue_ready(ac);
- }
}
static void
-amr_setup_ccb64map(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
+amr_setup_data(void *arg, bus_dma_segment_t *segs, int nsegs, int err)
{
- struct amr_command *ac = (struct amr_command *)arg;
- struct amr_softc *sc = ac->ac_sc;
- struct amr_sg64entry *sg;
- struct amr_passthrough *ap = (struct amr_passthrough *)ac->ac_data;
- struct amr_ext_passthrough *aep = (struct amr_ext_passthrough *)ac->ac_data;
- int i;
+ struct amr_command *ac = arg;
+ struct amr_softc *sc = ac->ac_sc;
+ int mb_channel;
- /* get base address of s/g table */
- sg = ac->ac_sg.sg64;
+ amr_setup_sg(arg, segs, nsegs, err);
- /* decide whether we need to populate the s/g table */
- if( ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS ) {
- /* save s/g table information in passthrough */
- aep->ap_no_sg_elements = nsegments;
- aep->ap_data_transfer_address = ac->ac_sgbusaddr;
- /*
- * populate s/g table (overwrites previous call which mapped the
- * passthrough)
- */
- for (i = 0; i < nsegments; i++, sg++) {
- sg->sg_addr = segs[i].ds_addr;
- sg->sg_count = segs[i].ds_len;
- debug(3, " %d: 0x%lx/%d", i, (u_long)sg->sg_addr, sg->sg_count);
- }
- debug(3, "slot %d %d segments at 0x%x\n", ac->ac_slot,
- aep->ap_no_sg_elements, aep->ap_data_transfer_address);
- } else {
- /* save s/g table information in passthrough */
- ap->ap_no_sg_elements = nsegments;
- ap->ap_data_transfer_address = ac->ac_sgbusaddr;
- /*
- * populate s/g table (overwrites previous call which mapped the
- * passthrough)
- */
- for (i = 0; i < nsegments; i++, sg++) {
- sg->sg_addr = segs[i].ds_addr;
- sg->sg_count = segs[i].ds_len;
- debug(3, " %d: 0x%lx/%d", i, (u_long)sg->sg_addr, sg->sg_count);
- }
- debug(3, "slot %d %d segments at 0x%x\n", ac->ac_slot,
- ap->ap_no_sg_elements, ap->ap_data_transfer_address);
+ /* for AMR_CMD_CONFIG Read/Write the s/g count goes elsewhere */
+ mb_channel = ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel;
+ if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG &&
+ ((mb_channel == AMR_CONFIG_READ_NVRAM_CONFIG) ||
+ (mb_channel == AMR_CONFIG_WRITE_NVRAM_CONFIG)))
+ ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param = ac->ac_nsegments;
+
+ ac->ac_mailbox.mb_nsgelem = ac->ac_nsegments;
+ ac->ac_mailbox.mb_physaddr = ac->ac_mb_physaddr;
+ if (AC_IS_SG64(ac)) {
+ ac->ac_sg64_hi = 0;
+ ac->ac_sg64_lo = ac->ac_sgbusaddr;
}
- if (ac->ac_flags & AMR_CMD_CCB_DATAIN)
- bus_dmamap_sync(sc->amr_buffer64_dmat, ac->ac_ccb_dma64map,
- BUS_DMASYNC_PREREAD);
- if (ac->ac_flags & AMR_CMD_CCB_DATAOUT)
- bus_dmamap_sync(sc->amr_buffer64_dmat, ac->ac_ccb_dma64map,
- BUS_DMASYNC_PREWRITE);
- if ((ac->ac_flags & (AMR_CMD_CCB_DATAIN | AMR_CMD_CCB_DATAOUT)) == 0)
- panic("no direction for ccb?\n");
-
- if (ac->ac_flags & AMR_CMD_DATAIN)
- bus_dmamap_sync(sc->amr_buffer64_dmat, ac->ac_dma64map,
- BUS_DMASYNC_PREREAD);
- if (ac->ac_flags & AMR_CMD_DATAOUT)
- bus_dmamap_sync(sc->amr_buffer64_dmat, ac->ac_dma64map,
- BUS_DMASYNC_PREWRITE);
-
- ac->ac_flags |= AMR_CMD_MAPPED;
if (sc->amr_submit_command(ac) == EBUSY) {
amr_freeslot(ac);
amr_requeue_ready(ac);
}
}
-
+
static void
-amr_setup_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nsegments,
- int error)
+amr_setup_ccb(void *arg, bus_dma_segment_t *segs, int nsegs, int err)
{
- struct amr_command *ac = (struct amr_command *)arg;
- struct amr_softc *sc = ac->ac_sc;
-
- amr_setup_dmamap(arg, segs, nsegments, error);
-
- if (bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_ccb_dmamap,
- ac->ac_ccb_data, ac->ac_ccb_length, amr_setup_ccbmap, ac,
- 0) == EINPROGRESS) {
- sc->amr_state |= AMR_STATE_QUEUE_FRZN;
+ struct amr_command *ac = arg;
+ struct amr_softc *sc = ac->ac_sc;
+ struct amr_passthrough *ap = &ac->ac_ccb->ccb_pthru;
+ struct amr_ext_passthrough *aep = &ac->ac_ccb->ccb_epthru;
+
+ /* Set up the mailbox portion of the command to point at the ccb */
+ ac->ac_mailbox.mb_nsgelem = 0;
+ ac->ac_mailbox.mb_physaddr = ac->ac_ccb_busaddr;
+
+ amr_setup_sg(arg, segs, nsegs, err);
+
+ switch (ac->ac_mailbox.mb_command) {
+ case AMR_CMD_EXTPASS:
+ aep->ap_no_sg_elements = ac->ac_nsegments;
+ aep->ap_data_transfer_address = ac->ac_mb_physaddr;
+ break;
+ case AMR_CMD_PASS:
+ ap->ap_no_sg_elements = ac->ac_nsegments;
+ ap->ap_data_transfer_address = ac->ac_mb_physaddr;
+ break;
+ default:
+ panic("Unknown ccb command");
}
-}
-
-static void
-amr_setup_dma64map_cb(void *arg, bus_dma_segment_t *segs, int nsegments,
- int error)
-{
- struct amr_command *ac = (struct amr_command *)arg;
- struct amr_softc *sc = ac->ac_sc;
-
- amr_setup_dma64map(arg, segs, nsegments, error);
- if (bus_dmamap_load(sc->amr_buffer64_dmat, ac->ac_ccb_dma64map,
- ac->ac_ccb_data, ac->ac_ccb_length, amr_setup_ccb64map, ac,
- 0) == EINPROGRESS) {
- sc->amr_state |= AMR_STATE_QUEUE_FRZN;
+ if (sc->amr_submit_command(ac) == EBUSY) {
+ amr_freeslot(ac);
+ amr_requeue_ready(ac);
}
}
static int
amr_mapcmd(struct amr_command *ac)
{
- bus_dma_tag_t tag;
- bus_dmamap_t datamap;
bus_dmamap_callback_t *cb;
struct amr_softc *sc = ac->ac_sc;
debug_called(3);
if (AC_IS_SG64(ac)) {
- tag = sc->amr_buffer64_dmat;
- datamap = ac->ac_dma64map;
- cb = amr_setup_dma64map_cb;
+ ac->ac_tag = sc->amr_buffer64_dmat;
+ ac->ac_datamap = ac->ac_dma64map;
} else {
- tag = sc->amr_buffer_dmat;
- datamap = ac->ac_dmamap;
- cb = amr_setup_dmamap_cb;
+ ac->ac_tag = sc->amr_buffer_dmat;
+ ac->ac_datamap = ac->ac_dmamap;
}
+ if (ac->ac_flags & AMR_CMD_CCB)
+ cb = amr_setup_ccb;
+ else
+ cb = amr_setup_data;
+
/* if the command involves data at all, and hasn't been mapped */
if ((ac->ac_flags & AMR_CMD_MAPPED) == 0 && (ac->ac_data != NULL)) {
- if (ac->ac_ccb_data == NULL)
- cb = amr_setup_data_dmamap;
/* map the data buffers into bus space and build the s/g list */
- if (bus_dmamap_load(tag, datamap, ac->ac_data, ac->ac_length,
- cb, ac, 0) == EINPROGRESS) {
+ if (bus_dmamap_load(ac->ac_tag, ac->ac_datamap, ac->ac_data,
+ ac->ac_length, cb, ac, 0) == EINPROGRESS) {
sc->amr_state |= AMR_STATE_QUEUE_FRZN;
}
} else {
@@ -1872,7 +1706,6 @@ amr_mapcmd(struct amr_command *ac)
static void
amr_unmapcmd(struct amr_command *ac)
{
- struct amr_softc *sc = ac->ac_sc;
int flag;
debug_called(3);
@@ -1888,63 +1721,14 @@ amr_unmapcmd(struct amr_command *ac)
if (ac->ac_flags & AMR_CMD_DATAOUT)
flag |= BUS_DMASYNC_POSTWRITE;
- if (AC_IS_SG64(ac)) {
- bus_dmamap_sync(sc->amr_buffer64_dmat, ac->ac_dma64map, flag);
- bus_dmamap_unload(sc->amr_buffer64_dmat, ac->ac_dma64map);
- } else {
- bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, flag);
- bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap);
- }
+ bus_dmamap_sync(ac->ac_tag, ac->ac_datamap, flag);
+ bus_dmamap_unload(ac->ac_tag, ac->ac_datamap);
}
- if (ac->ac_ccb_data != NULL) {
-
- flag = 0;
- if (ac->ac_flags & AMR_CMD_CCB_DATAIN)
- flag |= BUS_DMASYNC_POSTREAD;
- if (ac->ac_flags & AMR_CMD_CCB_DATAOUT)
- flag |= BUS_DMASYNC_POSTWRITE;
-
- if (AC_IS_SG64(ac)) {
- bus_dmamap_sync(sc->amr_buffer64_dmat,ac->ac_ccb_dma64map,flag);
- bus_dmamap_unload(sc->amr_buffer64_dmat, ac->ac_ccb_dma64map);
- } else {
- bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, flag);
- bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_ccb_dmamap);
- }
- }
ac->ac_flags &= ~AMR_CMD_MAPPED;
}
}
-static void
-amr_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegs, int err)
-{
- struct amr_command *ac = arg;
- struct amr_softc *sc = ac->ac_sc;
- int flags;
-
- flags = 0;
- if (ac->ac_flags & AMR_CMD_DATAIN)
- flags |= BUS_DMASYNC_PREREAD;
- if (ac->ac_flags & AMR_CMD_DATAOUT)
- flags |= BUS_DMASYNC_PREWRITE;
-
- if (AC_IS_SG64(ac)) {
- amr_setup_dma64map(arg, segs, nsegs, err);
- bus_dmamap_sync(sc->amr_buffer64_dmat,ac->ac_dma64map, flags);
- } else {
- amr_setup_dmamap(arg, segs, nsegs, err);
- bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap, flags);
- }
- ac->ac_flags |= AMR_CMD_MAPPED;
-
- if (sc->amr_submit_command(ac) == EBUSY) {
- amr_freeslot(ac);
- amr_requeue_ready(ac);
- }
-}
-
/********************************************************************************
* Take a command and give it to the controller, returns 0 if successful, or
* EBUSY if the command should be retried later.
@@ -2124,8 +1908,9 @@ amr_alloccmd(struct amr_softc *sc)
ac->ac_flags = 0;
ac->ac_bio = NULL;
ac->ac_data = NULL;
- ac->ac_ccb_data = NULL;
ac->ac_complete = NULL;
+ ac->ac_tag = NULL;
+ ac->ac_datamap = NULL;
return(ac);
}
@@ -2177,12 +1962,15 @@ amr_alloccmd_cluster(struct amr_softc *sc)
ac->ac_sg.sg32 = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
}
- if (bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_dmamap) ||
- bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_ccb_dmamap) ||
- (AMR_IS_SG64(sc) &&
- (bus_dmamap_create(sc->amr_buffer64_dmat, 0,&ac->ac_dma64map) ||
- bus_dmamap_create(sc->amr_buffer64_dmat, 0, &ac->ac_ccb_dma64map))))
- break;
+ ac->ac_ccb = sc->amr_ccb + ac->ac_slot;
+ ac->ac_ccb_busaddr = sc->amr_ccb_busaddr +
+ (ac->ac_slot * sizeof(union amr_ccb));
+
+ if (bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_dmamap))
+ break;
+ if (AMR_IS_SG64(sc) &&
+ (bus_dmamap_create(sc->amr_buffer64_dmat, 0,&ac->ac_dma64map)))
+ break;
amr_releasecmd(ac);
if (++nextslot > sc->amr_maxio)
break;
@@ -2202,10 +1990,8 @@ amr_freecmd_cluster(struct amr_command_cluster *acc)
for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++) {
bus_dmamap_destroy(sc->amr_buffer_dmat, acc->acc_command[i].ac_dmamap);
- bus_dmamap_destroy(sc->amr_buffer_dmat, acc->acc_command[i].ac_ccb_dmamap);
if (AMR_IS_SG64(sc))
bus_dmamap_destroy(sc->amr_buffer64_dmat, acc->acc_command[i].ac_dma64map);
- bus_dmamap_destroy(sc->amr_buffer64_dmat, acc->acc_command[i].ac_ccb_dma64map);
}
free(acc, M_AMR);
}
diff --git a/sys/dev/amr/amr_cam.c b/sys/dev/amr/amr_cam.c
index 9ad465e..65913d1 100644
--- a/sys/dev/amr/amr_cam.c
+++ b/sys/dev/amr/amr_cam.c
@@ -222,16 +222,16 @@ amr_cam_action(struct cam_sim *sim, union ccb *ccb)
/* check the CDB length */
if (csio->cdb_len > AMR_MAX_EXTCDB_LEN)
- ccbh->status = CAM_REQ_CMP_ERR;
+ ccbh->status = CAM_REQ_INVALID;
if ((csio->cdb_len > AMR_MAX_CDB_LEN) &&
(sc->support_ext_cdb == 0))
- ccbh->status = CAM_REQ_CMP_ERR;
+ ccbh->status = CAM_REQ_INVALID;
/* check that the CDB pointer is not to a physical address */
if ((ccbh->flags & CAM_CDB_POINTER) &&
(ccbh->flags & CAM_CDB_PHYS))
- ccbh->status = CAM_REQ_CMP_ERR;
+ ccbh->status = CAM_REQ_INVALID;
/*
* if there is data transfer, it must be to/from a virtual
* address
@@ -239,10 +239,10 @@ amr_cam_action(struct cam_sim *sim, union ccb *ccb)
if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
if (ccbh->flags & CAM_DATA_PHYS)
/* we can't map it */
- ccbh->status = CAM_REQ_CMP_ERR;
+ ccbh->status = CAM_REQ_INVALID;
if (ccbh->flags & CAM_SCATTER_VALID)
/* we want to do the s/g setup */
- ccbh->status = CAM_REQ_CMP_ERR;
+ ccbh->status = CAM_REQ_INVALID;
}
/*
@@ -252,7 +252,7 @@ amr_cam_action(struct cam_sim *sim, union ccb *ccb)
* devices appear echoed.
*/
if (csio->ccb_h.target_lun != 0)
- ccbh->status = CAM_REQ_CMP_ERR;
+ ccbh->status = CAM_DEV_NOT_THERE;
/* if we're happy with the request, queue it for attention */
if (ccbh->status == CAM_REQ_INPROG) {
@@ -405,13 +405,15 @@ amr_cam_command(struct amr_softc *sc, struct amr_command **acp)
* Build a passthrough command.
*/
+ /* construct command */
+ if ((ac = amr_alloccmd(sc)) == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
/* construct passthrough */
if (sc->support_ext_cdb ) {
- if ((aep = malloc(sizeof(*aep), M_AMRCAM, M_NOWAIT | M_ZERO))
- == NULL) {
- error = ENOMEM;
- goto out;
- }
+ aep = &ac->ac_ccb->ccb_epthru;
aep->ap_timeout = 2;
aep->ap_ars = 1;
aep->ap_request_sense_length = 14;
@@ -437,11 +439,7 @@ amr_cam_command(struct amr_softc *sc, struct amr_command **acp)
aep->ap_scsi_id, aep->ap_logical_drive_no);
} else {
- if ((ap = malloc(sizeof(*ap), M_AMRCAM, M_NOWAIT | M_ZERO))
- == NULL) {
- error = ENOMEM;
- goto out;
- }
+ ap = &ac->ac_ccb->ccb_pthru;
ap->ap_timeout = 0;
ap->ap_ars = 1;
ap->ap_request_sense_length = 14;
@@ -467,30 +465,20 @@ amr_cam_command(struct amr_softc *sc, struct amr_command **acp)
ap->ap_scsi_id, ap->ap_logical_drive_no);
}
- /* construct command */
- if ((ac = amr_alloccmd(sc)) == NULL) {
- error = ENOMEM;
- goto out;
- }
-
- ac->ac_flags |= AMR_CMD_DATAOUT | AMR_CMD_DATAIN;
+ ac->ac_flags |= AMR_CMD_CCB;
- ac->ac_ccb_data = csio->data_ptr;
- ac->ac_ccb_length = csio->dxfer_len;
+ ac->ac_data = csio->data_ptr;
+ ac->ac_length = csio->dxfer_len;
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
- ac->ac_flags |= AMR_CMD_CCB_DATAIN;
+ ac->ac_flags |= AMR_CMD_DATAIN;
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
- ac->ac_flags |= AMR_CMD_CCB_DATAOUT;
+ ac->ac_flags |= AMR_CMD_DATAOUT;
ac->ac_private = csio;
ac->ac_complete = amr_cam_complete;
if ( sc->support_ext_cdb ) {
- ac->ac_data = aep;
- ac->ac_length = sizeof(*aep);
ac->ac_mailbox.mb_command = AMR_CMD_EXTPASS;
} else {
- ac->ac_data = ap;
- ac->ac_length = sizeof(*ap);
ac->ac_mailbox.mb_command = AMR_CMD_PASS;
}
@@ -498,10 +486,6 @@ out:
if (error != 0) {
if (ac != NULL)
amr_releasecmd(ac);
- if (ap != NULL)
- free(ap, M_AMRCAM);
- if (aep != NULL)
- free(aep, M_AMRCAM);
if (csio != NULL)
/* put it back and try again later */
amr_requeue_ccb(sc, (union ccb *)csio);
@@ -532,19 +516,20 @@ amr_cam_complete(struct amr_command *ac)
struct scsi_inquiry_data *inq;
int scsi_status, cdb0;
- ap = (struct amr_passthrough *)ac->ac_data;
- aep = (struct amr_ext_passthrough *)ac->ac_data;
+ ap = &ac->ac_ccb->ccb_pthru;
+ aep = &ac->ac_ccb->ccb_epthru;
csio = (struct ccb_scsiio *)ac->ac_private;
inq = (struct scsi_inquiry_data *)csio->data_ptr;
- if (ac->ac_length == sizeof(*ap))
- scsi_status = ap->ap_scsi_status;
- else
+ if (ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS)
scsi_status = aep->ap_scsi_status;
+ else
+ scsi_status = ap->ap_scsi_status;
debug(1, "status 0x%x AP scsi_status 0x%x", ac->ac_status,
scsi_status);
- if (ac->ac_status != AMR_STATUS_SUCCESS) {
+ /* Make sure the status is sane */
+ if ((ac->ac_status != AMR_STATUS_SUCCESS) && (scsi_status == 0)) {
csio->ccb_h.status = CAM_REQ_CMP_ERR;
goto out;
}
@@ -561,10 +546,10 @@ amr_cam_complete(struct amr_command *ac)
/* handle passthrough SCSI status */
switch(scsi_status) {
case 0: /* completed OK */
- if (ac->ac_length == sizeof(*ap))
- cdb0 = ap->ap_cdb[0];
- else
+ if (ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS)
cdb0 = aep->ap_cdb[0];
+ else
+ cdb0 = ap->ap_cdb[0];
if ((cdb0 == INQUIRY) && (SID_TYPE(inq) == T_DIRECT))
inq->device = (inq->device & 0xe0) | T_NODEVICE;
csio->ccb_h.status = CAM_REQ_CMP;
@@ -573,11 +558,11 @@ amr_cam_complete(struct amr_command *ac)
case 0x02:
csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
csio->scsi_status = SCSI_STATUS_CHECK_COND;
- if (ac->ac_length == sizeof(*ap))
- bcopy(ap->ap_request_sense_area, &csio->sense_data,
+ if (ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS)
+ bcopy(aep->ap_request_sense_area, &csio->sense_data,
AMR_MAX_REQ_SENSE_LEN);
else
- bcopy(aep->ap_request_sense_area, &csio->sense_data,
+ bcopy(ap->ap_request_sense_area, &csio->sense_data,
AMR_MAX_REQ_SENSE_LEN);
csio->sense_len = AMR_MAX_REQ_SENSE_LEN;
csio->ccb_h.status |= CAM_AUTOSNS_VALID;
@@ -590,20 +575,20 @@ amr_cam_complete(struct amr_command *ac)
case 0xf0:
case 0xf4:
default:
- csio->ccb_h.status = CAM_REQ_CMP_ERR;
+ /*
+ * Non-zero LUNs are already filtered, so there's no need
+ * to return CAM_DEV_NOT_THERE.
+ */
+ csio->ccb_h.status = CAM_SEL_TIMEOUT;
break;
}
out:
- if (ac->ac_length == sizeof(*ap))
- free(ap, M_AMRCAM);
- else
- free(aep, M_AMRCAM);
if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
debug(2, "%*D\n", imin(csio->dxfer_len, 16), csio->data_ptr,
" ");
- mtx_unlock(&ac->ac_sc->amr_list_lock);
+ mtx_lock(&ac->ac_sc->amr_list_lock);
xpt_done((union ccb *)csio);
amr_releasecmd(ac);
mtx_unlock(&ac->ac_sc->amr_list_lock);
diff --git a/sys/dev/amr/amr_pci.c b/sys/dev/amr/amr_pci.c
index dec96c0..d72a129 100644
--- a/sys/dev/amr/amr_pci.c
+++ b/sys/dev/amr/amr_pci.c
@@ -86,10 +86,10 @@ static int amr_pci_suspend(device_t dev);
static int amr_pci_resume(device_t dev);
static void amr_pci_intr(void *arg);
static void amr_pci_free(struct amr_softc *sc);
-static void amr_sglist_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
+static void amr_sglist_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
static int amr_sglist_map(struct amr_softc *sc);
-static void amr_setup_mbox_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
static int amr_setup_mbox(struct amr_softc *sc);
+static int amr_ccb_map(struct amr_softc *sc);
static u_int amr_force_sg32 = 0;
TUNABLE_INT("hw.amr.force_sg32", &amr_force_sg32);
@@ -303,7 +303,7 @@ amr_pci_attach(device_t dev)
NULL, NULL, /* filter, filterarg */
MAXBSIZE, AMR_NSEG, /* maxsize, nsegments */
MAXBSIZE, /* maxsegsize */
- BUS_DMA_ALLOCNOW, /* flags */
+ 0, /* flags */
busdma_lock_mutex, /* lockfunc */
&sc->amr_list_lock, /* lockarg */
&sc->amr_buffer_dmat)) {
@@ -318,7 +318,7 @@ amr_pci_attach(device_t dev)
NULL, NULL, /* filter, filterarg */
MAXBSIZE, AMR_NSEG, /* maxsize, nsegments */
MAXBSIZE, /* maxsegsize */
- BUS_DMA_ALLOCNOW, /* flags */
+ 0, /* flags */
busdma_lock_mutex, /* lockfunc */
&sc->amr_list_lock, /* lockarg */
&sc->amr_buffer64_dmat)) {
@@ -343,9 +343,13 @@ amr_pci_attach(device_t dev)
*/
if (amr_sglist_map(sc))
goto out;
-
debug(2, "s/g list mapped");
+ if (amr_ccb_map(sc))
+ goto out;
+ debug(2, "ccb mapped");
+
+
/*
* Do bus-independant initialisation, bring controller online.
*/
@@ -469,7 +473,7 @@ amr_pci_intr(void *arg)
{
struct amr_softc *sc = (struct amr_softc *)arg;
- debug_called(2);
+ debug_called(3);
/* collect finished commands, queue anything waiting */
amr_done(sc);
@@ -495,6 +499,12 @@ amr_pci_free(struct amr_softc *sc)
if (sc->amr_buffer64_dmat)
bus_dma_tag_destroy(sc->amr_buffer64_dmat);
+ /* free and destroy DMA memory and tag for passthrough pool */
+ if (sc->amr_ccb)
+ bus_dmamem_free(sc->amr_ccb_dmat, sc->amr_ccb, sc->amr_ccb_dmamap);
+ if (sc->amr_ccb_dmat)
+ bus_dma_tag_destroy(sc->amr_ccb_dmat);
+
/* free and destroy DMA memory and tag for s/g lists */
if (sc->amr_sgtable)
bus_dmamem_free(sc->amr_sg_dmat, sc->amr_sgtable, sc->amr_sg_dmamap);
@@ -530,14 +540,14 @@ amr_pci_free(struct amr_softc *sc)
* Allocate and map the scatter/gather table in bus space.
*/
static void
-amr_sglist_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+amr_sglist_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
- struct amr_softc *sc = (struct amr_softc *)arg;
+ uint32_t *addr;
debug_called(1);
- /* save base of s/g table's address in bus space */
- sc->amr_sgbusaddr = segs->ds_addr;
+ addr = arg;
+ *addr = segs[0].ds_addr;
}
static int
@@ -562,7 +572,7 @@ amr_sglist_map(struct amr_softc *sc)
segsize = sizeof(struct amr_sgentry) * AMR_NSEG * AMR_MAXCMD;
error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
- 1, 0, /* alignment,boundary */
+ 512, 0, /* alignment,boundary */
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
@@ -597,7 +607,7 @@ retry:
device_printf(sc->amr_dev, "can't allocate s/g table\n");
return(ENOMEM);
}
- bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, p, segsize, amr_sglist_map_helper, sc, 0);
+ bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, p, segsize, amr_sglist_helper, &sc->amr_sgbusaddr, 0);
if (sc->amr_sgbusaddr < 0x2000) {
debug(1, "s/g table too low (0x%x), reallocating\n", sc->amr_sgbusaddr);
goto retry;
@@ -613,25 +623,14 @@ retry:
/********************************************************************************
* Allocate and set up mailbox areas for the controller (sc)
*
- * The basic mailbox structure should be 16-byte aligned. This means that the
- * mailbox64 structure has 4 bytes hanging off the bottom.
+ * The basic mailbox structure should be 16-byte aligned.
*/
-static void
-amr_setup_mbox_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- struct amr_softc *sc = (struct amr_softc *)arg;
-
- debug_called(1);
-
- /* save phsyical base of the basic mailbox structure */
- sc->amr_mailboxphys = segs->ds_addr + offsetof(struct amr_mailbox64, mb);
-}
-
static int
amr_setup_mbox(struct amr_softc *sc)
{
int error;
void *p;
+ uint32_t baddr;
debug_called(1);
@@ -666,13 +665,55 @@ amr_setup_mbox(struct amr_softc *sc)
return(ENOMEM);
}
bus_dmamap_load(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap, p,
- sizeof(struct amr_mailbox64), amr_setup_mbox_helper, sc, 0);
+ sizeof(struct amr_mailbox64), amr_sglist_helper, &baddr, 0);
/*
* Conventional mailbox is inside the mailbox64 region.
*/
+ /* save physical base of the basic mailbox structure */
+ sc->amr_mailboxphys = baddr + offsetof(struct amr_mailbox64, mb);
bzero(p, sizeof(struct amr_mailbox64));
sc->amr_mailbox64 = (struct amr_mailbox64 *)p;
sc->amr_mailbox = &sc->amr_mailbox64->mb;
return(0);
}
+
+static int
+amr_ccb_map(struct amr_softc *sc)
+{
+ int ccbsize, error;
+
+ /*
+ * Passthrough and Extended passthrough structures will share the same
+ * memory.
+ */
+ ccbsize = sizeof(union amr_ccb) * AMR_MAXCMD;
+ error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
+ 128, 0, /* alignment,boundary */
+ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ ccbsize, /* maxsize */
+ 1, /* nsegments */
+ ccbsize, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->amr_ccb_dmat);
+ if (error != 0) {
+ device_printf(sc->amr_dev, "can't allocate ccb tag\n");
+ return (ENOMEM);
+ }
+
+ error = bus_dmamem_alloc(sc->amr_ccb_dmat, (void **)&sc->amr_ccb,
+ BUS_DMA_NOWAIT, &sc->amr_ccb_dmamap);
+ if (error) {
+ device_printf(sc->amr_dev, "can't allocate ccb memory\n");
+ return (ENOMEM);
+ }
+ bus_dmamap_load(sc->amr_ccb_dmat, sc->amr_ccb_dmamap, sc->amr_ccb,
+ ccbsize, amr_sglist_helper, &sc->amr_ccb_busaddr, 0);
+ bzero(sc->amr_ccb, ccbsize);
+
+ return (0);
+}
+
diff --git a/sys/dev/amr/amrvar.h b/sys/dev/amr/amrvar.h
index 1fd78fd..0a39b1c 100644
--- a/sys/dev/amr/amrvar.h
+++ b/sys/dev/amr/amrvar.h
@@ -100,6 +100,12 @@ struct amr_logdrive
#define AMR_CMD_CLUSTERSIZE (16 * 1024)
+union amr_ccb {
+ struct amr_passthrough ccb_pthru;
+ struct amr_ext_passthrough ccb_epthru;
+ uint8_t bytes[128];
+};
+
/*
* Per-command control structure.
*/
@@ -121,8 +127,7 @@ struct amr_command
int ac_flags;
#define AMR_CMD_DATAIN (1<<0)
#define AMR_CMD_DATAOUT (1<<1)
-#define AMR_CMD_CCB_DATAIN (1<<2)
-#define AMR_CMD_CCB_DATAOUT (1<<3)
+#define AMR_CMD_CCB (1<<2)
#define AMR_CMD_PRIORITY (1<<4)
#define AMR_CMD_MAPPED (1<<5)
#define AMR_CMD_SLEEP (1<<6)
@@ -139,11 +144,13 @@ struct amr_command
bus_dmamap_t ac_dmamap;
bus_dmamap_t ac_dma64map;
- void *ac_ccb_data;
- size_t ac_ccb_length;
- bus_dmamap_t ac_ccb_dmamap;
- bus_dmamap_t ac_ccb_dma64map;
+ bus_dma_tag_t ac_tag;
+ bus_dmamap_t ac_datamap;
+ int ac_nsegments;
+ uint32_t ac_mb_physaddr;
+ union amr_ccb *ac_ccb;
+ uint32_t ac_ccb_busaddr;
};
struct amr_command_cluster
@@ -185,6 +192,11 @@ struct amr_softc
bus_dma_tag_t amr_sg_dmat; /* s/g buffer DMA tag */
bus_dmamap_t amr_sg_dmamap; /* map for s/g buffers */
+ union amr_ccb *amr_ccb;
+ uint32_t amr_ccb_busaddr;
+ bus_dma_tag_t amr_ccb_dmat;
+ bus_dmamap_t amr_ccb_dmamap;
+
/* controller limits and features */
int amr_nextslot; /* Next slot to use for newly allocated commands */
int amr_maxio; /* maximum number of I/O transactions */
OpenPOWER on IntegriCloud