Big update to the iir driver:

- Don't use a common buffer in the softc to store per-command data.  Reserve
  a buffer in the command itself.
- Don't allocate DMA memory for the kernel command structures when all you
  really need is DMA memory for the scratch buffer embedded in them.  Instead
  allocate a slab for the scratch buffers and divide it up as needed.
- Call bus_dmamap_unload() at the completion of commands.
- Preserve and clear the CAM CCB status flags at completion.
- Reorder some low-level command operations to try to close races.
- Limit the simq to 32 commands for now.  There are some serious problems
  with the driver under load that are not well understood, so keeping the
  simq lower helps avoid this.  It has been tested at a higher value, but
  this is a safe value that doesn't show much performance degredation.

These changes allow the driver to work reliably with >4GB of memory on i386
and amd64, and also work around deadlocks seen under very high load in
certain situations.  The work-around is far from ideal, but without and
documentation it is hard to know what the right fix is.

MFC candidate
This commit is contained in:
Scott Long 2006-03-01 07:24:39 +00:00
parent 80452384e6
commit 3469383f4f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=156139
3 changed files with 169 additions and 170 deletions

View File

@ -73,6 +73,8 @@ __FBSDID("$FreeBSD$");
#include <dev/iir/iir.h>
MALLOC_DEFINE(M_GDTBUF, "iirbuf", "iir driver buffer");
struct gdt_softc *gdt_wait_gdt;
int gdt_wait_index;
@ -166,8 +168,6 @@ static int gdt_wait(struct gdt_softc *gdt, struct gdt_ccb *ccb,
int timeout);
static struct gdt_ccb *gdt_get_ccb(struct gdt_softc *gdt);
static u_int32_t gdt_ccb_vtop(struct gdt_softc *gdt,
struct gdt_ccb *gccb);
static int gdt_sync_event(struct gdt_softc *gdt, int service,
u_int8_t index, struct gdt_ccb *gccb);
@ -228,20 +228,20 @@ iir_init(struct gdt_softc *gdt)
/*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL,
/*filterarg*/NULL,
GDT_MAXCMDS * sizeof(struct gdt_ccb), /* maxsize */
GDT_MAXCMDS * GDT_SCRATCH_SZ, /* maxsize */
/*nsegments*/1,
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
/*flags*/0, /*lockfunc*/busdma_lock_mutex,
/*lockarg*/&Giant, &gdt->sc_gccb_dmat) != 0) {
printf("iir%d: bus_dma_tag_create(...,gdt->sc_gccb_dmat) failed\n",
/*lockarg*/&Giant, &gdt->sc_gcscratch_dmat) != 0) {
printf("iir%d: bus_dma_tag_create(...,gdt->sc_gcscratch_dmat) failed\n",
gdt->sc_hanum);
return (1);
}
gdt->sc_init_level++;
/* Allocation for our ccbs */
if (bus_dmamem_alloc(gdt->sc_gccb_dmat, (void **)&gdt->sc_gccbs,
BUS_DMA_NOWAIT, &gdt->sc_gccb_dmamap) != 0) {
/* Allocation for our ccb scratch area */
if (bus_dmamem_alloc(gdt->sc_gcscratch_dmat, (void **)&gdt->sc_gcscratch,
BUS_DMA_NOWAIT, &gdt->sc_gcscratch_dmamap) != 0) {
printf("iir%d: bus_dmamem_alloc(...,&gdt->sc_gccbs,...) failed\n",
gdt->sc_hanum);
return (1);
@ -249,24 +249,33 @@ iir_init(struct gdt_softc *gdt)
gdt->sc_init_level++;
/* And permanently map them */
bus_dmamap_load(gdt->sc_gccb_dmat, gdt->sc_gccb_dmamap,
gdt->sc_gccbs, GDT_MAXCMDS * sizeof(struct gdt_ccb),
gdtmapmem, &gdt->sc_gccb_busbase, /*flags*/0);
bus_dmamap_load(gdt->sc_gcscratch_dmat, gdt->sc_gcscratch_dmamap,
gdt->sc_gcscratch, GDT_MAXCMDS * GDT_SCRATCH_SZ,
gdtmapmem, &gdt->sc_gcscratch_busbase, /*flags*/0);
gdt->sc_init_level++;
/* Clear them out. */
bzero(gdt->sc_gccbs, GDT_MAXCMDS * sizeof(struct gdt_ccb));
bzero(gdt->sc_gcscratch, GDT_MAXCMDS * GDT_SCRATCH_SZ);
/* Initialize the ccbs */
gdt->sc_gccbs = malloc(sizeof(struct gdt_ccb) * GDT_MAXCMDS, M_GDTBUF,
M_NOWAIT | M_ZERO);
if (gdt->sc_gccbs == NULL) {
printf("iir%d: no memory for gccbs.\n", gdt->sc_hanum);
return (1);
}
for (i = GDT_MAXCMDS-1; i >= 0; i--) {
gdt->sc_gccbs[i].gc_cmd_index = i + 2;
gdt->sc_gccbs[i].gc_flags = GDT_GCF_UNUSED;
gdt->sc_gccbs[i].gc_map_flag = FALSE;
gccb = &gdt->sc_gccbs[i];
gccb->gc_cmd_index = i + 2;
gccb->gc_flags = GDT_GCF_UNUSED;
gccb->gc_map_flag = FALSE;
if (bus_dmamap_create(gdt->sc_buffer_dmat, /*flags*/0,
&gdt->sc_gccbs[i].gc_dmamap) != 0)
&gccb->gc_dmamap) != 0)
return(1);
gdt->sc_gccbs[i].gc_map_flag = TRUE;
SLIST_INSERT_HEAD(&gdt->sc_free_gccb, &gdt->sc_gccbs[i], sle);
gccb->gc_map_flag = TRUE;
gccb->gc_scratch = &gdt->sc_gcscratch[GDT_SCRATCH_SZ * i];
gccb->gc_scratch_busbase = gdt->sc_gcscratch_busbase + GDT_SCRATCH_SZ * i;
SLIST_INSERT_HEAD(&gdt->sc_free_gccb, gccb, sle);
}
gdt->sc_init_level++;
@ -280,6 +289,7 @@ iir_init(struct gdt_softc *gdt)
gdt->sc_hanum);
return (1);
}
bzero(gccb->gc_cmd, GDT_CMD_SZ);
if (!gdt_internal_cmd(gdt, gccb, GDT_SCREENSERVICE, GDT_INIT,
0, 0, 0)) {
@ -456,11 +466,12 @@ iir_free(struct gdt_softc *gdt)
if (gdt->sc_gccbs[i].gc_map_flag)
bus_dmamap_destroy(gdt->sc_buffer_dmat,
gdt->sc_gccbs[i].gc_dmamap);
bus_dmamap_unload(gdt->sc_gccb_dmat, gdt->sc_gccb_dmamap);
bus_dmamap_unload(gdt->sc_gcscratch_dmat, gdt->sc_gcscratch_dmamap);
free(gdt->sc_gccbs, M_GDTBUF);
case 4:
bus_dmamem_free(gdt->sc_gccb_dmat, gdt->sc_gccbs, gdt->sc_gccb_dmamap);
bus_dmamem_free(gdt->sc_gcscratch_dmat, gdt->sc_gcscratch, gdt->sc_gcscratch_dmamap);
case 3:
bus_dma_tag_destroy(gdt->sc_gccb_dmat);
bus_dma_tag_destroy(gdt->sc_gcscratch_dmat);
case 2:
bus_dma_tag_destroy(gdt->sc_buffer_dmat);
case 1:
@ -481,8 +492,9 @@ iir_attach(struct gdt_softc *gdt)
/*
* Create the device queue for our SIM.
* XXX Throttle this down since the card has problems under load.
*/
devq = cam_simq_alloc(GDT_MAXCMDS);
devq = cam_simq_alloc(32);
if (devq == NULL)
return;
@ -491,7 +503,7 @@ iir_attach(struct gdt_softc *gdt)
* Construct our SIM entry
*/
gdt->sims[i] = cam_sim_alloc(iir_action, iir_poll, "iir",
gdt, gdt->sc_hanum, /*untagged*/2,
gdt, gdt->sc_hanum, /*untagged*/1,
/*tagged*/GDT_MAXCMDS, devq);
if (xpt_bus_register(gdt->sims[i], i) != CAM_SUCCESS) {
cam_sim_free(gdt->sims[i], /*free_devq*/i == 0);
@ -573,49 +585,48 @@ gdt_internal_cmd(struct gdt_softc *gdt, struct gdt_ccb *gccb,
GDT_DPRINTF(GDT_D_CMD, ("gdt_internal_cmd(%p, %d, %d, %d, %d, %d)\n",
gdt, service, opcode, arg1, arg2, arg3));
bzero(gdt->sc_cmd, GDT_CMD_SZ);
bzero(gccb->gc_cmd, GDT_CMD_SZ);
for (retries = GDT_RETRIES; ; ) {
gccb->gc_service = service;
gccb->gc_flags = GDT_GCF_INTERNAL;
gdt->sc_set_sema0(gdt);
gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
gdt_enc32(gccb->gc_cmd + GDT_CMD_COMMANDINDEX,
gccb->gc_cmd_index);
gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, opcode);
gdt_enc16(gccb->gc_cmd + GDT_CMD_OPCODE, opcode);
switch (service) {
case GDT_CACHESERVICE:
if (opcode == GDT_IOCTL) {
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION +
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION +
GDT_IOCTL_SUBFUNC, arg1);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION +
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION +
GDT_IOCTL_CHANNEL, arg2);
gdt_enc16(gdt->sc_cmd + GDT_CMD_UNION +
gdt_enc16(gccb->gc_cmd + GDT_CMD_UNION +
GDT_IOCTL_PARAM_SIZE, (u_int16_t)arg3);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_IOCTL_P_PARAM,
gdt_ccb_vtop(gdt, gccb) +
offsetof(struct gdt_ccb, gc_scratch[0]));
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_IOCTL_P_PARAM,
gccb->gc_scratch_busbase);
} else {
gdt_enc16(gdt->sc_cmd + GDT_CMD_UNION +
gdt_enc16(gccb->gc_cmd + GDT_CMD_UNION +
GDT_CACHE_DEVICENO, (u_int16_t)arg1);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION +
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION +
GDT_CACHE_BLOCKNO, arg2);
}
break;
case GDT_SCSIRAWSERVICE:
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION +
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION +
GDT_RAW_DIRECTION, arg1);
gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_BUS] =
gccb->gc_cmd[GDT_CMD_UNION + GDT_RAW_BUS] =
(u_int8_t)arg2;
gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_TARGET] =
gccb->gc_cmd[GDT_CMD_UNION + GDT_RAW_TARGET] =
(u_int8_t)arg3;
gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_LUN] =
gccb->gc_cmd[GDT_CMD_UNION + GDT_RAW_LUN] =
(u_int8_t)(arg3 >> 8);
}
gdt->sc_cmd_len = GDT_CMD_SZ;
gdt->sc_set_sema0(gdt);
gccb->gc_cmd_len = GDT_CMD_SZ;
gdt->sc_cmd_off = 0;
gdt->sc_cmd_cnt = 0;
gdt->sc_copy_cmd(gdt, gccb);
@ -668,13 +679,6 @@ gdt_free_ccb(struct gdt_softc *gdt, struct gdt_ccb *gccb)
wakeup(gccb);
}
static u_int32_t
gdt_ccb_vtop(struct gdt_softc *gdt, struct gdt_ccb *gccb)
{
return (gdt->sc_gccb_busbase
+ (u_int32_t)((caddr_t)gccb - (caddr_t)gdt->sc_gccbs));
}
void
gdt_next(struct gdt_softc *gdt)
{
@ -805,14 +809,13 @@ gdt_raw_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock)
return (NULL);
}
bzero(gdt->sc_cmd, GDT_CMD_SZ);
gccb = gdt_get_ccb(gdt);
if (gccb == NULL) {
GDT_DPRINTF(GDT_D_INVALID, ("iir%d: No free command index found\n",
gdt->sc_hanum));
return (gccb);
}
bzero(gccb->gc_cmd, GDT_CMD_SZ);
sim = (struct cam_sim *)ccb->ccb_h.ccb_sim_ptr;
gccb->gc_ccb = ccb;
gccb->gc_service = GDT_SCSIRAWSERVICE;
@ -821,30 +824,29 @@ gdt_raw_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock)
if (gdt->sc_cmd_cnt == 0)
gdt->sc_set_sema0(gdt);
splx(*lock);
gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
gdt_enc32(gccb->gc_cmd + GDT_CMD_COMMANDINDEX,
gccb->gc_cmd_index);
gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, GDT_WRITE);
gdt_enc16(gccb->gc_cmd + GDT_CMD_OPCODE, GDT_WRITE);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_DIRECTION,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_DIRECTION,
(ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN ?
GDT_DATA_IN : GDT_DATA_OUT);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SDLEN,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SDLEN,
ccb->csio.dxfer_len);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_CLEN,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_CLEN,
ccb->csio.cdb_len);
bcopy(ccb->csio.cdb_io.cdb_bytes, gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_CMD,
bcopy(ccb->csio.cdb_io.cdb_bytes, gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_CMD,
ccb->csio.cdb_len);
gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_TARGET] =
gccb->gc_cmd[GDT_CMD_UNION + GDT_RAW_TARGET] =
ccb->ccb_h.target_id;
gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_LUN] =
gccb->gc_cmd[GDT_CMD_UNION + GDT_RAW_LUN] =
ccb->ccb_h.target_lun;
gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_BUS] =
gccb->gc_cmd[GDT_CMD_UNION + GDT_RAW_BUS] =
cam_sim_bus(sim);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_LEN,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_LEN,
sizeof(struct scsi_sense_data));
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_DATA,
gdt_ccb_vtop(gdt, gccb) +
offsetof(struct gdt_ccb, gc_scratch[0]));
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_DATA,
gccb->gc_scratch_busbase);
/*
* If we have any data to send with this command,
@ -868,7 +870,7 @@ gdt_raw_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock)
gccb, /*flags*/0);
if (error == EINPROGRESS) {
xpt_freeze_simq(sim, 1);
gccb->gc_state |= CAM_RELEASE_SIMQ;
gccb->gc_ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
}
splx(s);
} else {
@ -916,14 +918,13 @@ gdt_cache_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock)
return (NULL);
}
bzero(gdt->sc_cmd, GDT_CMD_SZ);
gccb = gdt_get_ccb(gdt);
if (gccb == NULL) {
GDT_DPRINTF(GDT_D_DEBUG, ("iir%d: No free command index found\n",
gdt->sc_hanum));
return (gccb);
}
bzero(gccb->gc_cmd, GDT_CMD_SZ);
sim = (struct cam_sim *)ccb->ccb_h.ccb_sim_ptr;
gccb->gc_ccb = ccb;
gccb->gc_service = GDT_CACHESERVICE;
@ -932,15 +933,15 @@ gdt_cache_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock)
if (gdt->sc_cmd_cnt == 0)
gdt->sc_set_sema0(gdt);
splx(*lock);
gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
gdt_enc32(gccb->gc_cmd + GDT_CMD_COMMANDINDEX,
gccb->gc_cmd_index);
cmdp = ccb->csio.cdb_io.cdb_bytes;
opcode = (*cmdp == WRITE_6 || *cmdp == WRITE_10) ? GDT_WRITE : GDT_READ;
if ((gdt->sc_state & GDT_SHUTDOWN) && opcode == GDT_WRITE)
opcode = GDT_WRITE_THR;
gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, opcode);
gdt_enc16(gccb->gc_cmd + GDT_CMD_OPCODE, opcode);
gdt_enc16(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DEVICENO,
gdt_enc16(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_DEVICENO,
ccb->ccb_h.target_id);
if (ccb->csio.cdb_len == 6) {
struct scsi_rw_6 *rw = (struct scsi_rw_6 *)cmdp;
@ -951,9 +952,9 @@ gdt_cache_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock)
blockno = scsi_4btoul(rw->addr);
blockcnt = scsi_2btoul(rw->length);
}
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKNO,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKNO,
blockno);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKCNT,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKCNT,
blockcnt);
/*
@ -977,7 +978,7 @@ gdt_cache_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock)
gccb, /*flags*/0);
if (error == EINPROGRESS) {
xpt_freeze_simq(sim, 1);
gccb->gc_state |= CAM_RELEASE_SIMQ;
gccb->gc_ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
}
splx(s);
} else {
@ -1011,14 +1012,13 @@ gdt_ioctl_cmd(struct gdt_softc *gdt, gdt_ucmd_t *ucmd, int *lock)
GDT_DPRINTF(GDT_D_DEBUG, ("gdt_ioctl_cmd(%p, %p)\n", gdt, ucmd));
bzero(gdt->sc_cmd, GDT_CMD_SZ);
gccb = gdt_get_ccb(gdt);
if (gccb == NULL) {
GDT_DPRINTF(GDT_D_DEBUG, ("iir%d: No free command index found\n",
gdt->sc_hanum));
return (gccb);
}
bzero(gccb->gc_cmd, GDT_CMD_SZ);
gccb->gc_ucmd = ucmd;
gccb->gc_service = ucmd->service;
gccb->gc_flags = GDT_GCF_IOCTL;
@ -1026,7 +1026,7 @@ gdt_ioctl_cmd(struct gdt_softc *gdt, gdt_ucmd_t *ucmd, int *lock)
/* check DPMEM space, copy data buffer from user space */
if (ucmd->service == GDT_CACHESERVICE) {
if (ucmd->OpCode == GDT_IOCTL) {
gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_IOCTL_SZ,
gccb->gc_cmd_len = roundup(GDT_CMD_UNION + GDT_IOCTL_SZ,
sizeof(u_int32_t));
cnt = ucmd->u.ioctl.param_size;
if (cnt > GDT_SCRATCH_SZ) {
@ -1036,7 +1036,7 @@ gdt_ioctl_cmd(struct gdt_softc *gdt, gdt_ucmd_t *ucmd, int *lock)
return (NULL);
}
} else {
gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_CACHE_SG_LST +
gccb->gc_cmd_len = roundup(GDT_CMD_UNION + GDT_CACHE_SG_LST +
GDT_SG_SZ, sizeof(u_int32_t));
cnt = ucmd->u.cache.BlockCnt * GDT_SECTOR_SIZE;
if (cnt > GDT_SCRATCH_SZ) {
@ -1047,7 +1047,7 @@ gdt_ioctl_cmd(struct gdt_softc *gdt, gdt_ucmd_t *ucmd, int *lock)
}
}
} else {
gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_RAW_SG_LST +
gccb->gc_cmd_len = roundup(GDT_CMD_UNION + GDT_RAW_SG_LST +
GDT_SG_SZ, sizeof(u_int32_t));
cnt = ucmd->u.raw.sdlen;
if (cnt + ucmd->u.raw.sense_len > GDT_SCRATCH_SZ) {
@ -1060,7 +1060,7 @@ gdt_ioctl_cmd(struct gdt_softc *gdt, gdt_ucmd_t *ucmd, int *lock)
if (cnt != 0)
bcopy(ucmd->data, gccb->gc_scratch, cnt);
if (gdt->sc_cmd_off + gdt->sc_cmd_len + GDT_DPMEM_COMMAND_OFFSET >
if (gdt->sc_cmd_off + gccb->gc_cmd_len + GDT_DPMEM_COMMAND_OFFSET >
gdt->sc_ic_all_size) {
GDT_DPRINTF(GDT_D_INVALID, ("iir%d: gdt_ioctl_cmd(): DPMEM overflow\n",
gdt->sc_hanum));
@ -1073,70 +1073,66 @@ gdt_ioctl_cmd(struct gdt_softc *gdt, gdt_ucmd_t *ucmd, int *lock)
splx(*lock);
/* fill cmd structure */
gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
gdt_enc32(gccb->gc_cmd + GDT_CMD_COMMANDINDEX,
gccb->gc_cmd_index);
gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE,
gdt_enc16(gccb->gc_cmd + GDT_CMD_OPCODE,
ucmd->OpCode);
if (ucmd->service == GDT_CACHESERVICE) {
if (ucmd->OpCode == GDT_IOCTL) {
/* IOCTL */
gdt_enc16(gdt->sc_cmd + GDT_CMD_UNION + GDT_IOCTL_PARAM_SIZE,
gdt_enc16(gccb->gc_cmd + GDT_CMD_UNION + GDT_IOCTL_PARAM_SIZE,
ucmd->u.ioctl.param_size);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_IOCTL_SUBFUNC,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_IOCTL_SUBFUNC,
ucmd->u.ioctl.subfunc);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_IOCTL_CHANNEL,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_IOCTL_CHANNEL,
ucmd->u.ioctl.channel);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_IOCTL_P_PARAM,
gdt_ccb_vtop(gdt, gccb) +
offsetof(struct gdt_ccb, gc_scratch[0]));
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_IOCTL_P_PARAM,
gccb->gc_scratch_busbase);
} else {
/* cache service command */
gdt_enc16(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DEVICENO,
gdt_enc16(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_DEVICENO,
ucmd->u.cache.DeviceNo);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKNO,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKNO,
ucmd->u.cache.BlockNo);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKCNT,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKCNT,
ucmd->u.cache.BlockCnt);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DESTADDR,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_DESTADDR,
0xffffffffUL);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_CANZ,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_CANZ,
1);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
GDT_SG_PTR, gdt_ccb_vtop(gdt, gccb) +
offsetof(struct gdt_ccb, gc_scratch[0]));
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
GDT_SG_PTR, gccb->gc_scratch_busbase);
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
GDT_SG_LEN, ucmd->u.cache.BlockCnt * GDT_SECTOR_SIZE);
}
} else {
/* raw service command */
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_DIRECTION,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_DIRECTION,
ucmd->u.raw.direction);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SDATA,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SDATA,
0xffffffffUL);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SDLEN,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SDLEN,
ucmd->u.raw.sdlen);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_CLEN,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_CLEN,
ucmd->u.raw.clen);
bcopy(ucmd->u.raw.cmd, gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_CMD,
bcopy(ucmd->u.raw.cmd, gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_CMD,
12);
gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_TARGET] =
gccb->gc_cmd[GDT_CMD_UNION + GDT_RAW_TARGET] =
ucmd->u.raw.target;
gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_LUN] =
gccb->gc_cmd[GDT_CMD_UNION + GDT_RAW_LUN] =
ucmd->u.raw.lun;
gdt->sc_cmd[GDT_CMD_UNION + GDT_RAW_BUS] =
gccb->gc_cmd[GDT_CMD_UNION + GDT_RAW_BUS] =
ucmd->u.raw.bus;
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_LEN,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_LEN,
ucmd->u.raw.sense_len);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_DATA,
gdt_ccb_vtop(gdt, gccb) +
offsetof(struct gdt_ccb, gc_scratch[ucmd->u.raw.sdlen]));
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_RANZ,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_DATA,
gccb->gc_scratch_busbase + ucmd->u.raw.sdlen);
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SG_RANZ,
1);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
GDT_SG_PTR, gdt_ccb_vtop(gdt, gccb) +
offsetof(struct gdt_ccb, gc_scratch[0]));
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
GDT_SG_PTR, gccb->gc_scratch_busbase);
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
GDT_SG_LEN, ucmd->u.raw.sdlen);
}
@ -1221,7 +1217,7 @@ gdt_internal_cache_cmd(struct gdt_softc *gdt,union ccb *ccb)
ccb->csio.cdb_io.cdb_bytes[0]));
break;
}
ccb->ccb_h.status = CAM_REQ_CMP;
ccb->ccb_h.status |= CAM_REQ_CMP;
--gdt_stat.io_count_act;
xpt_done(ccb);
}
@ -1258,33 +1254,33 @@ gdtexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
/* Copy the segments into our SG list */
if (gccb->gc_service == GDT_CACHESERVICE) {
for (i = 0; i < nseg; ++i) {
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
i * GDT_SG_SZ + GDT_SG_PTR, dm_segs->ds_addr);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_LST +
i * GDT_SG_SZ + GDT_SG_LEN, dm_segs->ds_len);
dm_segs++;
}
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_CANZ,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_SG_CANZ,
nseg);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_CACHE_DESTADDR,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_DESTADDR,
0xffffffffUL);
gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_CACHE_SG_LST +
gccb->gc_cmd_len = roundup(GDT_CMD_UNION + GDT_CACHE_SG_LST +
nseg * GDT_SG_SZ, sizeof(u_int32_t));
} else {
for (i = 0; i < nseg; ++i) {
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
i * GDT_SG_SZ + GDT_SG_PTR, dm_segs->ds_addr);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SG_LST +
i * GDT_SG_SZ + GDT_SG_LEN, dm_segs->ds_len);
dm_segs++;
}
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SG_RANZ,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SG_RANZ,
nseg);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_RAW_SDATA,
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SDATA,
0xffffffffUL);
gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_RAW_SG_LST +
gccb->gc_cmd_len = roundup(GDT_CMD_UNION + GDT_RAW_SG_LST +
nseg * GDT_SG_SZ, sizeof(u_int32_t));
}
@ -1463,7 +1459,7 @@ iir_poll( struct cam_sim *sim )
static void
iir_timeout(void *arg)
{
GDT_DPRINTF(GDT_D_TIMEOUT, ("iir_timeout(%p)\n", arg));
GDT_DPRINTF(GDT_D_TIMEOUT, ("iir_timeout(%p)\n", gccb));
}
static void
@ -1494,7 +1490,7 @@ iir_watchdog(void *arg)
pends++;
GDT_DPRINTF(GDT_D_TIMEOUT, ("ccbs %d ucmds %d frees %d pends %d\n",
ccbs, ucmds, frees, pends));
ccbs, ucmds, frees, pends));
}
timeout(iir_watchdog, (caddr_t)gdt, hz * 15);
@ -1515,7 +1511,7 @@ iir_shutdown( void *arg, int howto )
gdt->sc_hanum);
/* allocate ucmd buffer */
ucmd = malloc(sizeof(gdt_ucmd_t), M_DEVBUF, M_NOWAIT);
ucmd = malloc(sizeof(gdt_ucmd_t), M_GDTBUF, M_NOWAIT);
if (ucmd == NULL) {
printf("iir%d: iir_shutdown(): Cannot allocate resource\n",
gdt->sc_hanum);
@ -1572,7 +1568,7 @@ iir_intr(void *arg)
gdt_wait_index = 0;
ctx.istatus = gdt->sc_get_status(gdt);
if (!ctx.istatus) {
if (ctx.istatus == 0x00) {
if (!(gdt->sc_state & GDT_POLLING))
splx(lock);
gdt->sc_status = GDT_S_NO_STATUS;
@ -1687,26 +1683,25 @@ gdt_async_event(struct gdt_softc *gdt, int service)
if (gdt->sc_status == GDT_MSG_REQUEST) {
while (gdt->sc_test_busy(gdt))
DELAY(1);
bzero(gdt->sc_cmd, GDT_CMD_SZ);
gccb = gdt_get_ccb(gdt);
if (gccb == NULL) {
printf("iir%d: No free command index found\n",
gdt->sc_hanum);
return (1);
}
bzero(gccb->gc_cmd, GDT_CMD_SZ);
gccb->gc_service = service;
gccb->gc_flags = GDT_GCF_SCREEN;
gdt->sc_set_sema0(gdt);
gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
gdt_enc32(gccb->gc_cmd + GDT_CMD_COMMANDINDEX,
gccb->gc_cmd_index);
gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, GDT_READ);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_HANDLE,
gdt_enc16(gccb->gc_cmd + GDT_CMD_OPCODE, GDT_READ);
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_HANDLE,
GDT_MSG_INV_HANDLE);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_ADDR,
gdt_ccb_vtop(gdt, gccb) +
offsetof(struct gdt_ccb, gc_scratch[0]));
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_ADDR,
gccb->gc_scratch_busbase);
gdt->sc_set_sema0(gdt);
gdt->sc_cmd_off = 0;
gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_SCREEN_SZ,
gccb->gc_cmd_len = roundup(GDT_CMD_UNION + GDT_SCREEN_SZ,
sizeof(u_int32_t));
gdt->sc_cmd_cnt = 0;
gdt->sc_copy_cmd(gdt, gccb);
@ -1762,7 +1757,7 @@ gdt_sync_event(struct gdt_softc *gdt, int service,
!gccb->gc_scratch[GDT_SCR_MSG_ANSWER]) {
while (gdt->sc_test_busy(gdt))
DELAY(1);
bzero(gdt->sc_cmd, GDT_CMD_SZ);
bzero(gccb->gc_cmd, GDT_CMD_SZ);
gccb = gdt_get_ccb(gdt);
if (gccb == NULL) {
printf("iir%d: No free command index found\n",
@ -1771,17 +1766,16 @@ gdt_sync_event(struct gdt_softc *gdt, int service,
}
gccb->gc_service = service;
gccb->gc_flags = GDT_GCF_SCREEN;
gdt->sc_set_sema0(gdt);
gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
gdt_enc32(gccb->gc_cmd + GDT_CMD_COMMANDINDEX,
gccb->gc_cmd_index);
gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, GDT_READ);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_HANDLE,
gdt_enc16(gccb->gc_cmd + GDT_CMD_OPCODE, GDT_READ);
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_HANDLE,
gccb->gc_scratch[GDT_SCR_MSG_HANDLE]);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_ADDR,
gdt_ccb_vtop(gdt, gccb) +
offsetof(struct gdt_ccb, gc_scratch[0]));
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_ADDR,
gccb->gc_scratch_busbase);
gdt->sc_set_sema0(gdt);
gdt->sc_cmd_off = 0;
gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_SCREEN_SZ,
gccb->gc_cmd_len = roundup(GDT_CMD_UNION + GDT_SCREEN_SZ,
sizeof(u_int32_t));
gdt->sc_cmd_cnt = 0;
gdt->sc_copy_cmd(gdt, gccb);
@ -1807,7 +1801,7 @@ gdt_sync_event(struct gdt_softc *gdt, int service,
gccb->gc_scratch[GDT_SCR_MSG_ANSWER] = 0;
while (gdt->sc_test_busy(gdt))
DELAY(1);
bzero(gdt->sc_cmd, GDT_CMD_SZ);
bzero(gccb->gc_cmd, GDT_CMD_SZ);
gccb = gdt_get_ccb(gdt);
if (gccb == NULL) {
printf("iir%d: No free command index found\n",
@ -1816,17 +1810,16 @@ gdt_sync_event(struct gdt_softc *gdt, int service,
}
gccb->gc_service = service;
gccb->gc_flags = GDT_GCF_SCREEN;
gdt->sc_set_sema0(gdt);
gdt_enc32(gdt->sc_cmd + GDT_CMD_COMMANDINDEX,
gdt_enc32(gccb->gc_cmd + GDT_CMD_COMMANDINDEX,
gccb->gc_cmd_index);
gdt_enc16(gdt->sc_cmd + GDT_CMD_OPCODE, GDT_WRITE);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_HANDLE,
gdt_enc16(gccb->gc_cmd + GDT_CMD_OPCODE, GDT_WRITE);
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_HANDLE,
gccb->gc_scratch[GDT_SCR_MSG_HANDLE]);
gdt_enc32(gdt->sc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_ADDR,
gdt_ccb_vtop(gdt, gccb) +
offsetof(struct gdt_ccb, gc_scratch[0]));
gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_SCREEN_MSG_ADDR,
gccb->gc_scratch_busbase);
gdt->sc_set_sema0(gdt);
gdt->sc_cmd_off = 0;
gdt->sc_cmd_len = roundup(GDT_CMD_UNION + GDT_SCREEN_SZ,
gccb->gc_cmd_len = roundup(GDT_CMD_UNION + GDT_SCREEN_SZ,
sizeof(u_int32_t));
gdt->sc_cmd_cnt = 0;
gdt->sc_copy_cmd(gdt, gccb);
@ -1850,14 +1843,17 @@ gdt_sync_event(struct gdt_softc *gdt, int service,
bus_dmamap_sync(gdt->sc_buffer_dmat, gccb->gc_dmamap,
(ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN ?
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(gdt->sc_buffer_dmat, gccb->gc_dmamap);
ccb->csio.resid = 0;
if (gdt->sc_status == GDT_S_OK) {
ccb->ccb_h.status = CAM_REQ_CMP;
ccb->ccb_h.status |= CAM_REQ_CMP;
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
} else {
/* error */
if (gccb->gc_service == GDT_CACHESERVICE) {
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
bzero(&ccb->csio.sense_data, ccb->csio.sense_len);
ccb->csio.sense_data.error_code =
@ -1879,7 +1875,8 @@ gdt_sync_event(struct gdt_softc *gdt, int service,
if (gdt->sc_status != GDT_S_RAW_SCSI || gdt->sc_info >= 0x100) {
ccb->ccb_h.status = CAM_DEV_NOT_THERE;
} else {
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR|CAM_AUTOSNS_VALID;
ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR|CAM_AUTOSNS_VALID;
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
ccb->csio.scsi_status = gdt->sc_info;
bcopy(gccb->gc_scratch, &ccb->csio.sense_data,
ccb->csio.sense_len);

View File

@ -612,20 +612,19 @@ struct gdt_softc {
bus_addr_t sc_dpmembase;
bus_dma_tag_t sc_parent_dmat;
bus_dma_tag_t sc_buffer_dmat;
bus_dma_tag_t sc_gccb_dmat;
bus_dmamap_t sc_gccb_dmamap;
bus_addr_t sc_gccb_busbase;
bus_dma_tag_t sc_gcscratch_dmat;
bus_dmamap_t sc_gcscratch_dmamap;
bus_addr_t sc_gcscratch_busbase;
struct gdt_ccb *sc_gccbs;
u_int8_t *sc_gcscratch;
SLIST_HEAD(, gdt_ccb) sc_free_gccb, sc_pending_gccb;
TAILQ_HEAD(, ccb_hdr) sc_ccb_queue;
TAILQ_HEAD(, gdt_ucmd) sc_ucmd_queue;
u_int16_t sc_ic_all_size;
u_int16_t sc_cmd_len;
u_int16_t sc_cmd_off;
u_int16_t sc_cmd_cnt;
u_int8_t sc_cmd[GDT_CMD_SZ];
u_int32_t sc_info;
u_int32_t sc_info2;
@ -679,13 +678,13 @@ struct gdt_softc {
* controller.
*/
struct gdt_ccb {
u_int8_t gc_scratch[GDT_SCRATCH_SZ];
u_int8_t *gc_scratch;
bus_addr_t gc_scratch_busbase;
union ccb *gc_ccb;
gdt_ucmd_t *gc_ucmd;
bus_dmamap_t gc_dmamap;
int gc_map_flag;
int gc_timeout;
int gc_state;
u_int8_t gc_service;
u_int8_t gc_cmd_index;
u_int8_t gc_flags;
@ -694,6 +693,8 @@ struct gdt_ccb {
#define GDT_GCF_SCREEN 2
#define GDT_GCF_SCSI 3
#define GDT_GCF_IOCTL 4
u_int16_t gc_cmd_len;
u_int8_t gc_cmd[GDT_CMD_SZ];
SLIST_ENTRY(gdt_ccb) sle;
};

View File

@ -386,9 +386,9 @@ gdt_pci_enable_intr(struct gdt_softc *gdt)
*/
void
gdt_mpr_copy_cmd(struct gdt_softc *gdt, struct gdt_ccb *ccb)
gdt_mpr_copy_cmd(struct gdt_softc *gdt, struct gdt_ccb *gccb)
{
u_int16_t cp_count = roundup(gdt->sc_cmd_len, sizeof (u_int32_t));
u_int16_t cp_count = roundup(gccb->gc_cmd_len, sizeof (u_int32_t));
u_int16_t dp_offset = gdt->sc_cmd_off;
u_int16_t cmd_no = gdt->sc_cmd_cnt++;
@ -396,15 +396,15 @@ gdt_mpr_copy_cmd(struct gdt_softc *gdt, struct gdt_ccb *ccb)
gdt->sc_cmd_off += cp_count;
bus_space_write_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh,
GDT_MPR_IC + GDT_DPR_CMD + dp_offset,
(u_int32_t *)gccb->gc_cmd, cp_count >> 2);
bus_space_write_2(gdt->sc_dpmemt, gdt->sc_dpmemh,
GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_OFFSET,
htole16(GDT_DPMEM_COMMAND_OFFSET + dp_offset));
bus_space_write_2(gdt->sc_dpmemt, gdt->sc_dpmemh,
GDT_MPR_IC + GDT_COMM_QUEUE + cmd_no * GDT_COMM_Q_SZ + GDT_SERV_ID,
htole16(ccb->gc_service));
bus_space_write_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh,
GDT_MPR_IC + GDT_DPR_CMD + dp_offset,
(u_int32_t *)gdt->sc_cmd, cp_count >> 2);
htole16(gccb->gc_service));
}
u_int8_t
@ -422,6 +422,8 @@ gdt_mpr_intr(struct gdt_softc *gdt, struct gdt_intr_ctx *ctx)
GDT_DPRINTF(GDT_D_INTR, ("gdt_mpr_intr(%p) ", gdt));
bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff);
if (ctx->istatus & 0x80) { /* error flag */
ctx->istatus &= ~0x80;
ctx->cmd_status = bus_space_read_2(gdt->sc_dpmemt,
@ -452,7 +454,6 @@ gdt_mpr_intr(struct gdt_softc *gdt, struct gdt_intr_ctx *ctx)
}
}
}
bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff);
bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_SEMA1, 0);
}