summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic')
-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