[BACK]Return to if_ate.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / isa

Annotation of src/sys/dev/isa/if_ate.c, Revision 1.41

1.41    ! abs         1: /*     $NetBSD: if_ate.c,v 1.40 2004/09/14 20:20:47 drochner Exp $     */
1.19      perry       2:
1.1       mycroft     3: /*
                      4:  * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
                      5:  *
                      6:  * This software may be used, modified, copied, distributed, and sold, in
                      7:  * both source and binary form provided that the above copyright, these
                      8:  * terms and the following disclaimer are retained.  The name of the author
                      9:  * and/or the contributor may not be used to endorse or promote products
                     10:  * derived from this software without specific prior written permission.
                     11:  *
                     12:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND
                     13:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     14:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     15:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE
                     16:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     17:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     18:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION.
                     19:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     20:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     21:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     22:  * SUCH DAMAGE.
                     23:  */
                     24:
                     25: /*
                     26:  * Portions copyright (C) 1993, David Greenman.  This software may be used,
                     27:  * modified, copied, distributed, and sold, in both source and binary form
                     28:  * provided that the above copyright and these terms are retained.  Under no
                     29:  * circumstances is the author responsible for the proper functioning of this
                     30:  * software, nor does the author assume any responsibility for damages
                     31:  * incurred with its use.
                     32:  */
1.28      lukem      33:
                     34: #include <sys/cdefs.h>
1.41    ! abs        35: __KERNEL_RCSID(0, "$NetBSD: if_ate.c,v 1.40 2004/09/14 20:20:47 drochner Exp $");
1.1       mycroft    36:
                     37: #include <sys/param.h>
                     38: #include <sys/systm.h>
1.21      enami      39: #include <sys/device.h>
1.1       mycroft    40: #include <sys/socket.h>
                     41: #include <sys/syslog.h>
                     42:
                     43: #include <net/if.h>
1.17      is         44: #include <net/if_ether.h>
1.21      enami      45: #include <net/if_media.h>
1.1       mycroft    46:
1.21      enami      47: #include <machine/bus.h>
1.13      mycroft    48: #include <machine/intr.h>
1.1       mycroft    49:
1.3       cgd        50: #include <dev/ic/mb86960reg.h>
1.21      enami      51: #include <dev/ic/mb86960var.h>
1.1       mycroft    52:
1.21      enami      53: #include <dev/isa/isavar.h>
1.1       mycroft    54:
1.21      enami      55: int    ate_match __P((struct device *, struct cfdata *, void *));
                     56: void   ate_attach __P((struct device *, struct device *, void *));
1.1       mycroft    57:
1.21      enami      58: struct ate_softc {
                     59:        struct  mb86960_softc sc_mb86960;       /* real "mb86960" softc */
1.1       mycroft    60:
1.21      enami      61:        /* ISA-specific goo. */
                     62:        void    *sc_ih;                         /* interrupt cookie */
                     63: };
1.1       mycroft    64:
1.35      thorpej    65: CFATTACH_DECL(ate_isa, sizeof(struct ate_softc),
                     66:     ate_match, ate_attach, NULL, NULL);
1.1       mycroft    67:
1.21      enami      68: struct fe_simple_probe_struct {
                     69:        u_char port;    /* Offset from the base I/O address. */
                     70:        u_char mask;    /* Bits to be checked. */
                     71:        u_char bits;    /* Values to be compared against. */
1.1       mycroft    72: };
                     73:
1.21      enami      74: static __inline__ int fe_simple_probe __P((bus_space_tag_t,
                     75:     bus_space_handle_t, struct fe_simple_probe_struct const *));
                     76: static int ate_find __P((bus_space_tag_t, bus_space_handle_t, int *,
                     77:     int *));
                     78: static int ate_detect __P((bus_space_tag_t, bus_space_handle_t,
                     79:     u_int8_t enaddr[ETHER_ADDR_LEN]));
1.1       mycroft    80:
1.21      enami      81: static int const ate_iomap[8] = {
                     82:        0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300
                     83: };
                     84: #define NATE_IOMAP (sizeof (ate_iomap) / sizeof (ate_iomap[0]))
                     85: #define ATE_NPORTS 0x20
