summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2004-12-02 02:28:36 +0000
committerBrad Smith <brad@cvs.openbsd.org>2004-12-02 02:28:36 +0000
commit5be4aaa7d145a69c784aa2e4ac65453b5c39e9d3 (patch)
tree859f5bf9feb8dcc1b64decb4031450fed2f81f7c /sys/dev
parenteb3cedd43561d5d9e147e965d5ec78333019d2b8 (diff)
rev 1.126
Ignore CSR13, CSR14, CSR15 'Media Specific Data' registers for 21143 based cards which use SIA mode. This fixes 10mbit mode for ZNYX ZX346Q cards and other 21143 based cards. rev 1.108 Only use a SIA/SYM media info block if no MII block is detected. The submitter of PR 32118 told me that this patch also fixes autoselecting for znyx 4 port cards (10baseT, 100baseTX did work already). From FreeBSD ok deraadt@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/dc.c65
-rw-r--r--sys/dev/ic/dcreg.h16
2 files changed, 65 insertions, 16 deletions
diff --git a/sys/dev/ic/dc.c b/sys/dev/ic/dc.c
index 9d56875cee3..483d4773c8e 100644
--- a/sys/dev/ic/dc.c
+++ b/sys/dev/ic/dc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dc.c,v 1.75 2004/11/28 02:10:59 brad Exp $ */
+/* $OpenBSD: dc.c,v 1.76 2004/12/02 02:28:35 brad Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@@ -1453,20 +1453,37 @@ dc_decode_leaf_sia(sc, l)
if (m == NULL)
return;
bzero(m, sizeof(struct dc_mediainfo));
- if (l->dc_sia_code == DC_SIA_CODE_10BT)
+ switch (l->dc_sia_code & ~DC_SIA_CODE_EXT) {
+ case DC_SIA_CODE_10BT:
m->dc_media = IFM_10_T;
-
- if (l->dc_sia_code == DC_SIA_CODE_10BT_FDX)
+ break;
+ case DC_SIA_CODE_10BT_FDX:
m->dc_media = IFM_10_T|IFM_FDX;
-
- if (l->dc_sia_code == DC_SIA_CODE_10B2)
+ break;
+ case DC_SIA_CODE_10B2:
m->dc_media = IFM_10_2;
-
- if (l->dc_sia_code == DC_SIA_CODE_10B5)
+ break;
+ case DC_SIA_CODE_10B5:
m->dc_media = IFM_10_5;
+ break;
+ default:
+ break;
+ }
- m->dc_gp_len = 2;
- m->dc_gp_ptr = (u_int8_t *)&l->dc_sia_gpio_ctl;
+ /*
+ * We need to ignore CSR13, CSR14, CSR15 for SIA mode.
+ * Things apparently already work for cards that do
+ * supply Media Specific Data.
+ */
+ if (l->dc_sia_code & DC_SIA_CODE_EXT) {
+ m->dc_gp_len = 2;
+ m->dc_gp_ptr =
+ (u_int8_t *)&l->dc_un.dc_sia_ext.dc_sia_gpio_ctl;
+ } else {
+ m->dc_gp_len = 2;
+ m->dc_gp_ptr =
+ (u_int8_t *)&l->dc_un.dc_sia_noext.dc_sia_gpio_ctl;
+ }
m->dc_next = sc->dc_mi;
sc->dc_mi = m;
@@ -1550,12 +1567,32 @@ dc_parse_21143_srom(sc)
struct dc_eblock_hdr *hdr;
int i, loff;
char *ptr;
+ int have_mii;
+ have_mii = 0;
loff = sc->dc_srom[27];
lhdr = (struct dc_leaf_hdr *)&(sc->dc_srom[loff]);
ptr = (char *)lhdr;
ptr += sizeof(struct dc_leaf_hdr) - 1;
+ /*
+ * Look if we got a MII media block.
+ */
+ for (i = 0; i < lhdr->dc_mcnt; i++) {
+ hdr = (struct dc_eblock_hdr *)ptr;
+ if (hdr->dc_type == DC_EBLOCK_MII)
+ have_mii++;
+
+ ptr += (hdr->dc_len & 0x7F);
+ ptr++;
+ }
+
+ /*
+ * Do the same thing again. Only use SIA and SYM media
+ * blocks if no MII media block is available.
+ */
+ ptr = (char *)lhdr;
+ ptr += sizeof(struct dc_leaf_hdr) - 1;
for (i = 0; i < lhdr->dc_mcnt; i++) {
hdr = (struct dc_eblock_hdr *)ptr;
switch(hdr->dc_type) {
@@ -1563,10 +1600,14 @@ dc_parse_21143_srom(sc)
dc_decode_leaf_mii(sc, (struct dc_eblock_mii *)hdr);
break;
case DC_EBLOCK_SIA:
- dc_decode_leaf_sia(sc, (struct dc_eblock_sia *)hdr);
+ if (! have_mii)
+ dc_decode_leaf_sia(sc,
+ (struct dc_eblock_sia *)hdr);
break;
case DC_EBLOCK_SYM:
- dc_decode_leaf_sym(sc, (struct dc_eblock_sym *)hdr);
+ if (! have_mii)
+ dc_decode_leaf_sym(sc,
+ (struct dc_eblock_sym *)hdr);
break;
default:
/* Don't care. Yet. */
diff --git a/sys/dev/ic/dcreg.h b/sys/dev/ic/dcreg.h
index 408afc17967..10999a4cac9 100644
--- a/sys/dev/ic/dcreg.h
+++ b/sys/dev/ic/dcreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dcreg.h,v 1.38 2004/10/29 01:10:43 brad Exp $ */
+/* $OpenBSD: dcreg.h,v 1.39 2004/12/02 02:28:35 brad Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@@ -985,9 +985,17 @@ struct dc_eblock_hdr {
struct dc_eblock_sia {
struct dc_eblock_hdr dc_sia_hdr;
u_int8_t dc_sia_code;
- u_int8_t dc_sia_mediaspec[6]; /* CSR13, CSR14, CSR15 */
- u_int8_t dc_sia_gpio_ctl[2];
- u_int8_t dc_sia_gpio_dat[2];
+ union {
+ struct dc_sia_ext { /* if (dc_sia_code & DC_SIA_CODE_EXT) */
+ u_int8_t dc_sia_mediaspec[6]; /* CSR13, CSR14, CSR15 */
+ u_int8_t dc_sia_gpio_ctl[2];
+ u_int8_t dc_sia_gpio_dat[2];
+ } dc_sia_ext;
+ struct dc_sia_noext {
+ u_int8_t dc_sia_gpio_ctl[2];
+ u_int8_t dc_sia_gpio_dat[2];
+ } dc_sia_noext;
+ } dc_un;
};
#define DC_SIA_CODE_10BT 0x00