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



>> 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