1.1       mycroft    86:
                     87: /*
                     88:  * Hardware probe routines.
                     89:  */
                     90:
                     91: /*
                     92:  * Determine if the device is present.
                     93:  */
                     94: int
1.21      enami      95: ate_match(parent, match, aux)
1.1       mycroft    96:        struct device *parent;
1.21      enami      97:        struct cfdata *match;
                     98:        void *aux;
1.1       mycroft    99: {
                    100:        struct isa_attach_args *ia = aux;
1.21      enami     101:        bus_space_tag_t iot = ia->ia_iot;
                    102:        bus_space_handle_t ioh;
                    103:        int i, iobase, irq, rv = 0;
                    104:        u_int8_t myea[ETHER_ADDR_LEN];
                    105:
1.30      thorpej   106:        if (ia->ia_nio < 1)
                    107:                return (0);
                    108:        if (ia->ia_nirq < 1)
                    109:                return (0);
                    110:
                    111:        if (ISA_DIRECT_CONFIG(ia))
                    112:                return (0);
                    113:
1.21      enami     114:        /* Disallow wildcarded values. */
1.40      drochner  115:        if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
1.21      enami     116:                return (0);
                    117:
                    118:        /*
                    119:         * See if the sepcified address is valid for MB86965A JLI mode.
                    120:         */
                    121:        for (i = 0; i < NATE_IOMAP; i++)
1.30      thorpej   122:                if (ate_iomap[i] == ia->ia_io[0].ir_addr)
1.21      enami     123:                        break;
                    124:        if (i == NATE_IOMAP) {
1.23      enami     125: #ifdef ATE_DEBUG
1.21      enami     126:                printf("ate_match: unknown iobase 0x%x\n", ia->ia_iobase);
                    127: #endif
                    128:                return (0);
                    129:        }
                    130:
                    131:        /* Map i/o space. */
1.30      thorpej   132:        if (bus_space_map(iot, ia->ia_io[0].ir_addr, ATE_NPORTS, 0, &ioh)) {
1.23      enami     133: #ifdef ATE_DEBUG
1.21      enami     134:                printf("ate_match: couldn't map iospace 0x%x\n",
1.30      thorpej   135:                    ia->ia_io[0].ir_addr);
1.21      enami     136: #endif
                    137:                return (0);
                    138:        }
1.1       mycroft   139:
1.21      enami     140:        if (ate_find(iot, ioh, &iobase, &irq) == 0) {
1.23      enami     141: #ifdef ATE_DEBUG
1.21      enami     142:                printf("ate_match: ate_find failed\n");
1.1       mycroft   143: #endif
1.21      enami     144:                goto out;
                    145:        }
                    146:
1.30      thorpej   147:        if (iobase != ia->ia_io[0].ir_addr) {
1.23      enami     148: #ifdef ATE_DEBUG
1.21      enami     149:                printf("ate_match: unexpected iobase in board: 0x%x\n",
                    150:                    ia->ia_iobase);
                    151: #endif
                    152:                goto out;
                    153:        }
                    154:
                    155:        if (ate_detect(iot, ioh, myea) == 0) { /* XXX necessary? */
1.23      enami     156: #ifdef ATE_DEBUG
1.21      enami     157:                printf("ate_match: ate_detect failed\n");
                    158: #endif
                    159:                goto out;
                    160:        }
                    161:
1.40      drochner  162:        if (ia->ia_irq[0].ir_irq != ISA_UNKNOWN_IRQ) {
1.30      thorpej   163:                if (ia->ia_irq[0].ir_irq != irq) {
1.21      enami     164:                        printf("ate_match: irq mismatch; "
                    165:                            "kernel configured %d != board configured %d\n",
1.30      thorpej   166:                            ia->ia_irq[0].ir_irq, irq);
1.21      enami     167:                        goto out;
                    168:                }
                    169:        } else
1.30      thorpej   170:                ia->ia_irq[0].ir_irq = irq;
                    171:
                    172:        ia->ia_nio = 1;
                    173:        ia->ia_io[0].ir_size = ATE_NPORTS;
                    174:
                    175:        ia->ia_nirq = 1;
                    176:
                    177:        ia->ia_niomem = 0;
                    178:        ia->ia_ndrq = 0;
1.1       mycroft   179:
1.21      enami     180:        rv = 1;
1.1       mycroft   181:
1.21      enami     182:  out:
                    183:        bus_space_unmap(iot, ioh, ATE_NPORTS);
                    184:        return (rv);
1.1       mycroft   185: }
                    186:
                    187: /*
                    188:  * Check for specific bits in specific registers have specific values.
                    189:  */
1.21      enami     190: static __inline__ int
                    191: fe_simple_probe (iot, ioh, sp)
                    192:        bus_space_tag_t iot;
                    193:        bus_space_handle_t ioh;
                    194:        struct fe_simple_probe_struct const *sp;
1.1       mycroft   195: {
1.21      enami     196:        u_int8_t val;
                    197:        struct fe_simple_probe_struct const *p;
1.1       mycroft   198:
                    199:        for (p = sp; p->mask != 0; p++) {
1.21      enami     200:                val = bus_space_read_1(iot, ioh, p->port);
                    201:                if ((val & p->mask) != p->bits) {
1.23      enami     202: #ifdef ATE_DEBUG
1.21      enami     203:                        printf("fe_simple_probe: %x & %x != %x\n",
                    204:                            val, p->mask, p->bits);
                    205: #endif
1.1       mycroft   206:                        return (0);
                    207:                }
                    208:        }
1.21      enami     209:
1.1       mycroft   210:        return (1);
                    211: }
                    212:
                    213: /*
                    214:  * Hardware (vendor) specific probe routines.
                    215:  */
                    216:
                    217: /*
                    218:  * Probe and initialization for Allied-Telesis AT1700/RE2000 series.
                    219:  */
1.21      enami     220: static int
                    221: ate_find(iot, ioh, iobase, irq)
                    222:        bus_space_tag_t iot;
                    223:        bus_space_handle_t ioh;
                    224:        int *iobase, *irq;
