Move part of wdc_sataprobe() to sys/dev/ata/sata_subr.c so that it can be

shared with non-wdc SATA controllers.
This commit is contained in:
bouyer 2006-11-20 23:42:21 +00:00
parent efbf65678a
commit 37152360bf
3 changed files with 76 additions and 49 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sata_subr.c,v 1.2 2005/12/11 12:21:14 christos Exp $ */
/* $NetBSD: sata_subr.c,v 1.3 2006/11/20 23:42:21 bouyer Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@ -41,6 +41,8 @@
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <dev/ata/satareg.h>
#include <dev/ata/satavar.h>
@ -76,3 +78,64 @@ sata_speed(uint32_t sstatus)
return (sata_speedtab[(sstatus & SStatus_SPD_mask) >>
SStatus_SPD_shift]);
}
/*
* reset the PHY and bring it online
*/
uint32_t
sata_reset_interface(struct ata_channel *chp, bus_space_tag_t sata_t,
bus_space_handle_t scontrol_r, bus_space_handle_t sstatus_r)
{
uint32_t scontrol, sstatus;
int i;
/* bring the PHYs online.
* The work-around for errata #1 for the 31244 says that we must
* write 0 to the port first to be sure of correctly initializing
* the device. It doesn't hurt for other devices.
*/
bus_space_write_4(sata_t, scontrol_r, 0, 0);
scontrol = SControl_IPM_NONE | SControl_SPD_ANY | SControl_DET_INIT;
bus_space_write_4 (sata_t, scontrol_r, 0, scontrol);
tsleep(chp, PRIBIO, "sataup", mstohz(50));
scontrol &= ~SControl_DET_INIT;
bus_space_write_4(sata_t, scontrol_r, 0, scontrol);
tsleep(chp, PRIBIO, "sataup", mstohz(50));
/* wait up to 1s for device to come up */
for (i = 0; i < 100; i++) {
sstatus = bus_space_read_4(sata_t, sstatus_r, 0);
if ((sstatus & SStatus_DET_mask) == SStatus_DET_DEV)
break;
tsleep(chp, PRIBIO, "sataup", mstohz(10));
}
switch (sstatus & SStatus_DET_mask) {
case SStatus_DET_NODEV:
/* No Device; be silent. */
break;
case SStatus_DET_DEV_NE:
aprint_error("%s: port %d: device connected, but "
"communication not established\n",
chp->ch_atac->atac_dev.dv_xname, chp->ch_channel);
break;
case SStatus_DET_OFFLINE:
aprint_error("%s: port %d: PHY offline\n",
chp->ch_atac->atac_dev.dv_xname, chp->ch_channel);
break;
case SStatus_DET_DEV:
aprint_normal("%s: port %d: device present, speed: %s\n",
chp->ch_atac->atac_dev.dv_xname, chp->ch_channel,
sata_speed(sstatus));
break;
default:
aprint_error("%s: port %d: unknown SStatus: 0x%08x\n",
chp->ch_atac->atac_dev.dv_xname, chp->ch_channel,
sstatus);
}
return(sstatus);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: satavar.h,v 1.2 2005/12/11 12:21:14 christos Exp $ */
/* $NetBSD: satavar.h,v 1.3 2006/11/20 23:42:21 bouyer Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@ -39,10 +39,15 @@
#ifndef _DEV_ATA_SATAVAR_H_
#define _DEV_ATA_SATAVAR_H_
#include <machine/bus.h>
#include <dev/ata/atavar.h>
/*
* Declaration of common data structures and functions for Serial ATA.
*/
const char *sata_speed(uint32_t);
uint32_t sata_reset_interface(struct ata_channel *, bus_space_tag_t,
bus_space_handle_t, bus_space_handle_t);
#endif /* _DEV_ATA_SATAVAR_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: wdc.c,v 1.241 2006/11/14 18:39:10 bouyer Exp $ */
/* $NetBSD: wdc.c,v 1.242 2006/11/20 23:42:21 bouyer Exp $ */
/*
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved.
@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.241 2006/11/14 18:39:10 bouyer Exp $");
__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.242 2006/11/20 23:42:21 bouyer Exp $");
#ifndef ATADEBUG
#define ATADEBUG
@ -214,7 +214,6 @@ void
wdc_sataprobe(struct ata_channel *chp)
{
struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
uint32_t scontrol, sstatus;
uint16_t scnt, sn, cl, ch;
int i, s;
@ -224,44 +223,9 @@ wdc_sataprobe(struct ata_channel *chp)
chp->ch_drive[i].drive = i;
}
/* bring the PHYs online.
* The work-around for errata #1 for the 31244 says that we must
* write 0 to the port first to be sure of correctly initializing
* the device. It doesn't hurt for other devices.
*/
bus_space_write_4(wdr->sata_iot, wdr->sata_control, 0, 0);
scontrol = SControl_IPM_NONE | SControl_SPD_ANY | SControl_DET_INIT;
bus_space_write_4 (wdr->sata_iot, wdr->sata_control, 0, scontrol);
tsleep(wdr, PRIBIO, "sataup", mstohz(50));
scontrol &= ~SControl_DET_INIT;
bus_space_write_4(wdr->sata_iot, wdr->sata_control, 0, scontrol);
tsleep(wdr, PRIBIO, "sataup", mstohz(50));
/* wait up to 1s for device to come up */
for (i = 0; i < 100; i++) {
sstatus = bus_space_read_4(wdr->sata_iot, wdr->sata_status, 0);
if ((sstatus & SStatus_DET_mask) == SStatus_DET_DEV)
break;
tsleep(wdr, PRIBIO, "sataup", mstohz(10));
}
switch (sstatus & SStatus_DET_mask) {
case SStatus_DET_NODEV:
/* No Device; be silent. */
break;
case SStatus_DET_DEV_NE:
aprint_error("%s: port %d: device connected, but "
"communication not established\n",
chp->ch_atac->atac_dev.dv_xname, chp->ch_channel);
break;
case SStatus_DET_OFFLINE:
aprint_error("%s: port %d: PHY offline\n",
chp->ch_atac->atac_dev.dv_xname, chp->ch_channel);
break;
/* reset the PHY and bring online */
switch (sata_reset_interface(chp, wdr->sata_iot, wdr->sata_control,
wdr->sata_status)) {
case SStatus_DET_DEV:
bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
WDSD_IBM);
@ -289,9 +253,6 @@ wdc_sataprobe(struct ata_channel *chp)
chp->ch_drive[0].drive_flags |= DRIVE_ATA;
splx(s);
aprint_normal("%s: port %d: device present, speed: %s\n",
chp->ch_atac->atac_dev.dv_xname, chp->ch_channel,
sata_speed(sstatus));
/*
* issue a reset in case only the interface part of the drive
* is up
@ -301,9 +262,7 @@ wdc_sataprobe(struct ata_channel *chp)
break;
default:
aprint_error("%s: port %d: unknown SStatus: 0x%08x\n",
chp->ch_atac->atac_dev.dv_xname, chp->ch_channel,
sstatus);
break;
}
}
#endif /* NSATA > 0 */