Add suspend/resume code mostly merged from fxp/rl driver.
This is temporary hack, better and generalized solution probably should be implemented at lower layer(MII or PCI?). Tested by: shoko.araki@soliton.co.jp MFC after: 1 week
This commit is contained in:
parent
1827483427
commit
f42381b21e
@ -198,6 +198,8 @@ static struct dc_type dc_devs[] = {
|
||||
static int dc_probe (device_t);
|
||||
static int dc_attach (device_t);
|
||||
static int dc_detach (device_t);
|
||||
static int dc_suspend (device_t);
|
||||
static int dc_resume (device_t);
|
||||
static void dc_acpi (device_t);
|
||||
static struct dc_type *dc_devtype (device_t);
|
||||
static int dc_newbuf (struct dc_softc *, int, struct mbuf *);
|
||||
@ -273,6 +275,8 @@ static device_method_t dc_methods[] = {
|
||||
DEVMETHOD(device_probe, dc_probe),
|
||||
DEVMETHOD(device_attach, dc_attach),
|
||||
DEVMETHOD(device_detach, dc_detach),
|
||||
DEVMETHOD(device_suspend, dc_suspend),
|
||||
DEVMETHOD(device_resume, dc_resume),
|
||||
DEVMETHOD(device_shutdown, dc_shutdown),
|
||||
|
||||
/* bus interface */
|
||||
@ -2871,6 +2875,10 @@ static void dc_intr(arg)
|
||||
|
||||
sc = arg;
|
||||
|
||||
if (sc->suspended) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0)
|
||||
return;
|
||||
|
||||
@ -3521,6 +3529,79 @@ static void dc_stop(sc)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device suspend routine. Stop the interface and save some PCI
|
||||
* settings in case the BIOS doesn't restore them properly on
|
||||
* resume.
|
||||
*/
|
||||
static int dc_suspend(dev)
|
||||
device_t dev;
|
||||
{
|
||||
register int i;
|
||||
int s;
|
||||
struct dc_softc *sc;
|
||||
|
||||
s = splimp();
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
dc_stop(sc);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
sc->saved_maps[i] = pci_read_config(dev, PCIR_MAPS + i * 4, 4);
|
||||
sc->saved_biosaddr = pci_read_config(dev, PCIR_BIOS, 4);
|
||||
sc->saved_intline = pci_read_config(dev, PCIR_INTLINE, 1);
|
||||
sc->saved_cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1);
|
||||
sc->saved_lattimer = pci_read_config(dev, PCIR_LATTIMER, 1);
|
||||
|
||||
sc->suspended = 1;
|
||||
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Device resume routine. Restore some PCI settings in case the BIOS
|
||||
* doesn't, re-enable busmastering, and restart the interface if
|
||||
* appropriate.
|
||||
*/
|
||||
static int dc_resume(dev)
|
||||
device_t dev;
|
||||
{
|
||||
register int i;
|
||||
int s;
|
||||
struct dc_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
|
||||
s = splimp();
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
dc_acpi(dev);
|
||||
|
||||
/* better way to do this? */
|
||||
for (i = 0; i < 5; i++)
|
||||
pci_write_config(dev, PCIR_MAPS + i * 4, sc->saved_maps[i], 4);
|
||||
pci_write_config(dev, PCIR_BIOS, sc->saved_biosaddr, 4);
|
||||
pci_write_config(dev, PCIR_INTLINE, sc->saved_intline, 1);
|
||||
pci_write_config(dev, PCIR_CACHELNSZ, sc->saved_cachelnsz, 1);
|
||||
pci_write_config(dev, PCIR_LATTIMER, sc->saved_lattimer, 1);
|
||||
|
||||
/* reenable busmastering */
|
||||
pci_enable_busmaster(dev);
|
||||
pci_enable_io(dev, DC_RES);
|
||||
|
||||
/* reinitialize interface if necessary */
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
dc_init(sc);
|
||||
|
||||
sc->suspended = 0;
|
||||
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop all chip I/O so that the kernel's probe routines don't
|
||||
* get confused by errant DMAs when rebooting.
|
||||
|
@ -726,6 +726,13 @@ struct dc_softc {
|
||||
#ifdef DEVICE_POLLING
|
||||
int rxcycles; /* ... when polling */
|
||||
#endif
|
||||
int suspended; /* 0 = normal 1 = suspended */
|
||||
|
||||
u_int32_t saved_maps[5]; /* pci data */
|
||||
u_int32_t saved_biosaddr;
|
||||
u_int8_t saved_intline;
|
||||
u_int8_t saved_cachelnsz;
|
||||
u_int8_t saved_lattimer;
|
||||
};
|
||||
|
||||
|
||||
|
@ -198,6 +198,8 @@ static struct dc_type dc_devs[] = {
|
||||
static int dc_probe (device_t);
|
||||
static int dc_attach (device_t);
|
||||
static int dc_detach (device_t);
|
||||
static int dc_suspend (device_t);
|
||||
static int dc_resume (device_t);
|
||||
static void dc_acpi (device_t);
|
||||
static struct dc_type *dc_devtype (device_t);
|
||||
static int dc_newbuf (struct dc_softc *, int, struct mbuf *);
|
||||
@ -273,6 +275,8 @@ static device_method_t dc_methods[] = {
|
||||
DEVMETHOD(device_probe, dc_probe),
|
||||
DEVMETHOD(device_attach, dc_attach),
|
||||
DEVMETHOD(device_detach, dc_detach),
|
||||
DEVMETHOD(device_suspend, dc_suspend),
|
||||
DEVMETHOD(device_resume, dc_resume),
|
||||
DEVMETHOD(device_shutdown, dc_shutdown),
|
||||
|
||||
/* bus interface */
|
||||
@ -2871,6 +2875,10 @@ static void dc_intr(arg)
|
||||
|
||||
sc = arg;
|
||||
|
||||
if (sc->suspended) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0)
|
||||
return;
|
||||
|
||||
@ -3521,6 +3529,79 @@ static void dc_stop(sc)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device suspend routine. Stop the interface and save some PCI
|
||||
* settings in case the BIOS doesn't restore them properly on
|
||||
* resume.
|
||||
*/
|
||||
static int dc_suspend(dev)
|
||||
device_t dev;
|
||||
{
|
||||
register int i;
|
||||
int s;
|
||||
struct dc_softc *sc;
|
||||
|
||||
s = splimp();
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
dc_stop(sc);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
sc->saved_maps[i] = pci_read_config(dev, PCIR_MAPS + i * 4, 4);
|
||||
sc->saved_biosaddr = pci_read_config(dev, PCIR_BIOS, 4);
|
||||
sc->saved_intline = pci_read_config(dev, PCIR_INTLINE, 1);
|
||||
sc->saved_cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1);
|
||||
sc->saved_lattimer = pci_read_config(dev, PCIR_LATTIMER, 1);
|
||||
|
||||
sc->suspended = 1;
|
||||
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Device resume routine. Restore some PCI settings in case the BIOS
|
||||
* doesn't, re-enable busmastering, and restart the interface if
|
||||
* appropriate.
|
||||
*/
|
||||
static int dc_resume(dev)
|
||||
device_t dev;
|
||||
{
|
||||
register int i;
|
||||
int s;
|
||||
struct dc_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
|
||||
s = splimp();
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
dc_acpi(dev);
|
||||
|
||||
/* better way to do this? */
|
||||
for (i = 0; i < 5; i++)
|
||||
pci_write_config(dev, PCIR_MAPS + i * 4, sc->saved_maps[i], 4);
|
||||
pci_write_config(dev, PCIR_BIOS, sc->saved_biosaddr, 4);
|
||||
pci_write_config(dev, PCIR_INTLINE, sc->saved_intline, 1);
|
||||
pci_write_config(dev, PCIR_CACHELNSZ, sc->saved_cachelnsz, 1);
|
||||
pci_write_config(dev, PCIR_LATTIMER, sc->saved_lattimer, 1);
|
||||
|
||||
/* reenable busmastering */
|
||||
pci_enable_busmaster(dev);
|
||||
pci_enable_io(dev, DC_RES);
|
||||
|
||||
/* reinitialize interface if necessary */
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
dc_init(sc);
|
||||
|
||||
sc->suspended = 0;
|
||||
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop all chip I/O so that the kernel's probe routines don't
|
||||
* get confused by errant DMAs when rebooting.
|
||||
|
@ -726,6 +726,13 @@ struct dc_softc {
|
||||
#ifdef DEVICE_POLLING
|
||||
int rxcycles; /* ... when polling */
|
||||
#endif
|
||||
int suspended; /* 0 = normal 1 = suspended */
|
||||
|
||||
u_int32_t saved_maps[5]; /* pci data */
|
||||
u_int32_t saved_biosaddr;
|
||||
u_int8_t saved_intline;
|
||||
u_int8_t saved_cachelnsz;
|
||||
u_int8_t saved_lattimer;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user