1.1       mycroft   225: {
1.36      tsutsui   226:        u_int8_t eeprom[FE_EEPROM_SIZE];
1.21      enami     227:        int n;
1.1       mycroft   228:
                    229:        static int const irqmap[4][4] = {
                    230:                {  3,  4,  5,  9 },
                    231:                { 10, 11, 12, 15 },
                    232:                {  3, 11,  5, 15 },
                    233:                { 10, 11, 14, 15 },
                    234:        };
                    235:        static struct fe_simple_probe_struct const probe_table[] = {
                    236:                { FE_DLCR2,  0x70, 0x00 },
                    237:                { FE_DLCR4,  0x08, 0x00 },
                    238:                { FE_DLCR5,  0x80, 0x00 },
                    239: #if 0
                    240:                { FE_BMPR16, 0x1B, 0x00 },
                    241:                { FE_BMPR17, 0x7F, 0x00 },
                    242: #endif
                    243:                { 0 }
                    244:        };
                    245:
1.23      enami     246: #if ATE_DEBUG >= 4
1.36      tsutsui   247:        log(LOG_INFO, "ate_find: probe (0x%x) for ATE\n", iobase);
1.1       mycroft   248: #if 0
1.21      enami     249:        fe_dump(LOG_INFO, sc);
1.1       mycroft   250: #endif
                    251: #endif
                    252:
                    253:        /*
                    254:         * We should test if MB86965A is on the base address now.
                    255:         * Unfortunately, it is very hard to probe it reliably, since
                    256:         * we have no way to reset the chip under software control.
                    257:         * On cold boot, we could check the "signature" bit patterns
                    258:         * described in the Fujitsu document.  On warm boot, however,
                    259:         * we can predict almost nothing about register values.
                    260:         */
1.21      enami     261:        if (!fe_simple_probe(iot, ioh, probe_table))
1.1       mycroft   262:                return (0);
                    263:
                    264:        /* Check if our I/O address matches config info on 86965. */
1.21      enami     265:        n = (bus_space_read_1(iot, ioh, FE_BMPR19) & FE_B19_ADDR)
                    266:            >> FE_B19_ADDR_SHIFT;
                    267:        *iobase = ate_iomap[n];
1.1       mycroft   268:
                    269:        /*
                    270:         * We are now almost sure we have an AT1700 at the given
                    271:         * address.  So, read EEPROM through 86965.  We have to write
                    272:         * into LSI registers to read from EEPROM.  I want to avoid it
1.29      wiz       273:         * at this stage, but I cannot test the presence of the chip
1.1       mycroft   274:         * any further without reading EEPROM.  FIXME.
                    275:         */
1.36      tsutsui   276:        mb86965_read_eeprom(iot, ioh, eeprom);
1.1       mycroft   277:
                    278:        /* Make sure that config info in EEPROM and 86965 agree. */
1.21      enami     279:        if (eeprom[FE_EEPROM_CONF] != bus_space_read_1(iot, ioh, FE_BMPR19)) {
                    280: #ifdef DIAGNOSTIC
                    281:                printf("ate_find: "
1.41    ! abs       282:                    "incorrect configuration in eeprom and chip\n");
1.21      enami     283: #endif
                    284:                return (0);
1.1       mycroft   285:        }
                    286:
                    287:        /*
                    288:         * Try to determine IRQ settings.
                    289:         * Different models use different ranges of IRQs.
                    290:         */
1.21      enami     291:        n = (bus_space_read_1(iot, ioh, FE_BMPR19) & FE_B19_IRQ)
                    292:            >> FE_B19_IRQ_SHIFT;
1.1       mycroft   293:        switch (eeprom[FE_ATI_EEP_REVISION] & 0xf0) {
                    294:        case 0x30:
1.21      enami     295:                *irq = irqmap[3][n];
1.1       mycroft   296:                break;
                    297:        case 0x10:
                    298:        case 0x50:
1.21      enami     299:                *irq = irqmap[2][n];
1.1       mycroft   300:                break;
                    301:        case 0x40:
                    302:        case 0x60:
                    303:                if (eeprom[FE_ATI_EEP_MAGIC] & 0x04) {
1.21      enami     304:                        *irq = irqmap[1][n];
1.1       mycroft   305:                        break;
                    306:                }
                    307:        default:
1.21      enami     308:                *irq = irqmap[0][n];
1.1       mycroft   309:                break;
                    310:        }
                    311:
1.21      enami     312:        return (1);
                    313: }
1.1       mycroft   314:
1.21      enami     315: /*
                    316:  * Determine type and ethernet address.
                    317:  */
                    318: static int
                    319: ate_detect(iot, ioh, enaddr)
                    320:        bus_space_tag_t iot;
                    321:        bus_space_handle_t ioh;
                    322:        u_int8_t enaddr[ETHER_ADDR_LEN];
                    323: {
1.36      tsutsui   324:        u_int8_t eeprom[FE_EEPROM_SIZE];
1.21      enami     325:        int type;
1.1       mycroft   326:
                    327:        /* Get our station address from EEPROM. */
1.36      tsutsui   328:        mb86965_read_eeprom(iot, ioh, eeprom);
1.27      thorpej   329:        memcpy(enaddr, eeprom + FE_ATI_EEP_ADDR, ETHER_ADDR_LEN);
1.1       mycroft   330:
                    331:        /* Make sure we got a valid station address. */
1.21      enami     332:        if ((enaddr[0] & 0x03) != 0x00 ||
                    333:            (enaddr[0] == 0x00 && enaddr[1] == 0x00 && enaddr[2] == 0x00)) {
1.23      enami     334: #ifdef ATE_DEBUG
1.36      tsutsui   335:                printf("ate_detect: invalid ethernet address\n");
1.1       mycroft   336: #endif
1.21      enami     337:                return (0);
                    338:        }
1.1       mycroft   339:
                    340:        /*
1.21      enami     341:         * Determine the card type.
1.1       mycroft   342:         */
1.21      enami     343:        switch (eeprom[FE_ATI_EEP_MODEL]) {
                    344:        case FE_ATI_MODEL_AT1700T:
                    345:                type = FE_TYPE_AT1700T;
                    346:                break;
                    347:        case FE_ATI_MODEL_AT1700BT:
                    348:                type = FE_TYPE_AT1700BT;
                    349:                break;
                    350:        case FE_ATI_MODEL_AT1700FT:
                    351:                type = FE_TYPE_AT1700FT;
                    352:                break;
                    353:        case FE_ATI_MODEL_AT1700AT:
                    354:                type = FE_TYPE_AT1700AT;
                    355:                break;
                    356:        default:
1.37      tsutsui   357:                type = FE_TYPE_AT_UNKNOWN;
1.21      enami     358:                break;
                    359:        }
1.1       mycroft   360:
1.21      enami     361:        return (type);
                    362: }
