/* use bounce buffer if the physical address is bad */ if (addr & wh->dma_xfer_mask) { /* drop useless mapping */
dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
scsi_pointer->this_residual,
DMA_DIR(dir_in));
scsi_pointer->dma_handle = (dma_addr_t) NULL;
if (scsi_alloc_out_of_range ||
!wh->dma_bounce_buffer) {
wh->dma_bounce_buffer =
amiga_chip_alloc(wh->dma_bounce_len, "GVP II SCSI Bounce Buffer");
if (!wh->dma_bounce_buffer) {
wh->dma_bounce_len = 0; return1;
}
wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
}
if (!dir_in) { /* copy to bounce buffer for a write */
memcpy(wh->dma_bounce_buffer, scsi_pointer->ptr,
scsi_pointer->this_residual);
}
if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) { /* will flush/invalidate cache for us */
addr = dma_map_single(hdata->dev,
wh->dma_bounce_buffer,
wh->dma_bounce_len,
DMA_DIR(dir_in)); /* can't map buffer; use PIO */ if (dma_mapping_error(hdata->dev, addr)) {
dev_warn(hdata->dev, "cannot map bounce buffer %p\n",
wh->dma_bounce_buffer); return1;
}
}
if (addr & wh->dma_xfer_mask) { /* drop useless mapping */
dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
scsi_pointer->this_residual,
DMA_DIR(dir_in)); /* fall back to Chip RAM if address out of range */ if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) {
kfree(wh->dma_bounce_buffer);
scsi_alloc_out_of_range = 1;
} else {
amiga_chip_free(wh->dma_bounce_buffer);
}
wh->dma_bounce_buffer =
amiga_chip_alloc(wh->dma_bounce_len, "GVP II SCSI Bounce Buffer");
if (!wh->dma_bounce_buffer) {
wh->dma_bounce_len = 0; return1;
}
if (!dir_in) { /* copy to bounce buffer for a write */
memcpy(wh->dma_bounce_buffer, scsi_pointer->ptr,
scsi_pointer->this_residual);
} /* chip RAM can be mapped to phys. address directly */
addr = virt_to_phys(wh->dma_bounce_buffer); /* no need to flush/invalidate cache */
wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
} /* finally, have OK mapping (punted for PIO else) */
scsi_pointer->dma_handle = addr;
}
/* setup dma direction */ if (!dir_in)
cntr |= GVP11_DMAC_DIR_WRITE;
/* stop DMA */
regs->SP_DMA = 1; /* remove write bit from CONTROL bits */
regs->CNTR = GVP11_DMAC_INT_ENABLE;
if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED)
dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
scsi_pointer->this_residual,
DMA_DIR(wh->dma_dir));
/* copy from a bounce buffer, if necessary */ if (status && wh->dma_bounce_buffer) { if (wh->dma_dir && SCpnt)
memcpy(scsi_pointer->ptr, wh->dma_bounce_buffer,
scsi_pointer->this_residual);
if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED)
kfree(wh->dma_bounce_buffer); else
amiga_chip_free(wh->dma_bounce_buffer);
q = *sasr_3393; /* read it */ if (q & 0x08) /* bit 3 should always be clear */ return -ENODEV;
*sasr_3393 = WD_AUXILIARY_STATUS; /* setup indirect address */ if (*sasr_3393 == WD_AUXILIARY_STATUS) { /* shouldn't retain the write */
*sasr_3393 = save_sasr; /* Oops - restore this byte */ return -ENODEV;
} if (*sasr_3393 != q) { /* should still read the same */
*sasr_3393 = save_sasr; /* Oops - restore this byte */ return -ENODEV;
} if (*scmd_3393 != q) /* and so should the image at 0x1f */ return -ENODEV;