diff options
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/dc.c | 65 | ||||
-rw-r--r-- | sys/dev/ic/dcreg.h | 16 |
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 |