1.1       mycroft   363:
1.21      enami     364: void
                    365: ate_attach(parent, self, aux)
                    366:        struct device *parent, *self;
                    367:        void *aux;
                    368: {
                    369:        struct ate_softc *isc = (struct ate_softc *)self;
                    370:        struct mb86960_softc *sc = &isc->sc_mb86960;
                    371:        struct isa_attach_args *ia = aux;
                    372:        bus_space_tag_t iot = ia->ia_iot;
                    373:        bus_space_handle_t ioh;
                    374:        u_int8_t myea[ETHER_ADDR_LEN];
                    375:        const char *typestr;
                    376:        int type;
                    377:
                    378:        /* Map i/o space. */
1.30      thorpej   379:        if (bus_space_map(iot, ia->ia_io[0].ir_addr, ATE_NPORTS, 0, &ioh)) {
1.38      tsutsui   380:                printf(": can't map i/o space\n");
1.21      enami     381:                return;
                    382:        }
1.1       mycroft   383:
1.21      enami     384:        sc->sc_bst = iot;
                    385:        sc->sc_bsh = ioh;
1.1       mycroft   386:
1.26      jdolecek  387:        /* Determine the card type and get ethernet address. */
1.21      enami     388:        type = ate_detect(iot, ioh, myea);
                    389:        switch (type) {
                    390:        case FE_TYPE_AT1700T:
1.37      tsutsui   391:                typestr = "AT-1700T/RE2001";
1.21      enami     392:                break;
                    393:        case FE_TYPE_AT1700BT:
1.37      tsutsui   394:                typestr = "AT-1700BT/RE2003";
1.21      enami     395:                break;
                    396:        case FE_TYPE_AT1700FT:
1.37      tsutsui   397:                typestr = "AT-1700FT/RE2009";
1.21      enami     398:                break;
                    399:        case FE_TYPE_AT1700AT:
1.37      tsutsui   400:                typestr = "AT-1700AT/RE2005";
1.21      enami     401:                break;
1.37      tsutsui   402:        case FE_TYPE_AT_UNKNOWN:
                    403:                typestr = "unknown AT-1700/RE2000";
1.1       mycroft   404:                break;
                    405:
                    406:        default:
1.21      enami     407:                /* Unknown card type: maybe a new model, but... */
1.38      tsutsui   408:                printf(": where did the card go?!\n");
1.21      enami     409:                panic("unknown card");
1.1       mycroft   410:        }
                    411:
1.38      tsutsui   412:        printf(": %s Ethernet\n", typestr);
1.1       mycroft   413:
1.21      enami     414:        /* This interface is always enabled. */
1.39      tsutsui   415:        sc->sc_stat |= FE_STAT_ENABLED;
1.1       mycroft   416:
                    417:        /*
1.21      enami     418:         * Do generic MB86960 attach.
1.1       mycroft   419:         */
1.39      tsutsui   420:        mb86960_attach(sc, myea);
1.1       mycroft   421:
1.21      enami     422:        mb86960_config(sc, NULL, 0, 0);
1.1       mycroft   423:
1.21      enami     424:        /* Establish the interrupt handler. */
1.30      thorpej   425:        isc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
                    426:            IST_EDGE, IPL_NET, mb86960_intr, sc);
1.21      enami     427:        if (isc->sc_ih == NULL)
                    428:                printf("%s: couldn't establish interrupt handler\n",
                    429:                    sc->sc_dev.dv_xname);
1.1       mycroft   430: }

CVSweb <webmaster@jp.NetBSD.org>