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