1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-03 09:00:21 +00:00

Add suspend/resume code mostly merged from fxp driver.

This commit is contained in:
Mitsuru IWASAKI 2001-11-23 14:27:33 +00:00
parent d0714ae55c
commit 0c66d318dd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=86822
2 changed files with 79 additions and 0 deletions

View File

@ -170,6 +170,8 @@ static int rl_ioctl __P((struct ifnet *, u_long, caddr_t));
static void rl_init __P((void *));
static void rl_stop __P((struct rl_softc *));
static void rl_watchdog __P((struct ifnet *));
static int rl_suspend __P((device_t));
static int rl_resume __P((device_t));
static void rl_shutdown __P((device_t));
static int rl_ifmedia_upd __P((struct ifnet *));
static void rl_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
@ -210,6 +212,8 @@ static device_method_t rl_methods[] = {
DEVMETHOD(device_probe, rl_probe),
DEVMETHOD(device_attach, rl_attach),
DEVMETHOD(device_detach, rl_detach),
DEVMETHOD(device_suspend, rl_suspend),
DEVMETHOD(device_resume, rl_resume),
DEVMETHOD(device_shutdown, rl_shutdown),
/* bus interface */
@ -1345,6 +1349,11 @@ static void rl_intr(arg)
u_int16_t status;
sc = arg;
if (sc->suspended) {
return;
}
RL_LOCK(sc);
ifp = &sc->arpcom.ac_if;
@ -1745,6 +1754,69 @@ static void rl_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 rl_suspend(dev)
device_t dev;
{
register int i;
struct rl_softc *sc;
sc = device_get_softc(dev);
rl_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;
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 rl_resume(dev)
device_t dev;
{
register int i;
struct rl_softc *sc;
struct ifnet *ifp;
sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
/* 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, RL_RES);
/* reinitialize interface if necessary */
if (ifp->if_flags & IFF_UP)
rl_init(sc);
sc->suspended = 0;
return (0);
}
/*
* Stop all chip I/O so that the kernel's probe routines don't
* get confused by errant DMAs when rebooting.

View File

@ -377,6 +377,13 @@ struct rl_softc {
struct rl_chain_data rl_cdata;
struct callout_handle rl_stat_ch;
struct mtx rl_mtx;
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;
};
#define RL_LOCK(_sc) mtx_lock(&(_sc)->rl_mtx)