Subject: kern/9286: ex driver cannot wake 3c905B from power state D3
To: None <gnats-bugs@gnats.netbsd.org>
From: None <steven_grunza@ieee.org>
List: netbsd-bugs
Date: 01/24/2000 10:09:41
>Number: 9286
>Category: kern
>Synopsis: Win98 warm boot puts 3c905B in state D3 and causes ex driver failure
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Jan 24 10:09:00 2000
>Last-Modified:
>Originator: Steven Grunza
>Organization:
>Release: NetBSD-i386 1.4.1
>Environment:
Dell Dimension xps R400, dual boot to Windows 98 or NetBSD
System: NetBSD pc-grunza-p 1.4.1 NetBSD 1.4.1 (xps_r400) #15: Mon Jan 24 12:46:01 EST 2000 root@pc-grunza-p:/usr/src/sys/arch/i386/compile/xps_r400 i386
>Description:
After choosing to restart in Windows98, the ex driver cannot wake the 3c905B
from power state D3. This may also be a problem with recent Linux releases.
>How-To-Repeat:
Warm boot the system from Windows98.
>Fix:
The following patch to /sys/dev/pci/if_ex_pci.c fixes the problem for me:
102a103
> void ex_d3tod0 __P(( struct ex_softc *, struct pci_attach_args *));
177a179,223
> ex_d3tod0( sc, pa )
> struct ex_softc *sc;
> struct pci_attach_args *pa;
> {
>
> #define PCI_CACHE_LAT_BIST 0x0c
> #define PCI_BAR0 0x10
> #define PCI_BAR1 0x14
> #define PCI_BAR2 0x18
> #define PCI_BAR3 0x1C
> #define PCI_BAR4 0x20
> #define PCI_BAR5 0x24
> #define PCI_EXP_ROM_BAR 0x30
> #define PCI_INT_GNT_LAT 0x3c
>
>
> pci_chipset_tag_t pc = pa->pa_pc;
>
> u_int32_t base0;
> u_int32_t base1;
> u_int32_t romaddr;
> u_int32_t pci_command;
> u_int32_t pci_int_lat;
> u_int32_t pci_cache_lat;
>
> pci_command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG );
> base0 = pci_conf_read(pc, pa->pa_tag, PCI_BAR0 );
> base1 = pci_conf_read(pc, pa->pa_tag, PCI_BAR1 );
> romaddr = pci_conf_read(pc, pa->pa_tag, PCI_EXP_ROM_BAR );
> pci_cache_lat= pci_conf_read(pc, pa->pa_tag, PCI_CACHE_LAT_BIST );
> pci_int_lat = pci_conf_read(pc, pa->pa_tag, PCI_INT_GNT_LAT );
>
> pci_conf_write(pc, pa->pa_tag, PCI_POWERCTL, 0);
> pci_conf_write(pc, pa->pa_tag, PCI_BAR0, base0 );
> pci_conf_write(pc, pa->pa_tag, PCI_BAR1, base1 );
> pci_conf_write(pc, pa->pa_tag, PCI_EXP_ROM_BAR, romaddr );
> pci_conf_write(pc, pa->pa_tag, PCI_INT_GNT_LAT, pci_int_lat );
> pci_conf_write(pc, pa->pa_tag, PCI_CACHE_LAT_BIST, pci_cache_lat );
> pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
> ( PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE));
>
> return;
> }
>
> void
226,228c272,279
< printf("%s: unable to wake up from power state D3\n",
< sc->sc_dev.dv_xname);
< return;
---
> printf("%s: found in power state D3, "
> "attempting to recover.\n",
> sc->sc_dev.dv_xname);
>
> ex_d3tod0( sc, pa );
>
> printf("%s: finished changing power state to D0.\n",
> sc->sc_dev.dv_xname);
The 3c905B and 3c905C documentation says that all PCI configuration is lost in
power state D3 but doesn't say what to do to recover. Don Becker's linux
driver seems to DTRT. He has information at http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html.
Steven Grunza
steven_grunza@ieee.org
>Audit-Trail:
>Unformatted: