コード例 #1
0
ファイル: ata-sata.c プロジェクト: dcui/FreeBSD-9.3_kernel
void
ata_sata_phy_check_events(device_t dev, int port)
{
    struct ata_channel *ch = device_get_softc(dev);
    u_int32_t error, status;

    if (ata_sata_scr_read(ch, port, ATA_SERROR, &error))
	return;

    /* Check that SError value is sane. */
    if (error == 0xffffffff)
	return;

    /* Clear set error bits/interrupt. */
    if (error)
	ata_sata_scr_write(ch, port, ATA_SERROR, error);

    /* if we have a connection event deal with it */
    if ((error & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) {
	if (bootverbose) {
	    if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status)) {
		    device_printf(dev, "PHYRDY change\n");
	    } else if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
		((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
		((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
		    device_printf(dev, "CONNECT requested\n");
	    } else
		    device_printf(dev, "DISCONNECT requested\n");
	}
	taskqueue_enqueue(taskqueue_thread, &ch->conntask);
    }
}
コード例 #2
0
int
ata_sata_phy_reset(device_t dev, int port, int quick)
{
    struct ata_channel *ch = device_get_softc(dev);
    int loop, retry;
    uint32_t val;

    if (quick) {
	if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
	    return (0);
	if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE)
	    return ata_sata_connect(ch, port);
    }

    if (bootverbose) {
	if (port < 0) {
	    device_printf(dev, "hardware reset ...\n");
	} else {
	    device_printf(dev, "p%d: hardware reset ...\n", port);
	}
    }
    for (retry = 0; retry < 10; retry++) {
	for (loop = 0; loop < 10; loop++) {
	    if (ata_sata_scr_write(ch, port, ATA_SCONTROL, ATA_SC_DET_RESET))
		return (0);
	    ata_udelay(100);
	    if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
		return (0);
	    if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_RESET)
		break;
	}
	ata_udelay(5000);
	for (loop = 0; loop < 10; loop++) {
	    if (ata_sata_scr_write(ch, port, ATA_SCONTROL,
		    ATA_SC_DET_IDLE | ((ch->pm_level > 0) ? 0 :
		    ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)))
		return (0);
	    ata_udelay(100);
	    if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
		return (0);
	    if ((val & ATA_SC_DET_MASK) == 0)
		return ata_sata_connect(ch, port);
	}
    }
    return 0;
}
コード例 #3
0
ファイル: ata-via.c プロジェクト: MattDooner/freebsd-west
static int
ata_via_sata_ch_attach(device_t dev)
{
	struct ata_channel *ch = device_get_softc(dev);

	if (ata_pci_ch_attach(dev))
		return ENXIO;
	if (ch->unit == 0) {
		ch->hw.status = ata_via_sata_status;
		ch->hw.pm_read = ata_via_sata_scr_read;
		ch->hw.pm_write = ata_via_sata_scr_write;
		ch->flags |= ATA_PERIODIC_POLL;
		ch->flags |= ATA_SATA;
		ata_sata_scr_write(ch, 0, ATA_SERROR, 0xffffffff);
		ata_sata_scr_write(ch, 1, ATA_SERROR, 0xffffffff);
	}
	return (0);
}
コード例 #4
0
ファイル: ata-via.c プロジェクト: MattDooner/freebsd-west
static int
ata_via_ch_attach(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
    struct ata_channel *ch = device_get_softc(dev);

    /* newer SATA chips has resources in one BAR for each channel */
    if (ctlr->chip->cfg2 & VIABAR) {
	struct resource *r_io;
	int i, rid;
		
	ata_pci_dmainit(dev);

	rid = PCIR_BAR(ch->unit);
	if (!(r_io = bus_alloc_resource_any(device_get_parent(dev),
					    SYS_RES_IOPORT,
					    &rid, RF_ACTIVE)))
	    return ENXIO;

	for (i = ATA_DATA; i <= ATA_COMMAND; i ++) {
	    ch->r_io[i].res = r_io;
	    ch->r_io[i].offset = i;
	}
	ch->r_io[ATA_CONTROL].res = r_io;
	ch->r_io[ATA_CONTROL].offset = 2 + ATA_IOSIZE;
	ch->r_io[ATA_IDX_ADDR].res = r_io;
	ata_default_registers(dev);
	for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) {
	    ch->r_io[i].res = ctlr->r_res1;
	    ch->r_io[i].offset = (i - ATA_BMCMD_PORT)+(ch->unit * ATA_BMIOSIZE);
	}
	ata_pci_hw(dev);
	if (ch->unit >= 2)
	    return 0;
    }
    else {
	/* setup the usual register normal pci style */
	if (ata_pci_ch_attach(dev))
	    return ENXIO;
    }

    ch->r_io[ATA_SSTATUS].res = ctlr->r_res2;
    ch->r_io[ATA_SSTATUS].offset = (ch->unit << ctlr->chip->cfg1);
    ch->r_io[ATA_SERROR].res = ctlr->r_res2;
    ch->r_io[ATA_SERROR].offset = 0x04 + (ch->unit << ctlr->chip->cfg1);
    ch->r_io[ATA_SCONTROL].res = ctlr->r_res2;
    ch->r_io[ATA_SCONTROL].offset = 0x08 + (ch->unit << ctlr->chip->cfg1);
    ch->hw.status = ata_via_status;
    ch->flags |= ATA_NO_SLAVE;
    ch->flags |= ATA_SATA;
    ch->flags |= ATA_PERIODIC_POLL;

    ata_sata_scr_write(ch, -1, ATA_SERROR, 0xffffffff);

    return 0;
}
コード例 #5
0
ファイル: ata-sata.c プロジェクト: dcui/FreeBSD-9.3_kernel
static int
ata_sata_connect(struct ata_channel *ch, int port, int quick)
{
    u_int32_t status;
    int timeout, t;

    /* wait up to 1 second for "connect well" */
    timeout = (quick == 2) ? 0 : 100;
    t = 0;
    while (1) {
	if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status))
	    return (0);
	if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
	    ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
	    ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE))
	    break;
	if (++t > timeout)
	    break;
	ata_udelay(10000);
    }
    if (bootverbose) {
	if (t > timeout) {
	    if (port < 0) {
		device_printf(ch->dev, "SATA connect timeout status=%08x\n",
		    status);
	    } else {
		device_printf(ch->dev, "p%d: SATA connect timeout status=%08x\n",
		    port, status);
	    }
	} else if (port < 0) {
	    device_printf(ch->dev, "SATA connect time=%dms status=%08x\n",
		t * 10, status);
	} else {
	    device_printf(ch->dev, "p%d: SATA connect time=%dms status=%08x\n",
		port, t * 10, status);
	}
    }

    /* clear SATA error register */
    ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff);

    return ((t > timeout) ? 0 : 1);
}
コード例 #6
0
static int
ata_sata_connect(struct ata_channel *ch, int port)
{
    u_int32_t status;
    int timeout;

    /* wait up to 1 second for "connect well" */
    for (timeout = 0; timeout < 100 ; timeout++) {
	if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status))
	    return (0);
	if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
	    (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
	    break;
	ata_udelay(10000);
    }
    if (timeout >= 100) {
	if (bootverbose) {
	    if (port < 0) {
		device_printf(ch->dev, "SATA connect timeout status=%08x\n",
		    status);
	    } else {
		device_printf(ch->dev, "p%d: SATA connect timeout status=%08x\n",
		    port, status);
	    }
	}
	return 0;
    }
    if (bootverbose) {
	if (port < 0) {
	    device_printf(ch->dev, "SATA connect time=%dms status=%08x\n",
		timeout * 10, status);
	} else {
	    device_printf(ch->dev, "p%d: SATA connect time=%dms status=%08x\n",
		port, timeout * 10, status);
	}
    }

    /* clear SATA error register */
    ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff);

    return 1;
}
コード例 #7
0
ファイル: ata-sata.c プロジェクト: dcui/FreeBSD-9.3_kernel
int
ata_sata_phy_reset(device_t dev, int port, int quick)
{
    struct ata_channel *ch = device_get_softc(dev);
    int loop, retry, sata_rev;
    uint32_t val, val1;

#ifdef ATA_CAM
    sata_rev = ch->user[port < 0 ? 0 : port].revision;
    if (sata_rev > 0)
	quick = 0;
#else
    sata_rev = 0;
#endif

    if (quick) {
	if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
	    return (0);
	if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE) {
	    ata_sata_scr_write(ch, port, ATA_SCONTROL,
		ATA_SC_DET_IDLE | ((ch->pm_level > 0) ? 0 :
		ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER));
	    return ata_sata_connect(ch, port, quick);
	}
    }

    if (bootverbose) {
	if (port < 0) {
	    device_printf(dev, "hard reset ...\n");
	} else {
	    device_printf(dev, "p%d: hard reset ...\n", port);
	}
    }
    if (sata_rev == 1)
	val1 = ATA_SC_SPD_SPEED_GEN1;
    else if (sata_rev == 2)
	val1 = ATA_SC_SPD_SPEED_GEN2;
    else if (sata_rev == 3)
	val1 = ATA_SC_SPD_SPEED_GEN3;
    else
	val1 = 0;
    for (retry = 0; retry < 10; retry++) {
	for (loop = 0; loop < 10; loop++) {
	    if (ata_sata_scr_write(ch, port, ATA_SCONTROL, ATA_SC_DET_RESET |
		    val1 | ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER))
		goto fail;
	    ata_udelay(100);
	    if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
		goto fail;
	    if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_RESET)
		break;
	}
	ata_udelay(5000);
	for (loop = 0; loop < 10; loop++) {
	    if (ata_sata_scr_write(ch, port, ATA_SCONTROL,
		    ATA_SC_DET_IDLE | val1 | ((ch->pm_level > 0) ? 0 :
		    ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)))
		goto fail;
	    ata_udelay(100);
	    if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
		goto fail;
	    if ((val & ATA_SC_DET_MASK) == 0)
		return ata_sata_connect(ch, port, 0);
	}
    }
fail:
    /* Clear SATA error register. */
    ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff);

    if (bootverbose) {
	if (port < 0) {
	    device_printf(dev, "hard reset failed\n");
	} else {
	    device_printf(dev, "p%d: hard reset failed\n", port);
	}
    }
    return (0);
}