Пример #1
0
static int
ata_pci_dmastart(device_t dev)
{
    struct ata_channel *ch = device_get_softc(device_get_parent(dev));
    u_int8_t val;

    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) | 
		 (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
    ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->sg_bus);
    ch->dma->flags |= ATA_DMA_ACTIVE;
    val = ATA_IDX_INB(ch, ATA_BMCMD_PORT);
    if (ch->dma->flags & ATA_DMA_READ)
	val |= ATA_BMCMD_WRITE_READ;
    else
	val &= ~ATA_BMCMD_WRITE_READ;
    ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, val);

    /*
     * Issue the start command separately from configuration setup,
     * in case the hardware latches portions of the configuration.
     */
    ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, val | ATA_BMCMD_START_STOP);

    return 0;
}
Пример #2
0
static u_int32_t
ata_siiprb_softreset(device_t dev, int port)
{
    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
    struct ata_channel *ch = device_get_softc(dev);
    struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work;
    u_int32_t signature;
    int offset = ch->unit * 0x2000;

    /* setup the workspace for a soft reset command */
    bzero(prb, sizeof(struct ata_siiprb_command));
    prb->control = htole16(0x0080);
    prb->fis[1] = port & 0x0f;

    /* issue soft reset */
    if (ata_siiprb_issue_cmd(dev))
	return -1;

    ata_udelay(150000);

    /* get possible signature */
    prb = (struct ata_siiprb_command *)
	((u_int8_t *)rman_get_virtual(ctlr->r_res2) + offset);
    signature=prb->fis[12]|(prb->fis[4]<<8)|(prb->fis[5]<<16)|(prb->fis[6]<<24);

    /* clear error bits/interrupt */
    ATA_IDX_OUTL(ch, ATA_SERROR, 0xffffffff);

    return signature;
}
Пример #3
0
int
ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val)
{

    if (ch->hw.pm_write != NULL)
	return (ch->hw.pm_write(ch->dev, port, reg, val));
    if (ch->r_io[reg].res) {
	ATA_IDX_OUTL(ch, reg, val);
	return (0);
    }
    return (-1);
}
Пример #4
0
static int
ata_pci_dmastart(device_t dev)
{
    struct ata_channel *ch = device_get_softc(device_get_parent(dev));

    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) | 
		 (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
    ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->sg_bus);
    ch->dma->flags |= ATA_DMA_ACTIVE;
    ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
		 (ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_WRITE_READ) |
		 ((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) |
		 ATA_BMCMD_START_STOP);
    return 0;
}
Пример #5
0
static int
ata_pci_dmastart(struct ata_request *request)
{
    struct ata_channel *ch = device_get_softc(request->parent);

    ATA_DEBUG_RQ(request, "dmastart");

    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) | 
		 (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
    ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, request->dma->sg_bus);
    ch->dma.flags |= ATA_DMA_ACTIVE;
    ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
		 (ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_WRITE_READ) |
		 ((request->flags & ATA_R_READ) ? ATA_BMCMD_WRITE_READ : 0)|
		 ATA_BMCMD_START_STOP);
    return 0;
}
Пример #6
0
static int
ata_siiprb_pm_write(device_t dev, int port, int reg, u_int32_t value)
{
    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
    struct ata_channel *ch = device_get_softc(dev);
    struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work;
    int offset = ch->unit * 0x2000;

    if (port < 0) {
	ATA_IDX_OUTL(ch, reg, value);
	return (0);
    }
    if (port < ATA_PM) {
	switch (reg) {
	case ATA_SSTATUS:
	    reg = 0;
	    break;
	case ATA_SERROR:
	    reg = 1;
	    break;
	case ATA_SCONTROL:
	    reg = 2;
	    break;
	default:
	    return (EINVAL);
	}
    }
    bzero(prb, sizeof(struct ata_siiprb_command));
    prb->fis[0] = 0x27;	/* host to device */
    prb->fis[1] = 0x8f;	/* command FIS to PM port */
    prb->fis[2] = ATA_WRITE_PM;
    prb->fis[3] = reg;
    prb->fis[7] = port;
    prb->fis[12] = value & 0xff;
    prb->fis[4] = (value >> 8) & 0xff;
    prb->fis[5] = (value >> 16) & 0xff;
    prb->fis[6] = (value >> 24) & 0xff;
    if (ata_siiprb_issue_cmd(dev)) {
	device_printf(dev, "error writing PM port\n");
	return ATA_E_ABORT;
    }
    prb = (struct ata_siiprb_command *)
	((u_int8_t *)rman_get_virtual(ctlr->r_res2) + offset);
    return prb->fis[3];
}
Пример #7
0
int
ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val)
{
    int r;

    if (port < 0) {
	ATA_IDX_OUTL(ch, reg, val);
	return (0);
    } else {
	switch (reg) {
	    case ATA_SERROR:
		r = 1;
		break;
	    case ATA_SCONTROL:
		r = 2;
		break;
	    default:
		return (EINVAL);
	}
	return (ch->hw.pm_write(ch->dev, port, r, val));
    }
}
Пример #8
0
void
ata_sata_phy_check_events(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);
    u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);

    /* clear error bits/interrupt */
    ATA_IDX_OUTL(ch, ATA_SERROR, error);

    /* if we have a connection event deal with it */
    if ((error & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) {
	if (bootverbose) {
	    u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
	    if (((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) ||
		((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)) {
		    device_printf(dev, "CONNECT requested\n");
	    } else
		    device_printf(dev, "DISCONNECT requested\n");
	}
	taskqueue_enqueue(taskqueue_thread, &ch->conntask);
    }
}
Пример #9
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));
}