NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-hp700/35531: iee0 does not work on 735/99



The following reply was made to PR port-hp700/35531; it has been noted by GNATS.

From: Izumi Tsutsui <tsutsui%ceres.dti.ne.jp@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: skrll%NetBSD.org@localhost, port-hp700-maintainer%NetBSD.org@localhost, 
gnats-admin%NetBSD.org@localhost,
        netbsd-bugs%NetBSD.org@localhost, tsutsui%ceres.dti.ne.jp@localhost
Subject: Re: port-hp700/35531: iee0 does not work on 735/99
Date: Sun, 3 May 2009 19:33:36 +0900

 >> I believe this is because the driver programs the chip as a
 >> rev C device where the chips in earlier models where rev.B
 >> (or earlier)
 
 The major difference between Step-A and B/C is 32 bit big endian mode
 enabled by IEE_SYSBUS_BE bit. On rev A chip, we have to treats
 all 32 bit pointers in DMA descriptors as two 16-bit big endian entities
 as well as the SCP pointer.
 
 My 735/125 seems to have Rev C chip as the following:
 
  KU82596DX-33
  L4502047
  SZ715 C
  INTEL(M)(C)1989
 
 but now it also works in Rev A compatible mode (i.e. without IEE_SYSBUS_BE)
 with the attached patch, so it should also work on Rev A chips.
 
 As noted in comments, it might be better to detect chip revision
 and switch flags at runtime, but I can't find how we ca do it
 in the Intel manual.
 
 ---
 Index: dev/ic/i82596.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ic/i82596.c,v
 retrieving revision 1.19
 diff -u -r1.19 i82596.c
 --- dev/ic/i82596.c    4 Apr 2008 17:03:42 -0000       1.19
 +++ dev/ic/i82596.c    3 May 2009 07:48:53 -0000
 @@ -256,7 +256,7 @@
                sc->sc_rx_mbuf[sc->sc_rx_done] = new_mbuf;
                rbd->rbd_count = 0;
                rbd->rbd_size = IEE_RBD_EL | rx_map->dm_segs[0].ds_len;
 -              rbd->rbd_rb_addr = rx_map->dm_segs[0].ds_addr;
 +              rbd->rbd_rb_addr = IEE_SWAPA32(rx_map->dm_segs[0].ds_addr);
                sc->sc_rx_done = (sc->sc_rx_done + 1) % IEE_NRFD;
                rfd = SC_RFD(sc->sc_rx_done);
        }
 @@ -266,16 +266,19 @@
                /* Receive Overrun, reinit receive ring buffer. */
                for (n = 0 ; n < IEE_NRFD ; n++) {
                        SC_RFD(n)->rfd_cmd = IEE_RFD_SF;
 -                      SC_RFD(n)->rfd_link_addr = IEE_PHYS_SHMEM(IEE_RFD_OFF
 -                          + IEE_RFD_SZ * ((n + 1) % IEE_NRFD));
 -                      SC_RBD(n)->rbd_next_rbd = IEE_PHYS_SHMEM(IEE_RBD_OFF
 -                          + IEE_RBD_SZ * ((n + 1) % IEE_NRFD));
 +                      SC_RFD(n)->rfd_link_addr =
 +                          IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_RFD_OFF
 +                          + IEE_RFD_SZ * ((n + 1) % IEE_NRFD)));
 +                      SC_RBD(n)->rbd_next_rbd =
 +                          IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_RBD_OFF
 +                          + IEE_RBD_SZ * ((n + 1) % IEE_NRFD)));
                        SC_RBD(n)->rbd_size = IEE_RBD_EL |
                            sc->sc_rx_map[n]->dm_segs[0].ds_len;
                        SC_RBD(n)->rbd_rb_addr =
 -                          sc->sc_rx_map[n]->dm_segs[0].ds_addr;
 +                          IEE_SWAPA32(sc->sc_rx_map[n]->dm_segs[0].ds_addr);
                }
 -              SC_RFD(0)->rfd_rbd_addr = IEE_PHYS_SHMEM(IEE_RBD_OFF);
 +              SC_RFD(0)->rfd_rbd_addr =
 +                  IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_RBD_OFF));
                sc->sc_rx_done = 0;
                bus_dmamap_sync(sc->sc_dmat, sc->sc_shmem_map, IEE_RFD_OFF,
                    IEE_RFD_LIST_SZ + IEE_RBD_LIST_SZ, BUS_DMASYNC_PREWRITE);
 @@ -330,33 +333,33 @@
                        /* Try to get deferred packets going. */
                        iee_start(ifp);
        }
 -      if (IEE_SWAP(SC_SCB->scb_crc_err) != sc->sc_crc_err) {
 -              sc->sc_crc_err = IEE_SWAP(SC_SCB->scb_crc_err);
 +      if (IEE_SWAP32(SC_SCB->scb_crc_err) != sc->sc_crc_err) {
 +              sc->sc_crc_err = IEE_SWAP32(SC_SCB->scb_crc_err);
                printf("%s: iee_intr: crc_err=%d\n", device_xname(sc->sc_dev),
                    sc->sc_crc_err);
        }
 -      if (IEE_SWAP(SC_SCB->scb_align_err) != sc->sc_align_err) {
 -              sc->sc_align_err = IEE_SWAP(SC_SCB->scb_align_err);
 +      if (IEE_SWAP32(SC_SCB->scb_align_err) != sc->sc_align_err) {
 +              sc->sc_align_err = IEE_SWAP32(SC_SCB->scb_align_err);
                printf("%s: iee_intr: align_err=%d\n", device_xname(sc->sc_dev),
                    sc->sc_align_err);
        }
 -      if (IEE_SWAP(SC_SCB->scb_resource_err) != sc->sc_resource_err) {
 -              sc->sc_resource_err = IEE_SWAP(SC_SCB->scb_resource_err);
 +      if (IEE_SWAP32(SC_SCB->scb_resource_err) != sc->sc_resource_err) {
 +              sc->sc_resource_err = IEE_SWAP32(SC_SCB->scb_resource_err);
                printf("%s: iee_intr: resource_err=%d\n",
                    device_xname(sc->sc_dev), sc->sc_resource_err);
        }
 -      if (IEE_SWAP(SC_SCB->scb_overrun_err) != sc->sc_overrun_err) {
 -              sc->sc_overrun_err = IEE_SWAP(SC_SCB->scb_overrun_err);
 +      if (IEE_SWAP32(SC_SCB->scb_overrun_err) != sc->sc_overrun_err) {
 +              sc->sc_overrun_err = IEE_SWAP32(SC_SCB->scb_overrun_err);
                printf("%s: iee_intr: overrun_err=%d\n",
                    device_xname(sc->sc_dev), sc->sc_overrun_err);
        }
 -      if (IEE_SWAP(SC_SCB->scb_rcvcdt_err) != sc->sc_rcvcdt_err) {
 -              sc->sc_rcvcdt_err = IEE_SWAP(SC_SCB->scb_rcvcdt_err);
 +      if (IEE_SWAP32(SC_SCB->scb_rcvcdt_err) != sc->sc_rcvcdt_err) {
 +              sc->sc_rcvcdt_err = IEE_SWAP32(SC_SCB->scb_rcvcdt_err);
                printf("%s: iee_intr: rcvcdt_err=%d\n",
                    device_xname(sc->sc_dev), sc->sc_rcvcdt_err);
        }
 -      if (IEE_SWAP(SC_SCB->scb_short_fr_err) != sc->sc_short_fr_err) {
 -              sc->sc_short_fr_err = IEE_SWAP(SC_SCB->scb_short_fr_err);
 +      if (IEE_SWAP32(SC_SCB->scb_short_fr_err) != sc->sc_short_fr_err) {
 +              sc->sc_short_fr_err = IEE_SWAP32(SC_SCB->scb_short_fr_err);
                printf("%s: iee_intr: short_fr_err=%d\n",
                    device_xname(sc->sc_dev), sc->sc_short_fr_err);
        }
 @@ -476,8 +479,9 @@
                iee_cb_setup(sc, IEE_CB_CMD_CONF);
                break;
        case IEE_CB_CMD_TR:     /* Transmit */
 -              cb->cb_transmit.tx_tbd_addr = IEE_PHYS_SHMEM(IEE_TBD_OFF
 -                  + IEE_TBD_SZ * sc->sc_next_tbd);
 +              cb->cb_transmit.tx_tbd_addr =
 +                  IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_TBD_OFF
 +                  + IEE_TBD_SZ * sc->sc_next_tbd));
                cb->cb_cmd |= IEE_CB_SF; /* Always use Flexible Mode. */
                break;
        case IEE_CB_CMD_TDR:    /* Time Domain Reflectometry */
 @@ -490,8 +494,8 @@
                /* can't happen */
                break;
        }
 -      cb->cb_link_addr = IEE_PHYS_SHMEM(IEE_CB_OFF + IEE_CB_SZ *
 -          (sc->sc_next_cb + 1));
 +      cb->cb_link_addr = IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_CB_OFF + IEE_CB_SZ *
 +          (sc->sc_next_cb + 1)));
        bus_dmamap_sync(sc->sc_dmat, sc->sc_shmem_map, IEE_CB_OFF
            + IEE_CB_SZ * sc->sc_next_cb, IEE_CB_SZ, BUS_DMASYNC_PREWRITE);
        sc->sc_next_cb++;
 @@ -510,14 +514,14 @@
  
        /* Set pointer to Intermediate System Configuration Pointer. */
        /* Phys. addr. in big endian order. (Big endian as defined by Intel.) */
 -      SC_SCP->scp_iscp_addr = IEE_SWAP(IEE_PHYS_SHMEM(IEE_ISCP_OFF));
 +      SC_SCP->scp_iscp_addr = IEE_SWAP32(IEE_PHYS_SHMEM(IEE_ISCP_OFF));
        /* Set pointer to System Control Block. */
        /* Phys. addr. in big endian order. (Big endian as defined by Intel.) */
 -      SC_ISCP->iscp_scb_addr = IEE_SWAP(IEE_PHYS_SHMEM(IEE_SCB_OFF));
 +      SC_ISCP->iscp_scb_addr = IEE_SWAP32(IEE_PHYS_SHMEM(IEE_SCB_OFF));
        /* Set pointer to Receive Frame Area. (physical address) */
 -      SC_SCB->scb_rfa_addr = IEE_PHYS_SHMEM(IEE_RFD_OFF);
 +      SC_SCB->scb_rfa_addr = IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_RFD_OFF));
        /* Set pointer to Command Block. (physical address) */
 -      SC_SCB->scb_cmd_blk_addr = IEE_PHYS_SHMEM(IEE_CB_OFF);
 +      SC_SCB->scb_cmd_blk_addr = IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_CB_OFF));
  
        ifmedia_init(&sc->sc_ifmedia, 0, iee_mediachange, iee_mediastatus);
        if (media != NULL) {
 @@ -656,12 +660,12 @@
                }
                for (n = 0 ; n < sc->sc_tx_map[t]->dm_nsegs ; n++) {
                        SC_TBD(sc->sc_next_tbd + n)->tbd_tb_addr =
 -                          sc->sc_tx_map[t]->dm_segs[n].ds_addr;
 +                          IEE_SWAPA32(sc->sc_tx_map[t]->dm_segs[n].ds_addr);
                        SC_TBD(sc->sc_next_tbd + n)->tbd_size =
                            sc->sc_tx_map[t]->dm_segs[n].ds_len;
                        SC_TBD(sc->sc_next_tbd + n)->tbd_link_addr =
 -                          IEE_PHYS_SHMEM(IEE_TBD_OFF + IEE_TBD_SZ
 -                          * (sc->sc_next_tbd + n + 1));
 +                          IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_TBD_OFF + IEE_TBD_SZ
 +                          * (sc->sc_next_tbd + n + 1)));
                }
                SC_TBD(sc->sc_next_tbd + n - 1)->tbd_size |= IEE_CB_EL;
                bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_map[t], 0,
 @@ -778,11 +782,13 @@
        memset(SC_RBD(0), 0, IEE_RBD_LIST_SZ);
        for (r = 0 ; r < IEE_NRFD ; r++) {
                SC_RFD(r)->rfd_cmd = IEE_RFD_SF;
 -              SC_RFD(r)->rfd_link_addr = IEE_PHYS_SHMEM(IEE_RFD_OFF
 -                  + IEE_RFD_SZ * ((r + 1) % IEE_NRFD));
 -
 -              SC_RBD(r)->rbd_next_rbd = IEE_PHYS_SHMEM(IEE_RBD_OFF
 -                  + IEE_RBD_SZ * ((r + 1) % IEE_NRFD));
 +              SC_RFD(r)->rfd_link_addr =
 +                  IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_RFD_OFF
 +                  + IEE_RFD_SZ * ((r + 1) % IEE_NRFD)));
 +
 +              SC_RBD(r)->rbd_next_rbd =
 +                  IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_RBD_OFF
 +                  + IEE_RBD_SZ * ((r + 1) % IEE_NRFD)));
                if (sc->sc_rx_mbuf[r] == NULL) {
                        MGETHDR(sc->sc_rx_mbuf[r], M_DONTWAIT, MT_DATA);
                        if (sc->sc_rx_mbuf[r] == NULL) {
 @@ -824,9 +830,10 @@
                bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_map[r], 0,
                    sc->sc_rx_mbuf[r]->m_ext.ext_size, BUS_DMASYNC_PREREAD);
                SC_RBD(r)->rbd_size = sc->sc_rx_map[r]->dm_segs[0].ds_len;
 -              SC_RBD(r)->rbd_rb_addr= sc->sc_rx_map[r]->dm_segs[0].ds_addr;
 +              SC_RBD(r)->rbd_rb_addr =
 +                  IEE_SWAPA32(sc->sc_rx_map[r]->dm_segs[0].ds_addr);
        }
 -      SC_RFD(0)->rfd_rbd_addr = IEE_PHYS_SHMEM(IEE_RBD_OFF);
 +      SC_RFD(0)->rfd_rbd_addr = IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_RBD_OFF));
        if (err != 0) {
                for (n = 0 ; n < r; n++) {
                        m_freem(sc->sc_rx_mbuf[n]);
 @@ -860,7 +867,7 @@
        sc->sc_cf[12] = IEE_CF_12_DEF;
        sc->sc_cf[13] = IEE_CF_13_DEF;
        iee_cb_setup(sc, IEE_CB_CMD_CONF | IEE_CB_S | IEE_CB_EL);
 -      SC_SCB->scb_rfa_addr = IEE_PHYS_SHMEM(IEE_RFD_OFF);
 +      SC_SCB->scb_rfa_addr = IEE_SWAPA32(IEE_PHYS_SHMEM(IEE_RFD_OFF));
        bus_dmamap_sync(sc->sc_dmat, sc->sc_shmem_map, 0, IEE_SHMEM_MAX,
            BUS_DMASYNC_PREWRITE);
        (sc->sc_iee_cmd)(sc, IEE_SCB_CUC_EXE | IEE_SCB_RUC_ST);
 Index: dev/ic/i82596var.h
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ic/i82596var.h,v
 retrieving revision 1.10
 diff -u -r1.10 i82596var.h
 --- dev/ic/i82596var.h 4 Apr 2008 17:03:42 -0000       1.10
 +++ dev/ic/i82596var.h 3 May 2009 07:48:53 -0000
 @@ -189,10 +189,23 @@
  
  /* Flags */
  #define IEE_NEED_SWAP 0x01
 -#define       IEE_WANT_MCAST  0x02
 +#define IEE_WANT_MCAST        0x02
 +#define IEE_REV_A     0x04
  
 -#define IEE_SWAP(x)   ((sc->sc_flags & IEE_NEED_SWAP) == 0 ? x :      \
 -                      (((x) << 16) | ((x) >> 16)))
 +/*
 + * Rev A1 chip doesn't have 32-bit BE mode and all 32 bit pointers are
 + * treated as two 16-bit big endian entities.
 + */
 +#define IEE_SWAPA32(x)        ((sc->sc_flags & (IEE_NEED_SWAP|IEE_REV_A)) ==  
\
 +                          (IEE_NEED_SWAP|IEE_REV_A) ?                 \
 +                          (((x) << 16) | ((x) >> 16)) : (x))
 +/*
 + * The SCB absolute address and statistical counters are
 + * always treated as two 16-bit big endian entities
 + * even in 32-bit BE mode supported by Rev B and C chips.
 + */
 +#define IEE_SWAP32(x) ((sc->sc_flags & IEE_NEED_SWAP) != 0 ?          \
 +                          (((x) << 16) | ((x) >> 16)) : (x))
  #define IEE_PHYS_SHMEM(x) ((uint32_t) (sc->sc_shmem_map->dm_segs[0].ds_addr \
                        + (x)))
  
 Index: arch/hp700/gsc/if_iee_gsc.c
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/hp700/gsc/if_iee_gsc.c,v
 retrieving revision 1.7
 diff -u -r1.7 if_iee_gsc.c
 --- arch/hp700/gsc/if_iee_gsc.c        4 Apr 2008 17:03:42 -0000       1.7
 +++ arch/hp700/gsc/if_iee_gsc.c        3 May 2009 07:48:53 -0000
 @@ -194,7 +194,8 @@
        struct gsc_attach_args *ga = aux;
  
        if (ga->ga_type.iodc_type == HPPA_TYPE_FIO
 -          && ga->ga_type.iodc_sv_model == HPPA_FIO_GLAN)
 +          && (ga->ga_type.iodc_sv_model == HPPA_FIO_LAN
 +          || ga->ga_type.iodc_sv_model == HPPA_FIO_GLAN))
                /* beat old ie(4) i82586 driver */
                return 10;
        return 0;
 @@ -216,7 +217,6 @@
                sc->sc_type = I82596_DX;        /* ASP(2) based */
        else
                sc->sc_type = I82596_CA;        /* LASI based */
 -      sc->sc_flags = IEE_NEED_SWAP;
        /*
         * Pre PA7100LC CPUs don't support uncacheable mappings. So make 
         * descriptors align to cache lines. Needed to avoid race conditions 
 @@ -266,8 +266,24 @@
        memset(sc->sc_shmem_addr, 0, IEE_SHMEM_MAX);
  
        /* Setup SYSBUS byte. */
 -      SC_SCP->scp_sysbus = IEE_SYSBUS_BE | IEE_SYSBUS_INT | 
 -          IEE_SYSBUS_TRG | IEE_SYSBUS_LIEAR | IEE_SYSBUS_STD;
 +      if (ga->ga_type.iodc_sv_model == HPPA_FIO_LAN) {
 +              /*
 +               * Some earlier machines have 82596DX Rev A1 chip
 +               * which doesn't have IEE_SYSBUS_BE for 32-bit BE pointers.
 +               *
 +               * XXX: How can we detect chip revision at runtime?
 +               *      Should we check cpu_models instead?
 +               *      715/50, 735/99: Rev A1? (per PR port-hp700/35531)
 +               *      735/125: Rev C
 +               */
 +              SC_SCP->scp_sysbus = IEE_SYSBUS_INT | 
 +                  IEE_SYSBUS_TRG | IEE_SYSBUS_LIEAR | IEE_SYSBUS_STD;
 +              sc->sc_flags = IEE_NEED_SWAP | IEE_REV_A;
 +      } else {
 +              SC_SCP->scp_sysbus = IEE_SYSBUS_BE | IEE_SYSBUS_INT | 
 +                  IEE_SYSBUS_TRG | IEE_SYSBUS_LIEAR | IEE_SYSBUS_STD;
 +              sc->sc_flags = IEE_NEED_SWAP;
 +      }
  
        sc_gsc->sc_ih = hp700_intr_establish(self, IPL_NET,
            iee_intr, sc, ga->ga_int_reg, ga->ga_irq);
 
 ---
 Izumi Tsutsui
 


Home | Main Index | Thread Index | Old Index