summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1999-04-23 23:27:31 +0000
committergibbs <gibbs@FreeBSD.org>1999-04-23 23:27:31 +0000
commit405e2ed76987008c9283af7e5e8f94106999dca9 (patch)
tree3c3a9a4a68271153884366e104e709d26fa7cdca
parent998c74d3802aa5010ff231f96a8e7cc26020179a (diff)
downloadFreeBSD-src-405e2ed76987008c9283af7e5e8f94106999dca9.zip
FreeBSD-src-405e2ed76987008c9283af7e5e8f94106999dca9.tar.gz
Complete conversion to bus dma. This driver now works on the alpha.
aicasm_symbol.c: Correct an unaligned access problem. You can't rely on DB to store your data in an aligned fashion.
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c956
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h142
-rw-r--r--sys/dev/aic7xxx/aicasm/aicasm_symbol.c20
-rw-r--r--sys/dev/aic7xxx/aicasm_symbol.c20
4 files changed, 703 insertions, 435 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index 5e0ccab..672b60e 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.c,v 1.21 1999/04/07 23:02:45 gibbs Exp $
+ * $Id: aic7xxx.c,v 1.22 1999/04/19 21:28:15 gibbs Exp $
*/
/*
* A few notes on features of the driver.
@@ -114,6 +114,7 @@
#include <machine/bus_pio.h>
#include <machine/bus.h>
#include <machine/clock.h>
+#include <sys/rman.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -192,8 +193,6 @@ typedef enum {
SEARCH_REMOVE
} ahc_search_action;
-u_long ahc_unit = 0;
-
#ifdef AHC_DEBUG
static int ahc_debug = AHC_DEBUG;
#endif
@@ -202,6 +201,11 @@ static int ahc_debug = AHC_DEBUG;
void ahc_pci_intr(struct ahc_softc *ahc);
#endif
+static int ahcinitscbdata(struct ahc_softc *ahc);
+static void ahcfiniscbdata(struct ahc_softc *ahc);
+
+static bus_dmamap_callback_t ahcdmamapcb;
+
#if UNUSED
static void ahc_dump_targcmd(struct target_cmd *cmd);
#endif
@@ -221,11 +225,7 @@ static void ahc_poll(struct cam_sim *sim);
static void ahc_setup_data(struct ahc_softc *ahc,
struct ccb_scsiio *csio, struct scb *scb);
static void ahc_freeze_devq(struct ahc_softc *ahc, struct cam_path *path);
-static struct scb *
- ahc_get_scb(struct ahc_softc *ahc);
-static void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
-static struct scb *
- ahc_alloc_scb(struct ahc_softc *ahc);
+static void ahcallocscbs(struct ahc_softc *ahc);
static void ahc_scb_devinfo(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
struct scb *scb);
@@ -350,8 +350,8 @@ static __inline void ahc_busy_tcl(struct ahc_softc *ahc, struct scb *scb);
static __inline void ahc_freeze_ccb(union ccb* ccb);
static __inline cam_status ahc_ccb_status(union ccb* ccb);
-static __inline void ahc_set_ccb_status(union ccb* ccb,
- cam_status status);
+static __inline void ahcsetccbstatus(union ccb* ccb,
+ cam_status status);
static __inline void ahc_run_tqinfifo(struct ahc_softc *ahc);
static __inline struct ahc_initiator_tinfo *
@@ -359,11 +359,16 @@ static __inline struct ahc_initiator_tinfo *
char channel,
u_int our_id, u_int target,
struct tmode_tstate **tstate);
+static __inline void
+ ahcfreescb(struct ahc_softc *ahc, struct scb *scb);
+static __inline struct scb *
+ ahcgetscb(struct ahc_softc *ahc);
static __inline u_int32_t
ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
{
- return (ahc->hscb_busaddr + (sizeof(struct hardware_scb) * index));
+ return (ahc->scb_data->hscb_busaddr
+ + (sizeof(struct hardware_scb) * index));
}
#define AHC_BUSRESET_DELAY 25 /* Reset delay in us */
@@ -440,7 +445,7 @@ ahc_ccb_status(union ccb* ccb)
}
static __inline void
-ahc_set_ccb_status(union ccb* ccb, cam_status status)
+ahcsetccbstatus(union ccb* ccb, cam_status status)
{
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
ccb->ccb_h.status |= status;
@@ -491,6 +496,62 @@ ahc_run_tqinfifo(struct ahc_softc *ahc)
}
}
+/*
+ * An scb (and hence an scb entry on the board) is put onto the
+ * free list.
+ */
+static __inline void
+ahcfreescb(struct ahc_softc *ahc, struct scb *scb)
+{
+ struct hardware_scb *hscb;
+ int opri;
+
+ hscb = scb->hscb;
+
+ opri = splcam();
+
+ if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0
+ && (scb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
+ scb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
+ ahc->flags &= ~AHC_RESOURCE_SHORTAGE;
+ }
+
+ /* Clean up for the next user */
+ scb->flags = SCB_FREE;
+ hscb->control = 0;
+ hscb->status = 0;
+
+ SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links);
+ splx(opri);
+}
+
+/*
+ * Get a free scb, either one already assigned to a hardware slot
+ * on the adapter or one that will require an SCB to be paged out before
+ * use. If there are none, see if we can allocate a new SCB. Otherwise
+ * either return an error or sleep.
+ */
+static __inline struct scb *
+ahcgetscb(struct ahc_softc *ahc)
+{
+ struct scb *scbp;
+ int opri;
+
+ opri = splcam();
+ if ((scbp = SLIST_FIRST(&ahc->scb_data->free_scbs))) {
+ SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links);
+ } else {
+ ahcallocscbs(ahc);
+ scbp = SLIST_FIRST(&ahc->scb_data->free_scbs);
+ if (scbp != NULL)
+ SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links);
+ }
+
+ splx(opri);
+
+ return (scbp);
+}
+
char *
ahc_name(struct ahc_softc *ahc)
{
@@ -518,8 +579,8 @@ ahc_print_scb(struct scb *scb)
hscb->SG_count,
hscb->SG_pointer);
printf(" sg_addr:%lx sg_len:%ld\n",
- scb->ahc_dma[0].addr,
- scb->ahc_dma[0].len);
+ scb->sg_list[0].addr,
+ scb->sg_list[0].len);
printf(" cdb:%x %x %x %x %x %x %x %x %x %x %x %x\n",
hscb->cmdstore[0], hscb->cmdstore[1], hscb->cmdstore[2],
hscb->cmdstore[3], hscb->cmdstore[4], hscb->cmdstore[5],
@@ -573,8 +634,9 @@ static struct ahc_syncrate ahc_syncrates[] = {
* Allocate a controller structure for a new device and initialize it.
*/
struct ahc_softc *
-ahc_alloc(int unit, u_int32_t iobase, vm_offset_t maddr, ahc_chip chip,
- ahc_feature features, ahc_flag flags, struct scb_data *scb_data)
+ahc_alloc(device_t dev, struct resource *regs, int regs_type, int regs_id,
+ bus_dma_tag_t parent_dmat, ahc_chip chip, ahc_feature features,
+ ahc_flag flags, struct scb_data *scb_data)
{
/*
* find unit and check we have that many defined
@@ -595,41 +657,33 @@ ahc_alloc(int unit, u_int32_t iobase, vm_offset_t maddr, ahc_chip chip,
alloc_size = sizeof(struct ahc_softc);
ahc = malloc(alloc_size, M_DEVBUF, M_NOWAIT);
if (!ahc) {
- printf("ahc%d: cannot malloc!\n", unit);
+ device_printf(dev, "cannot malloc softc!\n");
return NULL;
}
bzero(ahc, alloc_size);
+ LIST_INIT(&ahc->pending_ccbs);
+ ahc->device = dev;
+ ahc->unit = device_get_unit(dev);
+ ahc->regs_res_type = regs_type;
+ ahc->regs_res_id = regs_id;
+ ahc->regs = regs;
+ ahc->tag = rman_get_bustag(regs);
+ ahc->bsh = rman_get_bushandle(regs);
+ ahc->parent_dmat = parent_dmat;
+ ahc->chip = chip;
+ ahc->features = features;
+ ahc->flags = flags;
if (scb_data == NULL) {
struct full_ahc_softc* full_softc = (struct full_ahc_softc*)ahc;
ahc->scb_data = &full_softc->scb_data_storage;
- STAILQ_INIT(&ahc->scb_data->free_scbs);
} else
ahc->scb_data = scb_data;
- LIST_INIT(&ahc->pending_ccbs);
- ahc->unit = unit;
- /*
- * XXX This should be done by the bus specific probe stubs with
- * the bus layer providing the bsh and tag. Unfortunately,
- * we need to clean up how we configure things before this
- * can happen.
- */
- if (maddr != NULL) {
- ahc->tag = I386_BUS_SPACE_MEM;
- ahc->bsh = (bus_space_handle_t)maddr;
- } else {
- ahc->tag = I386_BUS_SPACE_IO;
- ahc->bsh = (bus_space_handle_t)iobase;
- }
- ahc->chip = chip;
- ahc->features = features;
- ahc->flags = flags;
ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
/* The IRQMS bit is only valid on VL and EISA chips */
if ((ahc->chip & AHC_PCI) != 0)
ahc->unpause &= ~IRQMS;
ahc->pause = ahc->unpause | PAUSE;
-
return (ahc);
}
@@ -637,10 +691,241 @@ void
ahc_free(ahc)
struct ahc_softc *ahc;
{
+ ahcfiniscbdata(ahc);
+ switch (ahc->init_level) {
+ case 3:
+ bus_dmamap_unload(ahc->shared_data_dmat,
+ ahc->shared_data_dmamap);
+ case 2:
+ bus_dmamem_free(ahc->shared_data_dmat, ahc->qoutfifo,
+ ahc->shared_data_dmamap);
+ bus_dmamap_destroy(ahc->shared_data_dmat,
+ ahc->shared_data_dmamap);
+ case 1:
+ bus_dma_tag_destroy(ahc->buffer_dmat);
+ break;
+ }
+
+ if (ahc->regs != NULL)
+ bus_release_resource(ahc->device, ahc->regs_res_type,
+ ahc->regs_res_id, ahc->regs);
+ if (ahc->irq != NULL)
+ bus_release_resource(ahc->device, ahc->irq_res_type,
+ 0, ahc->irq);
+
free(ahc, M_DEVBUF);
return;
}
+static int
+ahcinitscbdata(struct ahc_softc *ahc)
+{
+ struct scb_data *scb_data;
+ int i;
+
+ scb_data = ahc->scb_data;
+ SLIST_INIT(&scb_data->free_scbs);
+ SLIST_INIT(&scb_data->sg_maps);
+
+ /* Allocate SCB resources */
+ scb_data->scbarray =
+ (struct scb *)malloc(sizeof(struct scb) * AHC_SCB_MAX,
+ M_DEVBUF, M_NOWAIT);
+ if (scb_data->scbarray == NULL)
+ return (ENOMEM);
+ bzero(scb_data->scbarray, sizeof(struct scb) * AHC_SCB_MAX);
+
+ /* Determine the number of hardware SCBs and initialize them */
+
+ scb_data->maxhscbs = ahc_probe_scbs(ahc);
+ /* SCB 0 heads the free list */
+ ahc_outb(ahc, FREE_SCBH, 0);
+ for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
+ ahc_outb(ahc, SCBPTR, i);
+
+ /* Clear the control byte. */
+ ahc_outb(ahc, SCB_CONTROL, 0);
+
+ /* Set the next pointer */
+ ahc_outb(ahc, SCB_NEXT, i+1);
+
+ /* Make the tag number invalid */
+ ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL);
+ }
+
+ /* Make sure that the last SCB terminates the free list */
+ ahc_outb(ahc, SCBPTR, i-1);
+ ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL);
+
+ /* Ensure we clear the 0 SCB's control byte. */
+ ahc_outb(ahc, SCBPTR, 0);
+ ahc_outb(ahc, SCB_CONTROL, 0);
+
+ scb_data->maxhscbs = i;
+
+ if (ahc->scb_data->maxhscbs == 0)
+ panic("%s: No SCB space found", ahc_name(ahc));
+
+ /*
+ * Create our DMA tags. These tags define the kinds of device
+ * accessable memory allocations and memory mappings we will
+ * need to perform during normal operation.
+ *
+ * Unless we need to further restrict the allocation, we rely
+ * on the restrictions of the parent dmat, hence the common
+ * use of MAXADDR and MAXSIZE.
+ */
+
+ /* DMA tag for our hardware scb structures */
+ if (bus_dma_tag_create(ahc->parent_dmat, /*alignment*/0, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ AHC_SCB_MAX * sizeof(struct hardware_scb),
+ /*nsegments*/1,
+ /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
+ /*flags*/0, &scb_data->hscb_dmat) != 0) {
+ goto error_exit;
+ }
+
+ scb_data->init_level++;
+
+ /* Allocation for our ccbs */
+ if (bus_dmamem_alloc(scb_data->hscb_dmat, (void **)&scb_data->hscbs,
+ BUS_DMA_NOWAIT, &scb_data->hscb_dmamap) != 0) {
+ goto error_exit;
+ }
+
+ scb_data->init_level++;
+
+ /* And permanently map them */
+ bus_dmamap_load(scb_data->hscb_dmat, scb_data->hscb_dmamap,
+ scb_data->hscbs,
+ AHC_SCB_MAX * sizeof(struct hardware_scb),
+ ahcdmamapcb, &scb_data->hscb_busaddr, /*flags*/0);
+
+ scb_data->init_level++;
+
+ /* DMA tag for our sense buffers */
+ if (bus_dma_tag_create(ahc->parent_dmat, /*alignment*/0, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ AHC_SCB_MAX * sizeof(struct scsi_sense_data),
+ /*nsegments*/1,
+ /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
+ /*flags*/0, &scb_data->sense_dmat) != 0) {
+ goto error_exit;
+ }
+
+ scb_data->init_level++;
+
+ /* Allocate them */
+ if (bus_dmamem_alloc(scb_data->sense_dmat, (void **)&scb_data->sense,
+ BUS_DMA_NOWAIT, &scb_data->sense_dmamap) != 0) {
+ goto error_exit;
+ }
+
+ scb_data->init_level++;
+
+ /* And permanently map them */
+ bus_dmamap_load(scb_data->sense_dmat, scb_data->sense_dmamap,
+ scb_data->sense,
+ AHC_SCB_MAX * sizeof(struct scsi_sense_data),
+ ahcdmamapcb, &scb_data->sense_busaddr, /*flags*/0);
+
+ scb_data->init_level++;
+
+ /* DMA tag for our S/G structures. We allocate in page sized chunks */
+ if (bus_dma_tag_create(ahc->parent_dmat, /*alignment*/0, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ PAGE_SIZE, /*nsegments*/1,
+ /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
+ /*flags*/0, &scb_data->sg_dmat) != 0) {
+ goto error_exit;
+ }
+
+ scb_data->init_level++;
+
+ /* Perform initial CCB allocation */
+ bzero(scb_data->hscbs, AHC_SCB_MAX * sizeof(struct hardware_scb));
+ ahcallocscbs(ahc);
+
+ if (scb_data->numscbs == 0) {
+ printf("%s: ahc_init_scb_data - "
+ "Unable to allocate initial scbs\n",
+ ahc_name(ahc));
+ goto error_exit;
+ }
+
+ /*
+ * Note that we were successfull
+ */
+ return 0;
+
+error_exit:
+
+ return ENOMEM;
+}
+
+static void
+ahcfiniscbdata(struct ahc_softc *ahc)
+{
+ struct scb_data *scb_data;
+
+ scb_data = ahc->scb_data;
+
+ switch (scb_data->init_level) {
+ default:
+ case 7:
+ {
+ struct sg_map_node *sg_map;
+
+ while ((sg_map = SLIST_FIRST(&scb_data->sg_maps))!= NULL) {
+ SLIST_REMOVE_HEAD(&scb_data->sg_maps, links);
+ bus_dmamap_unload(scb_data->sg_dmat,
+ sg_map->sg_dmamap);
+ bus_dmamem_free(scb_data->sg_dmat, sg_map->sg_vaddr,
+ sg_map->sg_dmamap);
+ free(sg_map, M_DEVBUF);
+ }
+ bus_dma_tag_destroy(scb_data->sg_dmat);
+ }
+ case 6:
+ bus_dmamap_unload(scb_data->sense_dmat,
+ scb_data->sense_dmamap);
+ case 5:
+ bus_dmamem_free(scb_data->sense_dmat, scb_data->sense,
+ scb_data->sense_dmamap);
+ bus_dmamap_destroy(scb_data->sense_dmat,
+ scb_data->sense_dmamap);
+ case 4:
+ bus_dma_tag_destroy(scb_data->sense_dmat);
+ case 3:
+ bus_dmamap_unload(scb_data->hscb_dmat, scb_data->hscb_dmamap);
+ case 2:
+ bus_dmamem_free(scb_data->hscb_dmat, scb_data->hscbs,
+ scb_data->hscb_dmamap);
+ bus_dmamap_destroy(scb_data->hscb_dmat, scb_data->hscb_dmamap);
+ case 1:
+ bus_dma_tag_destroy(scb_data->hscb_dmat);
+ break;
+ }
+ if (scb_data->scbarray != NULL)
+ free(scb_data->scbarray, M_DEVBUF);
+}
+
+static void
+ahcdmamapcb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ bus_addr_t *baddr;
+
+ baddr = (bus_addr_t *)arg;
+ *baddr = segs->ds_addr;
+}
+
int
ahc_reset(struct ahc_softc *ahc)
{
@@ -1082,11 +1367,22 @@ ahc_attach(struct ahc_softc *ahc)
struct cam_path *path;
struct cam_path *path2;
int count;
+ int s;
+ int error;
count = 0;
sim = NULL;
sim2 = NULL;
+ s = splcam();
+ /* Hook up our interrupt handler */
+ if ((error = bus_setup_intr(ahc->device, ahc->irq, ahc_intr,
+ ahc, &ahc->ih)) != 0) {
+ device_printf(ahc->device, "bus_setup_intr() failed: %d\n",
+ error);
+ goto fail;
+ }
+
/*
* Attach secondary channel first if the user has
* declared it the primary channel.
@@ -1102,7 +1398,7 @@ ahc_attach(struct ahc_softc *ahc)
/*
* Create the device queue for our SIM(s).
*/
- devq = cam_simq_alloc(ahc->scb_data->maxscbs);
+ devq = cam_simq_alloc(AHC_SCB_MAX);
if (devq == NULL)
goto fail;
@@ -1110,7 +1406,7 @@ ahc_attach(struct ahc_softc *ahc)
* Construct our first channel SIM entry
*/
sim = cam_sim_alloc(ahc_action, ahc_poll, "ahc", ahc, ahc->unit,
- 1, ahc->scb_data->maxscbs, devq);
+ 1, AHC_SCB_MAX, devq);
if (sim == NULL) {
cam_simq_free(devq);
goto fail;
@@ -1142,7 +1438,7 @@ ahc_attach(struct ahc_softc *ahc)
if (ahc->features & AHC_TWIN) {
sim2 = cam_sim_alloc(ahc_action, ahc_poll, "ahc",
ahc, ahc->unit, 1,
- ahc->scb_data->maxscbs, devq);
+ AHC_SCB_MAX, devq);
if (sim2 == NULL) {
printf("ahc_attach: Unable to attach second "
@@ -1178,6 +1474,7 @@ ahc_attach(struct ahc_softc *ahc)
xpt_action((union ccb *)&csa);
count++;
}
+
fail:
if ((ahc->flags & AHC_CHANNEL_B_PRIMARY) != 0) {
ahc->sim_b = sim;
@@ -1190,6 +1487,7 @@ fail:
ahc->sim_b = sim2;
ahc->path_b = path2;
}
+ splx(s);
return (count);
}
@@ -1298,8 +1596,9 @@ ahc_intr(void *arg)
scb_index = ahc->qoutfifo[ahc->qoutfifonext];
ahc->qoutfifo[ahc->qoutfifonext++] = SCB_LIST_NULL;
- scb = ahc->scb_data->scbarray[scb_index];
- if (!scb || !(scb->flags & SCB_ACTIVE)) {
+ scb = &ahc->scb_data->scbarray[scb_index];
+ if (scb_index >= ahc->scb_data->numscbs
+ || (scb->flags & SCB_ACTIVE) == 0) {
printf("%s: WARNING no command for scb %d "
"(cmdcmplt)\nQOUTPOS = %d\n",
ahc_name(ahc), scb_index,
@@ -1843,7 +2142,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
* the in kernel copy directly.
*/
scb_index = ahc_inb(ahc, SCB_TAG);
- scb = ahc->scb_data->scbarray[scb_index];
+ scb = &ahc->scb_data->scbarray[scb_index];
hscb = scb->hscb;
/*
@@ -1852,7 +2151,8 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
* this if needed.
*/
ahc_outb(ahc, RETURN_1, 0);
- if (!(scb && (scb->flags & SCB_ACTIVE))) {
+ if (!(scb_index < ahc->scb_data->numscbs
+ && (scb->flags & SCB_ACTIVE) != 0)) {
printf("%s:%c:%d: ahc_intr - referenced scb "
"not valid during seqint 0x%x scb(%d)\n",
ahc_name(ahc), devinfo.channel,
@@ -1868,10 +2168,10 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
* complete.
*/
scb->flags &= ~SCB_SENSE;
- ahc_set_ccb_status(scb->ccb, CAM_AUTOSENSE_FAIL);
+ ahcsetccbstatus(scb->ccb, CAM_AUTOSENSE_FAIL);
break;
}
- ahc_set_ccb_status(scb->ccb, CAM_SCSI_STATUS_ERROR);
+ ahcsetccbstatus(scb->ccb, CAM_SCSI_STATUS_ERROR);
/* Freeze the queue unit the client sees the error. */
ahc_freeze_devq(ahc, scb->ccb->ccb_h.path);
ahc_freeze_ccb(scb->ccb);
@@ -1893,12 +2193,13 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
#endif
if ((csio->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) {
- struct ahc_dma_seg *sg = scb->ahc_dma;
- struct scsi_sense *sc =
- (struct scsi_sense *)(&hscb->cmdstore);
+ struct ahc_dma_seg *sg;
+ struct scsi_sense *sc;
struct ahc_initiator_tinfo *tinfo;
struct tmode_tstate *tstate;
+ sg = scb->sg_list;
+ sc = (struct scsi_sense *)(&hscb->cmdstore);
/*
* Save off the residual if there is one.
*/
@@ -1911,24 +2212,18 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
printf("Sending Sense\n");
}
#endif
- /*
- * bzero from the sense data before having
- * the drive fill it. The SCSI spec mandates
- * that any untransfered data should be
- * assumed to be zero.
- */
- bzero(&csio->sense_data,
- sizeof(csio->sense_data));
+ sg->addr = ahc->scb_data->sense_busaddr
+ + (hscb->tag*sizeof(struct scsi_sense_data));
+ sg->len = MIN(sizeof(struct scsi_sense_data),
+ csio->sense_len);
+
sc->opcode = REQUEST_SENSE;
sc->byte2 = SCB_LUN(scb) << 5;
sc->unused[0] = 0;
sc->unused[1] = 0;
- sc->length = csio->sense_len;
+ sc->length = sg->len;
sc->control = 0;
- sg->addr = vtophys(&csio->sense_data);
- sg->len = csio->sense_len;
-
/*
* Would be nice to preserve DISCENB here,
* but due to the way we page SCBs, we can't.
@@ -1952,7 +2247,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
/*paused*/TRUE);
hscb->status = 0;
hscb->SG_count = 1;
- hscb->SG_pointer = scb->ahc_dmaphys;
+ hscb->SG_pointer = scb->sg_list_phys;
hscb->data = sg->addr;
hscb->datalen = sg->len;
hscb->cmdpointer = hscb->cmdstore_busaddr;
@@ -2032,7 +2327,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
u_int scb_index;
scb_index = ahc_inb(ahc, SCB_TAG);
- scb = ahc->scb_data->scbarray[scb_index];
+ scb = &ahc->scb_data->scbarray[scb_index];
if (bus_phase == P_MESGOUT)
ahc_setup_initiator_msgout(ahc,
@@ -2072,7 +2367,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
u_int lastphase = ahc_inb(ahc, LASTPHASE);
int i;
- scb = ahc->scb_data->scbarray[scbindex];
+ scb = &ahc->scb_data->scbarray[scbindex];
xpt_print_path(scb->ccb->ccb_h.path);
printf("data overrun detected in %s phase."
" Tag == 0x%x.\n",
@@ -2086,8 +2381,8 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
for (i = 0; i < scb->sg_count - 1; i++) {
printf("sg[%d] - Addr 0x%x : Length %d\n",
i,
- scb->ahc_dma[i].addr,
- scb->ahc_dma[i].len);
+ scb->sg_list[i].addr,
+ scb->sg_list[i].len);
}
}
/*
@@ -2095,7 +2390,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
* target does a command complete.
*/
ahc_freeze_devq(ahc, scb->ccb->ccb_h.path);
- ahc_set_ccb_status(scb->ccb, CAM_DATA_RUN_ERR);
+ ahcsetccbstatus(scb->ccb, CAM_DATA_RUN_ERR);
ahc_freeze_ccb(scb->ccb);
break;
}
@@ -2179,7 +2474,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
scb_index = ahc_inb(ahc, SCB_TAG);
if (scb_index < ahc->scb_data->numscbs) {
- scb = ahc->scb_data->scbarray[scb_index];
+ scb = &ahc->scb_data->scbarray[scb_index];
if ((scb->flags & SCB_ACTIVE) == 0)
scb = NULL;
} else
@@ -2221,8 +2516,8 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
scb->hscb->tag, tag == SCB_LIST_NULL ?
"" : "Tag");
if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
- ahc_set_ccb_status(scb->ccb,
- CAM_REQ_ABORTED);
+ ahcsetccbstatus(scb->ccb,
+ CAM_REQ_ABORTED);
ahc_done(ahc, scb);
}
printerror = 0;
@@ -2283,7 +2578,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
scb_index = ahc_inb(ahc, SCB_TAG);
if (scb_index < ahc->scb_data->numscbs) {
- scb = ahc->scb_data->scbarray[scb_index];
+ scb = &ahc->scb_data->scbarray[scb_index];
if ((scb->flags & SCB_ACTIVE) == 0)
scb = NULL;
} else
@@ -2531,7 +2826,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
int response = 0;
scb_index = ahc_inb(ahc, SCB_TAG);
- scb = ahc->scb_data->scbarray[scb_index];
+ scb = &ahc->scb_data->scbarray[scb_index];
/* Might be necessary */
last_msg = ahc_inb(ahc, LAST_MSG);
@@ -3181,7 +3476,7 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
struct scb *scb;
scb_index = ahc_inb(ahc, SCB_TAG);
- scb = ahc->scb_data->scbarray[scb_index];
+ scb = &ahc->scb_data->scbarray[scb_index];
if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0
|| (scb->ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_IN) {
/*
@@ -3227,18 +3522,18 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
sg_index = scb->sg_count - resid_sgcnt;
/*
- * scb->ahc_dma starts with the second S/G entry.
+ * scb->sg_list starts with the second S/G entry.
*/
if (sg_index-- != 0
- && (scb->ahc_dma[sg_index].len < data_cnt)) {
+ && (scb->sg_list[sg_index].len < data_cnt)) {
u_int sg_addr;
data_cnt = 1;
- data_addr = scb->ahc_dma[sg_index - 1].addr
- + scb->ahc_dma[sg_index - 1].len - 1;
+ data_addr = scb->sg_list[sg_index - 1].addr
+ + scb->sg_list[sg_index - 1].len - 1;
- sg_addr = scb->ahc_dmaphys
- + (sg_index * sizeof(*scb->ahc_dma));
+ sg_addr = scb->sg_list_phys
+ + (sg_index * sizeof(*scb->sg_list));
ahc_outb(ahc, SG_NEXT + 3, sg_addr >> 24);
ahc_outb(ahc, SG_NEXT + 2, sg_addr >> 16);
ahc_outb(ahc, SG_NEXT + 1, sg_addr >> 8);
@@ -3317,8 +3612,8 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
op = BUS_DMASYNC_POSTREAD;
else
op = BUS_DMASYNC_POSTWRITE;
- bus_dmamap_sync(ahc->dmat, scb->dmamap, op);
- bus_dmamap_unload(ahc->dmat, scb->dmamap);
+ bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op);
+ bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
}
/*
@@ -3330,7 +3625,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
ccb->ccb_h.status = CAM_REQ_CMP;
- ahc_free_scb(ahc, scb);
+ ahcfreescb(ahc, scb);
xpt_done(ccb);
return;
}
@@ -3367,7 +3662,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
SCB_LUN(scb), scb->hscb->tag, /*status*/0,
SEARCH_REMOVE);
if (ahc_ccb_status(ccb) == CAM_BDR_SENT)
- ahc_set_ccb_status(ccb, CAM_CMD_TIMEOUT);
+ ahcsetccbstatus(ccb, CAM_CMD_TIMEOUT);
xpt_print_path(ccb->ccb_h.path);
printf("no longer in timeout, status = %x\n",
ccb->ccb_h.status);
@@ -3377,11 +3672,24 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
if (ahc_ccb_status(ccb) == CAM_REQ_INPROG) {
ccb->ccb_h.status |= CAM_REQ_CMP;
} else if ((scb->flags & SCB_SENSE) != 0) {
- /* We performed autosense retrieval */
+ /*
+ * We performed autosense retrieval.
+ *
+ * bzero from the sense data before having
+ * the drive fill it. The SCSI spec mandates
+ * that any untransfered data should be
+ * assumed to be zero. Complete the 'bounce'
+ * of sense information through buffers accessible
+ * via bus-space by copying it into the clients
+ * csio.
+ */
+ bzero(&ccb->csio.sense_data, sizeof(ccb->csio.sense_data));
+ bcopy(&ahc->scb_data->sense[scb->hscb->tag],
+ &ccb->csio.sense_data, scb->sg_list->len);
scb->ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
}
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
- ahc_free_scb(ahc, scb);
+ ahcfreescb(ahc, scb);
xpt_done(ccb);
}
@@ -3411,14 +3719,16 @@ ahc_probe_scbs(struct ahc_softc *ahc) {
int
ahc_init(struct ahc_softc *ahc)
{
- int max_targ = 15;
- int i;
- int term;
- u_int scsi_conf;
- u_int scsiseq_template;
- u_int ultraenb;
- u_int discenable;
- u_int tagenable;
+ int max_targ = 15;
+ int i;
+ int term;
+ u_int scsi_conf;
+ u_int scsiseq_template;
+ u_int ultraenb;
+ u_int discenable;
+ u_int tagenable;
+ size_t driver_data_size;
+ u_int32_t physaddr;
#ifdef AHC_PRINT_SRAM
printf("Scratch Ram:");
@@ -3469,6 +3779,120 @@ ahc_init(struct ahc_softc *ahc)
ahc->flags &= ~AHC_INITIATORMODE;
}
+ /* DMA tag for mapping buffers into device visible space. */
+ if (bus_dma_tag_create(ahc->parent_dmat, /*alignment*/0, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/MAXBSIZE, /*nsegments*/AHC_NSEG,
+ /*maxsegsz*/AHC_MAXTRANSFER_SIZE,
+ /*flags*/BUS_DMA_ALLOCNOW,
+ &ahc->buffer_dmat) != 0) {
+ return (ENOMEM);
+ }
+
+ ahc->init_level++;
+
+ /*
+ * DMA tag for our command fifos and other data in system memory
+ * the card's sequencer must be able to access. For initiator
+ * roles, we need to allocate space for the qinfifo, qoutfifo,
+ * and untagged_scb arrays each of which are composed of 256
+ * 1 byte elements. When providing for the target mode role,
+ * we additionally must provide space for the incoming target
+ * command fifo.
+ */
+ driver_data_size = 3 * 256 * sizeof(u_int8_t);
+ if ((ahc->flags & AHC_TARGETMODE) != 0)
+ driver_data_size += AHC_TMODE_CMDS * sizeof(struct target_cmd);
+ if (bus_dma_tag_create(ahc->parent_dmat, /*alignment*/0, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ driver_data_size,
+ /*nsegments*/1,
+ /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
+ /*flags*/0, &ahc->shared_data_dmat) != 0) {
+ return (ENOMEM);
+ }
+
+ ahc->init_level++;
+
+ /* Allocation of driver data */
+ if (bus_dmamem_alloc(ahc->shared_data_dmat, (void **)&ahc->qoutfifo,
+ BUS_DMA_NOWAIT, &ahc->shared_data_dmamap) != 0) {
+ return (ENOMEM);
+ }
+
+ ahc->init_level++;
+
+ /* And permanently map it in */
+ bus_dmamap_load(ahc->shared_data_dmat, ahc->shared_data_dmamap,
+ ahc->qoutfifo, driver_data_size,
+ ahcdmamapcb, &ahc->shared_data_busaddr, /*flags*/0);
+
+ ahc->init_level++;
+
+ /* Allocate SCB data now that buffer_dmat is initialized) */
+ if (ahc->scb_data->maxhscbs == 0)
+ if (ahcinitscbdata(ahc) != 0)
+ return (ENOMEM);
+
+ ahc->qinfifo = &ahc->qoutfifo[256];
+ ahc->untagged_scbs = &ahc->qinfifo[256];
+ /* There are no untagged SCBs active yet. */
+ for (i = 0; i < 256; i++)
+ ahc->untagged_scbs[i] = SCB_LIST_NULL;
+
+ /* All of our queues are empty */
+ for (i = 0; i < 256; i++)
+ ahc->qoutfifo[i] = SCB_LIST_NULL;
+ ahc_outb(ahc, KERNEL_QINPOS, 0);
+ ahc_outb(ahc, QINPOS, 0);
+ ahc_outb(ahc, QOUTPOS, 0);
+
+ if ((ahc->flags & AHC_TARGETMODE) != 0) {
+ ahc->targetcmds = (struct target_cmd *)&ahc->untagged_scbs[256];
+
+ /* All target command blocks start out invalid. */
+ for (i = 0; i < AHC_TMODE_CMDS; i++)
+ ahc->targetcmds[i].cmd_valid = 0;
+ ahc_outb(ahc, KERNEL_TQINPOS, ahc->tqinfifonext - 1);
+ ahc_outb(ahc, TQINPOS, 0);
+ }
+
+ /*
+ * Tell the sequencer where it can find the our arrays in memory.
+ */
+ physaddr = ahc->scb_data->hscb_busaddr;
+ ahc_outb(ahc, HSCB_ADDR, physaddr & 0xFF);
+ ahc_outb(ahc, HSCB_ADDR + 1, (physaddr >> 8) & 0xFF);
+ ahc_outb(ahc, HSCB_ADDR + 2, (physaddr >> 16) & 0xFF);
+ ahc_outb(ahc, HSCB_ADDR + 3, (physaddr >> 24) & 0xFF);
+
+ physaddr = ahc->shared_data_busaddr;
+ ahc_outb(ahc, SCBID_ADDR, physaddr & 0xFF);
+ ahc_outb(ahc, SCBID_ADDR + 1, (physaddr >> 8) & 0xFF);
+ ahc_outb(ahc, SCBID_ADDR + 2, (physaddr >> 16) & 0xFF);
+ ahc_outb(ahc, SCBID_ADDR + 3, (physaddr >> 24) & 0xFF);
+
+ /* Target mode incomding command fifo */
+ physaddr += 3 * 256 * sizeof(u_int8_t);
+ ahc_outb(ahc, TMODE_CMDADDR, physaddr & 0xFF);
+ ahc_outb(ahc, TMODE_CMDADDR + 1, (physaddr >> 8) & 0xFF);
+ ahc_outb(ahc, TMODE_CMDADDR + 2, (physaddr >> 16) & 0xFF);
+ ahc_outb(ahc, TMODE_CMDADDR + 3, (physaddr >> 24) & 0xFF);
+
+ /* Initialize the group code to command length table */
+ ahc_outb(ahc, CMDSIZE_TABLE, 5);
+ ahc_outb(ahc, CMDSIZE_TABLE + 1, 9);
+ ahc_outb(ahc, CMDSIZE_TABLE + 2, 9);
+ ahc_outb(ahc, CMDSIZE_TABLE + 3, 0);
+ ahc_outb(ahc, CMDSIZE_TABLE + 4, 15);
+ ahc_outb(ahc, CMDSIZE_TABLE + 5, 11);
+ ahc_outb(ahc, CMDSIZE_TABLE + 6, 0);
+ ahc_outb(ahc, CMDSIZE_TABLE + 7, 0);
+
/*
* Allocate a tstate to house information for our
* initiator presence on the bus as well as the user
@@ -3500,46 +3924,10 @@ ahc_init(struct ahc_softc *ahc)
ahc_outb(ahc, SEQ_FLAGS, 0);
- /* Determine the number of SCBs and initialize them */
-
- if (ahc->scb_data->maxhscbs == 0) {
- ahc->scb_data->maxhscbs = ahc_probe_scbs(ahc);
- /* SCB 0 heads the free list */
- ahc_outb(ahc, FREE_SCBH, 0);
- for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
- ahc_outb(ahc, SCBPTR, i);
-
- /* Clear the control byte. */
- ahc_outb(ahc, SCB_CONTROL, 0);
-
- /* Set the next pointer */
- ahc_outb(ahc, SCB_NEXT, i+1);
-
- /* Make the tag number invalid */
- ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL);
- }
-
- /* Make that the last SCB terminates the free list */
- ahc_outb(ahc, SCBPTR, i-1);
- ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL);
-
- /* Ensure we clear the 0 SCB's control byte. */
- ahc_outb(ahc, SCBPTR, 0);
- ahc_outb(ahc, SCB_CONTROL, 0);
-
- ahc->scb_data->maxhscbs = i;
- }
-
- if (ahc->scb_data->maxhscbs == 0)
- panic("%s: No SCB space found", ahc_name(ahc));
-
if (ahc->scb_data->maxhscbs < AHC_SCB_MAX) {
ahc->flags |= AHC_PAGESCBS;
- ahc->scb_data->maxscbs = AHC_SCB_MAX;
- printf("%d/%d SCBs\n", ahc->scb_data->maxhscbs,
- ahc->scb_data->maxscbs);
+ printf("%d/%d SCBs\n", ahc->scb_data->maxhscbs, AHC_SCB_MAX);
} else {
- ahc->scb_data->maxscbs = ahc->scb_data->maxhscbs;
ahc->flags &= ~AHC_PAGESCBS;
printf("%d SCBs\n", ahc->scb_data->maxhscbs);
}
@@ -3722,111 +4110,6 @@ ahc_init(struct ahc_softc *ahc)
ahc->needsdtr_orig, ahc->needwdtr_orig,
discenable, ultraenb);
#endif
- /*
- * Allocate enough "hardware scbs" to handle
- * the maximum number of concurrent transactions
- * we can have active. We have to use contigmalloc
- * if this array crosses a page boundary since the
- * sequencer depends on this array being physically
- * contiguous.
- */
- if (ahc->scb_data->hscbs == NULL) {
- size_t array_size;
-
- array_size = ahc->scb_data->maxscbs*sizeof(struct hardware_scb);
- if (array_size > PAGE_SIZE) {
- ahc->scb_data->hscbs = (struct hardware_scb *)
- contigmalloc(array_size, M_DEVBUF,
- M_NOWAIT, 0ul, 0xffffffff,
- PAGE_SIZE, 0x10000);
- } else {
- ahc->scb_data->hscbs = (struct hardware_scb *)
- malloc(array_size, M_DEVBUF, M_NOWAIT);
- }
-
- if (ahc->scb_data->hscbs == NULL) {
- printf("%s: unable to allocate hardware SCB array. "
- "Failing attach\n", ahc_name(ahc));
- return (-1);
- }
- /* At least the control byte of each hscb needs to be zeroed */
- bzero(ahc->scb_data->hscbs, array_size);
- }
-
- if ((ahc->flags & AHC_TARGETMODE) != 0) {
- size_t array_size;
-
- array_size = AHC_TMODE_CMDS * sizeof(struct target_cmd);
- ahc->targetcmds = contigmalloc(array_size, M_DEVBUF,
- M_NOWAIT, 0ul, 0xffffffff,
- PAGE_SIZE, 0x10000);
-
- if (ahc->targetcmds == NULL) {
- printf("%s: unable to allocate targetcmd array. "
- "Failing attach\n", ahc_name(ahc));
- return (-1);
- }
-
- /* All target command blocks start out invalid. */
- for (i = 0; i < AHC_TMODE_CMDS; i++)
- ahc->targetcmds[i].cmd_valid = 0;
- ahc_outb(ahc, KERNEL_TQINPOS, ahc->tqinfifonext - 1);
- ahc_outb(ahc, TQINPOS, 0);
- }
-
- /*
- * Tell the sequencer where it can find the our arrays in memory.
- */
- {
- u_int32_t physaddr;
-
- /* Tell the sequencer where it can find the hscb array. */
- physaddr = vtophys(ahc->scb_data->hscbs);
- ahc_outb(ahc, HSCB_ADDR, physaddr & 0xFF);
- ahc_outb(ahc, HSCB_ADDR + 1, (physaddr >> 8) & 0xFF);
- ahc_outb(ahc, HSCB_ADDR + 2, (physaddr >> 16) & 0xFF);
- ahc_outb(ahc, HSCB_ADDR + 3, (physaddr >> 24) & 0xFF);
- ahc->hscb_busaddr = physaddr;
-
- physaddr = vtophys(ahc->qoutfifo);
- ahc_outb(ahc, SCBID_ADDR, physaddr & 0xFF);
- ahc_outb(ahc, SCBID_ADDR + 1, (physaddr >> 8) & 0xFF);
- ahc_outb(ahc, SCBID_ADDR + 2, (physaddr >> 16) & 0xFF);
- ahc_outb(ahc, SCBID_ADDR + 3, (physaddr >> 24) & 0xFF);
-
- if ((ahc->flags & AHC_TARGETMODE) != 0) {
- physaddr = vtophys(ahc->targetcmds);
- ahc_outb(ahc, TMODE_CMDADDR, physaddr & 0xFF);
- ahc_outb(ahc, TMODE_CMDADDR + 1,
- (physaddr >> 8) & 0xFF);
- ahc_outb(ahc, TMODE_CMDADDR + 2,
- (physaddr >> 16) & 0xFF);
- ahc_outb(ahc, TMODE_CMDADDR + 3,
- (physaddr >> 24) & 0xFF);
-
- ahc_outb(ahc, CMDSIZE_TABLE, 5);
- ahc_outb(ahc, CMDSIZE_TABLE + 1, 9);
- ahc_outb(ahc, CMDSIZE_TABLE + 2, 9);
- ahc_outb(ahc, CMDSIZE_TABLE + 3, 0);
- ahc_outb(ahc, CMDSIZE_TABLE + 4, 15);
- ahc_outb(ahc, CMDSIZE_TABLE + 5, 11);
- ahc_outb(ahc, CMDSIZE_TABLE + 6, 0);
- ahc_outb(ahc, CMDSIZE_TABLE + 7, 0);
- }
-
- /* There are no untagged SCBs active yet. */
- for (i = 0; i < sizeof(ahc->untagged_scbs); i++) {
- ahc->untagged_scbs[i] = SCB_LIST_NULL;
- }
- for (i = 0; i < sizeof(ahc->qoutfifo); i++) {
- ahc->qoutfifo[i] = SCB_LIST_NULL;
- }
- }
-
- /* Our Q FIFOs are empty. */
- ahc_outb(ahc, KERNEL_QINPOS, 0);
- ahc_outb(ahc, QINPOS, 0);
- ahc_outb(ahc, QOUTPOS, 0);
/* Don't have any special messages to send to targets */
ahc_outb(ahc, TARGET_MSG_REQUEST, 0);
@@ -4028,14 +4311,14 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
/*
* get an scb to use.
*/
- if ((scb = ahc_get_scb(ahc)) == NULL) {
+ if ((scb = ahcgetscb(ahc)) == NULL) {
int s;
s = splcam();
ahc->flags |= AHC_RESOURCE_SHORTAGE;
splx(s);
xpt_freeze_simq(ahc->sim, /*count*/1);
- ahc_set_ccb_status(ccb, CAM_REQUEUE_REQ);
+ ahcsetccbstatus(ccb, CAM_REQUEUE_REQ);
xpt_done(ccb);
return;
}
@@ -4434,13 +4717,13 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
end_seg = dm_segs + nsegments;
/* Copy the first SG into the data pointer area */
- scb->hscb->SG_pointer = scb->ahc_dmaphys;
+ scb->hscb->SG_pointer = scb->sg_list_phys;
scb->hscb->data = dm_segs->ds_addr;
scb->hscb->datalen = dm_segs->ds_len;
dm_segs++;
/* Copy the remaining segments into our SG list */
- sg = scb->ahc_dma;
+ sg = scb->sg_list;
while (dm_segs < end_seg) {
sg->addr = dm_segs->ds_addr;
sg->len = dm_segs->ds_len;
@@ -4453,7 +4736,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
else
op = BUS_DMASYNC_PREWRITE;
- bus_dmamap_sync(ahc->dmat, scb->dmamap, op);
+ bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op);
if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
scb->hscb->cmdpointer |= DPHASE_PENDING;
@@ -4476,8 +4759,8 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
*/
if (ahc_ccb_status(ccb) != CAM_REQ_INPROG) {
if (nsegments != 0)
- bus_dmamap_unload(ahc->dmat, scb->dmamap);
- ahc_free_scb(ahc, scb);
+ bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
+ ahcfreescb(ahc, scb);
xpt_done(ccb);
splx(s);
return;
@@ -4550,12 +4833,16 @@ ahc_setup_data(struct ahc_softc *ahc, struct ccb_scsiio *csio,
hscb->cmdlen);
hscb->cmdpointer =
hscb->cmdstore_busaddr;
- } else
- hscb->cmdpointer =
- vtophys(csio->cdb_io.cdb_ptr);
+ } else {
+ ahcsetccbstatus(scb->ccb,
+ CAM_REQ_INVALID);
+ xpt_done(scb->ccb);
+ ahcfreescb(ahc, scb);
+ return;
+ }
else
hscb->cmdpointer =
- (u_int32_t)csio->cdb_io.cdb_ptr;
+ ((intptr_t)csio->cdb_io.cdb_ptr) & 0xffffffff;
} else {
/*
* CCB CDB Data Storage area is only 16 bytes
@@ -4576,7 +4863,7 @@ ahc_setup_data(struct ahc_softc *ahc, struct ccb_scsiio *csio,
int error;
s = splsoftvm();
- error = bus_dmamap_load(ahc->dmat,
+ error = bus_dmamap_load(ahc->buffer_dmat,
scb->dmamap,
csio->data_ptr,
csio->dxfer_len,
@@ -4643,124 +4930,67 @@ ahc_freeze_devq(struct ahc_softc *ahc, struct cam_path *path)
SEARCH_COMPLETE);
}
-/*
- * An scb (and hence an scb entry on the board) is put onto the
- * free list.
- */
static void
-ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
-{
- struct hardware_scb *hscb;
- int opri;
-
- hscb = scb->hscb;
-
- opri = splcam();
+ahcallocscbs(struct ahc_softc *ahc)
+{
+ struct scb_data *scb_data;
+ struct scb *next_scb;
+ struct sg_map_node *sg_map;
+ bus_addr_t physaddr;
+ struct ahc_dma_seg *segs;
+ int newcount;
+ int i;
- if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0
- && (scb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
- scb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
- ahc->flags &= ~AHC_RESOURCE_SHORTAGE;
- }
+ scb_data = ahc->scb_data;
+ if (scb_data->numscbs >= AHC_SCB_MAX)
+ /* Can't allocate any more */
+ return;
- /* Clean up for the next user */
- scb->flags = SCB_FREE;
- hscb->control = 0;
- hscb->status = 0;
+ next_scb = &scb_data->scbarray[scb_data->numscbs];
- STAILQ_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links);
- splx(opri);
-}
+ sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
-/*
- * Get a free scb, either one already assigned to a hardware slot
- * on the adapter or one that will require an SCB to be paged out before
- * use. If there are none, see if we can allocate a new SCB. Otherwise
- * either return an error or sleep.
- */
-static struct scb *
-ahc_get_scb(struct ahc_softc *ahc)
-{
- struct scb *scbp;
- int opri;
+ if (sg_map == NULL)
+ return;
- opri = splcam();
- if ((scbp = STAILQ_FIRST(&ahc->scb_data->free_scbs))) {
- STAILQ_REMOVE_HEAD(&ahc->scb_data->free_scbs, links);
- } else if (ahc->scb_data->numscbs < ahc->scb_data->maxscbs) {
- scbp = ahc_alloc_scb(ahc);
- if (scbp == NULL)
- printf("%s: Can't malloc SCB\n", ahc_name(ahc));
+ /* Allocate S/G space for the next batch of SCBS */
+ if (bus_dmamem_alloc(scb_data->sg_dmat, (void **)&sg_map->sg_vaddr,
+ BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
+ free(sg_map, M_DEVBUF);
+ return;
}
- splx(opri);
+ SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
- return (scbp);
-}
+ bus_dmamap_load(scb_data->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr,
+ PAGE_SIZE, ahcdmamapcb, &sg_map->sg_physaddr,
+ /*flags*/0);
+ segs = sg_map->sg_vaddr;
+ physaddr = sg_map->sg_physaddr;
-static struct scb *
-ahc_alloc_scb(struct ahc_softc *ahc)
-{
- static struct ahc_dma_seg *next_sg_array = NULL;
- static int sg_arrays_free = 0;
- struct scb *newscb;
- int error;
-
- newscb = (struct scb *) malloc(sizeof(struct scb), M_DEVBUF, M_NOWAIT);
- if (newscb != NULL) {
- bzero(newscb, sizeof(struct scb));
- error = bus_dmamap_create(ahc->dmat, /*flags*/0,
- &newscb->dmamap);
+ newcount = (PAGE_SIZE / (AHC_NSEG * sizeof(struct ahc_dma_seg)));
+ for (i = 0; scb_data->numscbs < AHC_SCB_MAX && i < newcount; i++) {
+ int error;
+
+ next_scb->sg_list = segs;
+ next_scb->sg_list_phys = physaddr;
+ next_scb->flags = SCB_FREE;
+ error = bus_dmamap_create(ahc->buffer_dmat, /*flags*/0,
+ &next_scb->dmamap);
if (error != 0)
- printf("%s: Unable to allocate SCB dmamap - error %d\n",
- ahc_name(ahc), error);
-
- if (error == 0 && next_sg_array == NULL) {
- size_t alloc_size = sizeof(struct ahc_dma_seg)
- * AHC_NSEG;
- sg_arrays_free = PAGE_SIZE / alloc_size;
- alloc_size *= sg_arrays_free;
- if (alloc_size == 0)
- panic("%s: SG list doesn't fit in a page",
- ahc_name(ahc));
- next_sg_array = (struct ahc_dma_seg *)
- malloc(alloc_size, M_DEVBUF, M_NOWAIT);
- }
- if (error == 0 && next_sg_array != NULL) {
- struct hardware_scb *hscb;
-
- newscb->ahc_dma = next_sg_array;
- newscb->ahc_dmaphys = vtophys(next_sg_array);
- sg_arrays_free--;
- if (sg_arrays_free == 0)
- next_sg_array = NULL;
- else
- next_sg_array = &next_sg_array[AHC_NSEG];
- hscb = &ahc->scb_data->hscbs[ahc->scb_data->numscbs];
- newscb->hscb = hscb;
- hscb->control = 0;
- hscb->status = 0;
- hscb->tag = ahc->scb_data->numscbs;
- hscb->residual_data_count[2] = 0;
- hscb->residual_data_count[1] = 0;
- hscb->residual_data_count[0] = 0;
- hscb->residual_SG_count = 0;
- hscb->cmdstore_busaddr =
- ahc_hscb_busaddr(ahc, hscb->tag)
- + offsetof(struct hardware_scb, cmdstore);
- /*
- * Place in the scbarray
- * Never is removed.
- */
- ahc->scb_data->scbarray[hscb->tag] = newscb;
- ahc->scb_data->numscbs++;
- } else {
- free(newscb, M_DEVBUF);
- newscb = NULL;
- }
+ break;
+ next_scb->hscb = &scb_data->hscbs[scb_data->numscbs];
+ next_scb->hscb->tag = ahc->scb_data->numscbs;
+ next_scb->hscb->cmdstore_busaddr =
+ ahc_hscb_busaddr(ahc, next_scb->hscb->tag)
+ + offsetof(struct hardware_scb, cmdstore);
+ SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, next_scb, links);
+ segs += AHC_NSEG;
+ physaddr += (AHC_NSEG * sizeof(struct ahc_dma_seg));
+ next_scb++;
+ ahc->scb_data->numscbs++;
}
- return newscb;
}
static void
@@ -5082,7 +5312,7 @@ ahc_timeout(void *arg)
* Do a full bus reset.
*/
bus_reset:
- ahc_set_ccb_status(scb->ccb, CAM_CMD_TIMEOUT);
+ ahcsetccbstatus(scb->ccb, CAM_CMD_TIMEOUT);
found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE);
printf("%s: Issued Channel %c Bus Reset. "
"%d SCBs aborted\n", ahc_name(ahc), channel, found);
@@ -5123,7 +5353,7 @@ bus_reset:
* and wait for it's timeout to expire before
* taking additional action.
*/
- active_scb = ahc->scb_data->scbarray[active_scb_index];
+ active_scb = &ahc->scb_data->scbarray[active_scb_index];
if (active_scb->hscb->tcl != scb->hscb->tcl
&& (scb->flags & SCB_OTHERTCL_TIMEOUT) == 0) {
struct ccb_hdr *ccbh;
@@ -5150,7 +5380,7 @@ bus_reset:
* and properly record the error condition.
*/
ahc_freeze_devq(ahc, scb->ccb->ccb_h.path);
- ahc_set_ccb_status(scb->ccb, CAM_CMD_TIMEOUT);
+ ahcsetccbstatus(scb->ccb, CAM_CMD_TIMEOUT);
ahc_freeze_ccb(scb->ccb);
ahc_done(ahc, scb);
@@ -5273,7 +5503,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
ahc->qinfifonext = qinpos;
while (qinpos != qintail) {
- scbp = ahc->scb_data->scbarray[ahc->qinfifo[qinpos]];
+ scbp = &ahc->scb_data->scbarray[ahc->qinfifo[qinpos]];
if (ahc_match_scb(scbp, target, channel, lun, tag)) {
/*
* We found an scb that needs to be removed.
@@ -5281,7 +5511,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
switch (action) {
case SEARCH_COMPLETE:
if (ahc_ccb_status(scbp->ccb) == CAM_REQ_INPROG)
- ahc_set_ccb_status(scbp->ccb, status);
+ ahcsetccbstatus(scbp->ccb, status);
ahc_freeze_ccb(scbp->ccb);
ahc_done(ahc, scbp);
break;
@@ -5431,7 +5661,7 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
"SCB index == %d, yet numscbs == %d.",
scb_index, ahc->scb_data->numscbs);
}
- scbp = ahc->scb_data->scbarray[scb_index];
+ scbp = &ahc->scb_data->scbarray[scb_index];
if (ahc_match_scb(scbp, target, channel, lun, tag)) {
next = ahc_abort_wscb(ahc, next, prev);
@@ -5458,7 +5688,7 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
ahc_outb(ahc, SCBPTR, i);
scbid = ahc_inb(ahc, SCB_TAG);
if (scbid < ahc->scb_data->numscbs) {
- scbp = ahc->scb_data->scbarray[scbid];
+ scbp = &ahc->scb_data->scbarray[scbid];
if (ahc_match_scb(scbp, target, channel, lun, tag)) {
ahc_add_curscb_to_free_list(ahc);
}
@@ -5481,7 +5711,7 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
ccb_h = ccb_h->sim_links.le.le_next;
if (ahc_match_scb(scbp, target, channel, lun, tag)) {
if (ahc_ccb_status(scbp->ccb) == CAM_REQ_INPROG)
- ahc_set_ccb_status(scbp->ccb, status);
+ ahcsetccbstatus(scbp->ccb, status);
ahc_freeze_ccb(scbp->ccb);
ahc_done(ahc, scbp);
found++;
@@ -5519,7 +5749,7 @@ ahc_search_disc_list(struct ahc_softc *ahc, int target, char channel,
"SCB index == %d, yet numscbs == %d.",
scb_index, ahc->scb_data->numscbs);
}
- scbp = ahc->scb_data->scbarray[scb_index];
+ scbp = &ahc->scb_data->scbarray[scb_index];
if (ahc_match_scb(scbp, target, channel, lun, tag)) {
next = ahc_rem_scb_from_disc_list(ahc, prev,
next);
@@ -5806,7 +6036,7 @@ ahc_calc_residual(struct scb *scb)
sg = scb->sg_count - resid_sgs - 1/*first SG*/;
while (resid_sgs > 0) {
- resid += scb->ahc_dma[sg].len;
+ resid += scb->sg_list[sg].len;
sg++;
resid_sgs--;
}
@@ -5905,7 +6135,7 @@ ahc_update_pending_syncrates(struct ahc_softc *ahc)
u_int our_id, remote_id;
u_int control;
- pending_scb = ahc->scb_data->scbarray[scb_tag];
+ pending_scb = &ahc->scb_data->scbarray[scb_tag];
if (pending_scb->flags == SCB_FREE)
continue;
pending_hscb = pending_scb->hscb;
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index cf3037a..5f1bb86 100644
--- a/sys/dev/aic7xxx/aic7xxx.h
+++ b/sys/dev/aic7xxx/aic7xxx.h
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.h,v 1.5 1999/01/14 06:14:15 gibbs Exp $
+ * $Id: aic7xxx.h,v 1.6 1999/03/05 23:35:47 gibbs Exp $
*/
#ifndef _AIC7XXX_H_
@@ -43,22 +43,31 @@
#include "ahc.h" /* for NAHC from config */
#include "opt_aic7xxx.h" /* for config options */
-#include <pci/pcivar.h> /* for pcici_t */
+#include <sys/bus.h> /* For device_t */
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+/*
+ * The maximum transfer per S/G segment.
+ */
#define AHC_MAXTRANSFER_SIZE 0x00ffffff /* limited by 24bit counter */
-#define AHC_NSEG 32 /* The number of dma segments supported.
- * AHC_NSEG can be maxed out at 256 entries,
- * but the kernel will never need to transfer
- * such a large (1MB) request. To reduce the
- * driver's memory consumption, we reduce the
- * max to 32. 16 would work if all transfers
- * are paged alined since the kernel will only
- * generate at most a 64k transfer, but to
- * handle non-page aligned transfers, you need
- * 17, so we round to the next power of two
- * to make allocating SG space easy and
- * efficient.
- */
+
+/*
+ * The number of dma segments supported. The current implementation limits
+ * us to 255 S/G entries (this may change to be unlimited at some point).
+ * To reduce the driver's memory consumption, we further limit the number
+ * supported to be sufficient to handle the largest mapping supported by
+ * the kernel, MAXPHYS. Assuming the transfer is as fragmented as possible
+ * and unaligned, this turns out to be the number of paged sized transfers
+ * in MAXPHYS plus an extra element to handle any unaligned residual.
+ */
+#define AHC_NSEG (MIN(btoc(MAXPHYS) + 1, 255))
#define AHC_SCB_MAX 255 /*
* Up to 255 SCBs on some types of aic7xxx
@@ -75,10 +84,6 @@
* wrap point of an 8bit counter.
*/
-#if defined(__FreeBSD__)
-extern u_long ahc_unit;
-#endif
-
struct ahc_dma_seg {
u_int32_t addr;
u_int32_t len;
@@ -138,7 +143,6 @@ typedef enum {
* SRAM, we use the default target
* settings.
*/
- AHC_INDIRECT_PAGING = 0x008,
AHC_SHARED_SRAM = 0x010,
AHC_LARGE_SEEPROM = 0x020,/* Uses C56_66 not C46 */
AHC_RESET_BUS_A = 0x040,
@@ -228,28 +232,13 @@ struct hardware_scb {
struct scb {
struct hardware_scb *hscb;
- STAILQ_ENTRY(scb) links; /* for chaining */
+ SLIST_ENTRY(scb) links; /* for chaining */
union ccb *ccb; /* the ccb for this cmd */
- scb_flag flags;
- bus_dmamap_t dmamap;
- struct ahc_dma_seg *ahc_dma;/* Pointer to SG segments */
- u_int32_t ahc_dmaphys;/* Phsical address of SG list */
- u_int sg_count;/* How full ahc_dma_seg is */
-};
-
-struct scb_data {
- struct hardware_scb *hscbs; /* Array of hardware SCBs */
- struct scb *scbarray[AHC_SCB_MAX]; /* Array of kernel SCBs */
- STAILQ_HEAD(, scb) free_scbs; /*
- * Pool of SCBs ready to be assigned
- * commands to execute.
- */
- u_int8_t numscbs;
- u_int8_t maxhscbs; /* Number of SCBs on the card */
- u_int8_t maxscbs; /*
- * Max SCBs we allocate total including
- * any that will force us to page SCBs
- */
+ scb_flag flags;
+ bus_dmamap_t dmamap;
+ struct ahc_dma_seg *sg_list;
+ bus_addr_t sg_list_phys;
+ u_int sg_count;/* How full ahc_dma_seg is */
};
/*
@@ -402,10 +391,45 @@ typedef enum {
MSG_TYPE_TARGET_MSGIN = 0x04
} ahc_msg_type;
+struct sg_map_node {
+ bus_dmamap_t sg_dmamap;
+ bus_addr_t sg_physaddr;
+ struct ahc_dma_seg* sg_vaddr;
+ SLIST_ENTRY(sg_map_node) links;
+};
+
+struct scb_data {
+ struct hardware_scb *hscbs; /* Array of hardware SCBs */
+ struct scb *scbarray; /* Array of kernel SCBs */
+ SLIST_HEAD(, scb) free_scbs; /*
+ * Pool of SCBs ready to be assigned
+ * commands to execute.
+ */
+ struct scsi_sense_data *sense; /* Per SCB sense data */
+
+ /*
+ * "Bus" addresses of our data structures.
+ */
+ bus_dma_tag_t hscb_dmat; /* dmat for our hardware SCB array */
+ bus_dmamap_t hscb_dmamap;
+ bus_addr_t hscb_busaddr;
+ bus_dma_tag_t sense_dmat;
+ bus_dmamap_t sense_dmamap;
+ bus_addr_t sense_busaddr;
+ bus_dma_tag_t sg_dmat; /* dmat for our sg segments */
+ SLIST_HEAD(, sg_map_node) sg_maps;
+ u_int8_t numscbs;
+ u_int8_t maxhscbs; /* Number of SCBs on the card */
+ u_int8_t init_level; /*
+ * How far we've initialized
+ * this structure.
+ */
+};
+
struct ahc_softc {
bus_space_tag_t tag;
bus_space_handle_t bsh;
- bus_dma_tag_t dmat;
+ bus_dma_tag_t buffer_dmat; /* dmat for buffer I/O */
struct scb_data *scb_data;
/*
@@ -447,14 +471,14 @@ struct ahc_softc {
/* Command Queues */
u_int8_t qoutfifonext;
u_int8_t qinfifonext;
- u_int8_t qoutfifo[256];
- u_int8_t qinfifo[256];
+ u_int8_t *qoutfifo;
+ u_int8_t *qinfifo;
/*
* 256 byte array storing the SCBID of outstanding
* untagged SCBs indexed by TCL.
*/
- u_int8_t untagged_scbs[256];
+ u_int8_t *untagged_scbs;
/*
* Hooks into the XPT.
@@ -482,7 +506,7 @@ struct ahc_softc {
* PCI error interrupt handler.
*/
int unsolicited_ints;
- pcici_t pci_config_id;
+ device_t device;
/*
* Target incoming command FIFO.
@@ -501,13 +525,22 @@ struct ahc_softc {
u_int msgout_index; /* Current index in msgout */
u_int msgin_index; /* Current index in msgin */
+ int regs_res_type;
+ int regs_res_id;
+ int irq_res_type;
+ struct resource *regs;
+ struct resource *irq;
+ void *ih;
+ bus_dma_tag_t parent_dmat;
+ bus_dma_tag_t shared_data_dmat;
+ bus_dmamap_t shared_data_dmamap;
+ bus_addr_t shared_data_busaddr;
+
/* Number of enabled target mode device on this card */
u_int enabled_luns;
- /*
- * "Bus" addresses of our data structures.
- */
- u_int32_t hscb_busaddr;
+ /* Initialization level of this data structure */
+ u_int init_level;
};
struct full_ahc_softc {
@@ -530,10 +563,11 @@ extern int ahc_debug; /* Initialized in i386/scsi/aic7xxx.c */
char *ahc_name(struct ahc_softc *ahc);
-struct ahc_softc *ahc_alloc(int unit, u_int32_t io_base,
- vm_offset_t maddr, ahc_chip chip,
- ahc_feature features, ahc_flag flags,
- struct scb_data *scb_data);
+struct ahc_softc*
+ ahc_alloc(device_t dev, struct resource *regs, int regs_type,
+ int regs_id, bus_dma_tag_t parent_dmat, ahc_chip chip,
+ ahc_feature features, ahc_flag flags,
+ struct scb_data *scb_data);
int ahc_reset(struct ahc_softc *ahc);
void ahc_free(struct ahc_softc *);
int ahc_probe_scbs(struct ahc_softc *);
diff --git a/sys/dev/aic7xxx/aicasm/aicasm_symbol.c b/sys/dev/aic7xxx/aicasm/aicasm_symbol.c
index f808e89..0704baa 100644
--- a/sys/dev/aic7xxx/aicasm/aicasm_symbol.c
+++ b/sys/dev/aic7xxx/aicasm/aicasm_symbol.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aicasm_symbol.c,v 1.4 1997/09/27 19:37:30 gibbs Exp $
+ * $Id: aicasm_symbol.c,v 1.5 1998/09/15 07:24:17 gibbs Exp $
*/
@@ -128,10 +128,10 @@ symtable_close()
DBT data;
while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
- symbol_t *cursym;
+ symbol_t *stored_ptr;
- cursym = *(symbol_t **)data.data;
- symbol_delete(cursym);
+ memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
+ symbol_delete(stored_ptr);
}
symtable->close(symtable);
}
@@ -145,9 +145,10 @@ symbol_t *
symtable_get(name)
char *name;
{
- DBT key;
- DBT data;
- int retval;
+ symbol_t *stored_ptr;
+ DBT key;
+ DBT data;
+ int retval;
key.data = (void *)name;
key.size = strlen(name);
@@ -176,7 +177,8 @@ symtable_get(name)
/* NOTREACHED */
}
}
- return (*(symbol_t **)data.data);
+ memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
+ return (stored_ptr);
}
symbol_node_t *
@@ -327,7 +329,7 @@ symtable_dump(ofile)
while (symtable->seq(symtable, &key, &data, flag) == 0) {
symbol_t *cursym;
- cursym = *(symbol_t **)data.data;
+ memcpy(&cursym, data.data, sizeof(cursym));
switch(cursym->type) {
case REGISTER:
case SCBLOC:
diff --git a/sys/dev/aic7xxx/aicasm_symbol.c b/sys/dev/aic7xxx/aicasm_symbol.c
index f808e89..0704baa 100644
--- a/sys/dev/aic7xxx/aicasm_symbol.c
+++ b/sys/dev/aic7xxx/aicasm_symbol.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aicasm_symbol.c,v 1.4 1997/09/27 19:37:30 gibbs Exp $
+ * $Id: aicasm_symbol.c,v 1.5 1998/09/15 07:24:17 gibbs Exp $
*/
@@ -128,10 +128,10 @@ symtable_close()
DBT data;
while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
- symbol_t *cursym;
+ symbol_t *stored_ptr;
- cursym = *(symbol_t **)data.data;
- symbol_delete(cursym);
+ memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
+ symbol_delete(stored_ptr);
}
symtable->close(symtable);
}
@@ -145,9 +145,10 @@ symbol_t *
symtable_get(name)
char *name;
{
- DBT key;
- DBT data;
- int retval;
+ symbol_t *stored_ptr;
+ DBT key;
+ DBT data;
+ int retval;
key.data = (void *)name;
key.size = strlen(name);
@@ -176,7 +177,8 @@ symtable_get(name)
/* NOTREACHED */
}
}
- return (*(symbol_t **)data.data);
+ memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
+ return (stored_ptr);
}
symbol_node_t *
@@ -327,7 +329,7 @@ symtable_dump(ofile)
while (symtable->seq(symtable, &key, &data, flag) == 0) {
symbol_t *cursym;
- cursym = *(symbol_t **)data.data;
+ memcpy(&cursym, data.data, sizeof(cursym));
switch(cursym->type) {
case REGISTER:
case SCBLOC:
OpenPOWER on IntegriCloud