On Sun, Sep 17, 2000 at 06:15:45AM -0700, David Greenman wrote:
>    I've made a few changes to the patches which should address my primary
> concerns. Instead of using IFF_RUNNING, I added a new softc variable to
> track the suspended condition. Only the APM stuff should call suspend/resume,
> so the interrupt logic should be uneffected in non-APM machines. Please try
> these patches out and let me know if they work as expected. They should apply
> and work with both -stable and -current.

yup, suspend/resume still works fine with this new patch.  thanks,
and sorry i've been such a pest about this...

> -DG
> 
> David Greenman
> Co-founder, The FreeBSD Project - http://www.freebsd.org
> President, TeraSolutions, Inc. - http://www.terasolutions.com
> Pave the road of life with opportunities.
> 
> Index: if_fxp.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/pci/if_fxp.c,v
> retrieving revision 1.77.2.3
> diff -c -r1.77.2.3 if_fxp.c
> *** if_fxp.c  2000/06/19 00:54:30     1.77.2.3
> --- if_fxp.c  2000/09/17 13:15:33
> ***************
> *** 125,135 ****
> --- 125,139 ----
>   fxp_lwcopy(src, dst)
>       volatile u_int32_t *src, *dst;
>   {
> + #ifdef __i386__
> +     *dst = *src;
> + #else
>       volatile u_int16_t *a = (volatile u_int16_t *)src;
>       volatile u_int16_t *b = (volatile u_int16_t *)dst;
>   
>       b[0] = a[0];
>       b[1] = a[1];
> + #endif
>   }
>   
>   /*
> ***************
> *** 215,220 ****
> --- 219,225 ----
>   static void fxp_mediastatus __P((struct ifnet *, struct ifmediareq *));
>   static void fxp_set_media   __P((struct fxp_softc *, int));
>   static __inline void fxp_scb_wait __P((struct fxp_softc *));
> + static __inline void fxp_dma_wait __P((volatile u_int16_t *, struct fxp_softc 
>*sc));
>   static FXP_INTR_TYPE fxp_intr       __P((void *));
>   static void fxp_start               __P((struct ifnet *));
>   static int fxp_ioctl                __P((struct ifnet *,
> ***************
> *** 283,290 ****
>       struct fxp_softc *sc;
>   {
>       int i = 10000;
>   
> !     while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i);
>   }
>   
>   /*************************************************************
> --- 288,311 ----
>       struct fxp_softc *sc;
>   {
>       int i = 10000;
> + 
> +     while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i)
> +             DELAY(2);
> +     if (i == 0)
> +             printf(FXP_FORMAT ": SCB timeout\n", FXP_ARGS(sc));
> + }
> + 
> + static __inline void
> + fxp_dma_wait(status, sc)
> +     volatile u_int16_t *status;
> +     struct fxp_softc *sc;
> + {
> +     int i = 10000;
>   
> !     while (!(*status & FXP_CB_STATUS_C) && --i)
> !             DELAY(2);
> !     if (i == 0)
> !             printf(FXP_FORMAT ": DMA timeout\n", FXP_ARGS(sc));
>   }
>   
>   /*************************************************************
> ***************
> *** 679,690 ****
> --- 700,784 ----
>       return 0;
>   }
>   
> + /*
> +  * Device suspend routine.  Stop the interface and save some PCI
> +  * settings in case the BIOS doesn't restore them properly on
> +  * resume.
> +  */
> + static int
> + fxp_suspend(device_t dev)
> + {
> +     struct fxp_softc *sc = device_get_softc(dev);
> +     int i, s;
> + 
> +     s = splimp();
> + 
> +     fxp_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
> + fxp_resume(device_t dev)
> + {
> +     struct fxp_softc *sc = device_get_softc(dev);
> +     struct ifnet *ifp = &sc->sc_if;
> +     u_int16_t pci_command;
> +     int i, s;
> + 
> +     s = splimp();
> + 
> +     /* 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_command = pci_read_config(dev, PCIR_COMMAND, 2);
> +     pci_command |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
> +     pci_write_config(dev, PCIR_COMMAND, pci_command, 2);
> + 
> +     CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
> +     DELAY(10);
> + 
> +     /* reinitialize interface if necessary */
> +     if (ifp->if_flags & IFF_UP)
> +             fxp_init(sc);
> + 
> +     sc->suspended = 0;
> + 
> +     splx(s);
> + 
> +     return 0;
> + }
> + 
>   static device_method_t fxp_methods[] = {
>       /* Device interface */
>       DEVMETHOD(device_probe,         fxp_probe),
>       DEVMETHOD(device_attach,        fxp_attach),
>       DEVMETHOD(device_detach,        fxp_detach),
>       DEVMETHOD(device_shutdown,      fxp_shutdown),
> +     DEVMETHOD(device_suspend,       fxp_suspend),
> +     DEVMETHOD(device_resume,        fxp_resume),
>   
>       { 0, 0 }
>   };
> ***************
> *** 1095,1101 ****
>       int claimed = 0;
>   #endif
>   
> !     while ((statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK)) != 0) {
>   #if defined(__NetBSD__)
>               claimed = 1;
>   #endif
> --- 1189,1195 ----
>       int claimed = 0;
>   #endif
>   
> !     while (!sc->suspended && (statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK)) != 0) 
>{
>   #if defined(__NetBSD__)
>               claimed = 1;
>   #endif
> ***************
> *** 1158,1164 ****
>                                */
>                               if (fxp_add_rfabuf(sc, m) == 0) {
>                                       struct ether_header *eh;
> !                                     u_int16_t total_len;
>   
>                                       total_len = rfa->actual_size &
>                                           (MCLBYTES - 1);
> --- 1252,1258 ----
>                                */
>                               if (fxp_add_rfabuf(sc, m) == 0) {
>                                       struct ether_header *eh;
> !                                     int total_len;
>   
>                                       total_len = rfa->actual_size &
>                                           (MCLBYTES - 1);
> ***************
> *** 1317,1322 ****
> --- 1411,1419 ----
>       struct fxp_cb_tx *txp;
>       int i;
>   
> +     ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
> +     ifp->if_timer = 0;
> + 
>       /*
>        * Cancel stats updater.
>        */
> ***************
> *** 1359,1367 ****
>                       panic("fxp_stop: no buffers!");
>               }
>       }
> - 
> -     ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
> -     ifp->if_timer = 0;
>   }
>   
>   /*
> --- 1456,1461 ----
> ***************
> *** 1474,1480 ****
>       CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&cbp->cb_status));
>       CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
>       /* ...and wait for it to complete. */
> !     while (!(cbp->cb_status & FXP_CB_STATUS_C));
>   
>       /*
>        * Now initialize the station address. Temporarily use the TxCB
> --- 1568,1574 ----
>       CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&cbp->cb_status));
>       CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
>       /* ...and wait for it to complete. */
> !     fxp_dma_wait(&cbp->cb_status, sc);
>   
>       /*
>        * Now initialize the station address. Temporarily use the TxCB
> ***************
> *** 1497,1503 ****
>       fxp_scb_wait(sc);
>       CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
>       /* ...and wait for it to complete. */
> !     while (!(cb_ias->cb_status & FXP_CB_STATUS_C));
>   
>       /*
>        * Initialize transmit control block (TxCB) list.
> --- 1591,1597 ----
>       fxp_scb_wait(sc);
>       CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
>       /* ...and wait for it to complete. */
> !     fxp_dma_wait(&cb_ias->cb_status, sc);
>   
>       /*
>        * Initialize transmit control block (TxCB) list.
> ***************
> *** 1936,1941 ****
> --- 2030,2036 ----
>       struct ifnet *ifp = &sc->sc_if;
>       struct ifmultiaddr *ifma;
>       int nmcasts;
> +     int count;
>   
>       /*
>        * If there are queued commands, we must wait until they are all
> ***************
> *** 2017,2024 ****
>        * Wait until command unit is not active. This should never
>        * be the case when nothing is queued, but make sure anyway.
>        */
>       while ((CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS) >> 6) ==
> !         FXP_SCB_CUS_ACTIVE) ;
>   
>       /*
>        * Start the multicast setup command.
> --- 2112,2125 ----
>        * Wait until command unit is not active. This should never
>        * be the case when nothing is queued, but make sure anyway.
>        */
> +     count = 100;
>       while ((CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS) >> 6) ==
> !         FXP_SCB_CUS_ACTIVE && --count)
> !             DELAY(10);
> !     if (count == 0) {
> !             printf(FXP_FORMAT ": command queue timeout\n", FXP_ARGS(sc));
> !             return;
> !     }
>   
>       /*
>        * Start the multicast setup command.
> Index: if_fxpvar.h
> ===================================================================
> RCS file: /home/ncvs/src/sys/pci/if_fxpvar.h,v
> retrieving revision 1.9.2.1
> diff -c -r1.9.2.1 if_fxpvar.h
> *** if_fxpvar.h       2000/03/29 02:02:39     1.9.2.1
> --- if_fxpvar.h       2000/09/17 13:15:33
> ***************
> *** 68,73 ****
> --- 68,79 ----
>       int phy_primary_device;         /* device type of primary PHY */
>       int phy_10Mbps_only;            /* PHY is 10Mbps-only device */
>       int eeprom_size;                /* size of serial EEPROM */
> +     int suspended;                  /* 0 = normal  1 = suspended (APM) */
> +     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;
>   };
>   
>   /* Macros to ease CSR access. */
> 


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to