Beispiel #1
0
void 
ata_dmainit(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);
    struct ata_dc_cb_args dcba;

    if (ch->dma.alloc == NULL)
	ch->dma.alloc = ata_dmaalloc;
    if (ch->dma.free == NULL)
	ch->dma.free = ata_dmafree;
    if (ch->dma.setprd == NULL)
	ch->dma.setprd = ata_dmasetprd;
    if (ch->dma.load == NULL)
	ch->dma.load = ata_dmaload;
    if (ch->dma.unload == NULL)
	ch->dma.unload = ata_dmaunload;
    if (ch->dma.alignment == 0)
	ch->dma.alignment = 2;
    if (ch->dma.boundary == 0)
	ch->dma.boundary = 65536;
    if (ch->dma.segsize == 0)
	ch->dma.segsize = 65536;
    if (ch->dma.max_iosize == 0)
	ch->dma.max_iosize = MIN((ATA_DMA_ENTRIES - 1) * PAGE_SIZE, MAXPHYS);
    if (ch->dma.max_address == 0)
	ch->dma.max_address = BUS_SPACE_MAXADDR_32BIT;
    if (ch->dma.dma_slots == 0)
	ch->dma.dma_slots = 1;

    if (bus_dma_tag_create(bus_get_dma_tag(dev), ch->dma.alignment, 0,
			   ch->dma.max_address, BUS_SPACE_MAXADDR,
			   NULL, NULL, ch->dma.max_iosize,
			   ATA_DMA_ENTRIES, ch->dma.segsize,
			   0, NULL, NULL, &ch->dma.dmatag))
	goto error;

    if (bus_dma_tag_create(ch->dma.dmatag, PAGE_SIZE, 64 * 1024,
			   ch->dma.max_address, BUS_SPACE_MAXADDR,
			   NULL, NULL, MAXWSPCSZ, 1, MAXWSPCSZ,
			   0, NULL, NULL, &ch->dma.work_tag))
	goto error;

    if (bus_dmamem_alloc(ch->dma.work_tag, (void **)&ch->dma.work,
			 BUS_DMA_WAITOK | BUS_DMA_COHERENT,
			 &ch->dma.work_map))
	goto error;

    if (bus_dmamap_load(ch->dma.work_tag, ch->dma.work_map, ch->dma.work,
			MAXWSPCSZ, ata_dmasetupc_cb, &dcba, 0) ||
			dcba.error) {
	bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
	goto error;
    }
    ch->dma.work_bus = dcba.maddr;
    return;

error:
    device_printf(dev, "WARNING - DMA initialization failed, disabling DMA\n");
    ata_dmafini(dev);
}
Beispiel #2
0
static int
sata_channel_detach(device_t dev)
{
	struct sata_softc *sc;
	struct ata_channel *ch;
	int error;

	sc = device_get_softc(device_get_parent(dev));
	ch = device_get_softc(dev);

	if (!ch->attached)
		return (0);

	/* Turn off EDMA engine */
	sata_edma_ctrl(dev, 0);

	/* Mask chanel interrupts */
	SATA_OUTL(sc, SATA_EDMA_IEMR(ch->unit), 0);
	SATA_OUTL(sc, SATA_MIMR, SATA_INL(sc, SATA_MIMR) & ~(
	    SATA_MICR_DONE(ch->unit) | SATA_MICR_DMADONE(ch->unit) |
	    SATA_MICR_ERR(ch->unit)));

	error = ata_detach(dev);
	ata_dmafini(dev);

	ch->attached = 0;

	return (error);
}
Beispiel #3
0
static int
ata_siiprb_ch_detach(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);

    if (ch->dma.work_tag && ch->dma.work_map)
	bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
	    BUS_DMASYNC_POSTWRITE);
    ata_dmafini(dev);
    return 0;
}
Beispiel #4
0
void
ata_pci_dmafini(device_t dev)
{

    ata_dmafini(dev);
}
Beispiel #5
0
static int
sata_channel_attach(device_t dev)
{
	struct sata_softc *sc;
	struct ata_channel *ch;
	uint64_t work;
	int error, i;

	sc = device_get_softc(device_get_parent(dev));
	ch = device_get_softc(dev);

	if (ch->attached)
		return (0);

	ch->dev = dev;
	ch->unit = device_get_unit(dev);
	ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE | ATA_SATA;

	/* Set legacy ATA resources. */
	for (i = ATA_DATA; i <= ATA_COMMAND; i++) {
		ch->r_io[i].res = sc->sc_mem_res;
		ch->r_io[i].offset = SATA_SHADOWR_BASE(ch->unit) + (i << 2);
	}

	ch->r_io[ATA_CONTROL].res = sc->sc_mem_res;
	ch->r_io[ATA_CONTROL].offset = SATA_SHADOWR_CONTROL(ch->unit);

	ch->r_io[ATA_IDX_ADDR].res = sc->sc_mem_res;
	ata_default_registers(dev);

	/* Set SATA resources. */
	ch->r_io[ATA_SSTATUS].res = sc->sc_mem_res;
	ch->r_io[ATA_SSTATUS].offset = SATA_SATA_SSTATUS(ch->unit);
	ch->r_io[ATA_SERROR].res = sc->sc_mem_res;
	ch->r_io[ATA_SERROR].offset = SATA_SATA_SERROR(ch->unit);
	ch->r_io[ATA_SCONTROL].res = sc->sc_mem_res;
	ch->r_io[ATA_SCONTROL].offset = SATA_SATA_SCONTROL(ch->unit);
	ata_generic_hw(dev);

	ch->hw.begin_transaction = sata_channel_begin_transaction;
	ch->hw.end_transaction = sata_channel_end_transaction;
	ch->hw.status = sata_channel_status;

	/* Set DMA resources */
	ata_dmainit(dev);
	ch->dma.setprd = sata_channel_dmasetprd;

	/* Clear work area */
	KASSERT(sc->sc_edma_qlen * (sizeof(struct sata_crqb) +
	    sizeof(struct sata_crpb)) <= ch->dma.max_iosize,
	    ("insufficient DMA memory for request/response queues.\n"));
	bzero(ch->dma.work, sc->sc_edma_qlen * (sizeof(struct sata_crqb) +
	    sizeof(struct sata_crpb)));
	bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);

	/* Turn off EDMA engine */
	error = sata_edma_ctrl(dev, 0);
	if (error) {
		ata_dmafini(dev);
		return (error);
	}

	/*
	 * Initialize EDMA engine:
	 *	- Native Command Queuing off,
	 *	- Non-Queued operation,
	 *	- Host Queue Cache enabled.
	 */
	SATA_OUTL(sc, SATA_EDMA_CFG(ch->unit), SATA_EDMA_CFG_HQCACHE |
	    (sc->sc_version == 1) ? SATA_EDMA_CFG_QL128 : 0);

	/* Set request queue pointers */
	work = ch->dma.work_bus;
	SATA_OUTL(sc, SATA_EDMA_REQBAHR(ch->unit), work >> 32);
	SATA_OUTL(sc, SATA_EDMA_REQIPR(ch->unit), work & 0xFFFFFFFF);
	SATA_OUTL(sc, SATA_EDMA_REQOPR(ch->unit), work & 0xFFFFFFFF);

	/* Set response queue pointers */
	work += sc->sc_edma_qlen * sizeof(struct sata_crqb);
	SATA_OUTL(sc, SATA_EDMA_RESBAHR(ch->unit), work >> 32);
	SATA_OUTL(sc, SATA_EDMA_RESIPR(ch->unit), work & 0xFFFFFFFF);
	SATA_OUTL(sc, SATA_EDMA_RESOPR(ch->unit), work & 0xFFFFFFFF);

	/* Clear any outstanding interrupts */
	ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
	SATA_OUTL(sc, SATA_SATA_FISICR(ch->unit), 0);
	SATA_OUTL(sc, SATA_EDMA_IECR(ch->unit), 0);
	SATA_OUTL(sc, SATA_ICR,
	    ~(SATA_ICR_DEV(ch->unit) | SATA_ICR_DMADONE(ch->unit)));

	/* Umask channel interrupts */
	SATA_OUTL(sc, SATA_EDMA_IEMR(ch->unit), 0xFFFFFFFF);
	SATA_OUTL(sc, SATA_MIMR, SATA_INL(sc, SATA_MIMR) |
	    SATA_MICR_DONE(ch->unit) | SATA_MICR_DMADONE(ch->unit) |
	    SATA_MICR_ERR(ch->unit));

	ch->attached = 1;

	return (ata_attach(dev));
}