168349Sobrien/* $NetBSD: if_le.c,v 1.18 2010/01/19 22:06:21 pooka Exp $ */ 268349Sobrien 368349Sobrien/*- 468349Sobrien * Copyright (c) 1996 The NetBSD Foundation, Inc. 568349Sobrien * All rights reserved. 668349Sobrien * 768349Sobrien * This code is derived from software contributed to The NetBSD Foundation 868349Sobrien * by Adam Glass and Gordon W. Ross. 968349Sobrien * 1068349Sobrien * Redistribution and use in source and binary forms, with or without 11133359Sobrien * modification, are permitted provided that the following conditions 1268349Sobrien * are met: 1368349Sobrien * 1. Redistributions of source code must retain the above copyright 1468349Sobrien * notice, this list of conditions and the following disclaimer. 1568349Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1668349Sobrien * notice, this list of conditions and the following disclaimer in the 1768349Sobrien * documentation and/or other materials provided with the distribution. 18133359Sobrien * 19133359Sobrien * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20133359Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21133359Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22133359Sobrien * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23133359Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24133359Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25133359Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26133359Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27133359Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28169942Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29133359Sobrien * POSSIBILITY OF SUCH DAMAGE. 30133359Sobrien */ 31133359Sobrien 32133359Sobrien/* 3368349Sobrien * news68k/dev/if_le.c - based on newsmips/dev/if_le.c 3468349Sobrien */ 3568349Sobrien 3668349Sobrien#include <sys/cdefs.h> 3768349Sobrien__KERNEL_RCSID(0, "$NetBSD: if_le.c,v 1.18 2010/01/19 22:06:21 pooka Exp $"); 3868349Sobrien 3968349Sobrien#include "opt_inet.h" 4068349Sobrien 41133359Sobrien#include <sys/param.h> 4268349Sobrien#include <sys/systm.h> 4368349Sobrien#include <sys/mbuf.h> 4468349Sobrien#include <sys/socket.h> 4568349Sobrien#include <sys/device.h> 4668349Sobrien 4768349Sobrien#include <net/if.h> 48133359Sobrien#include <net/if_ether.h> 49133359Sobrien#include <net/if_media.h> 50133359Sobrien 51133359Sobrien#ifdef INET 52133359Sobrien#include <netinet/in.h> 53133359Sobrien#include <netinet/if_inarp.h> 54133359Sobrien#endif 55133359Sobrien 56133359Sobrien#include <machine/cpu.h> 57133359Sobrien 58169942Sobrien#include <news68k/dev/hbvar.h> 59133359Sobrien 60133359Sobrien#include <dev/ic/lancereg.h> 61133359Sobrien#include <dev/ic/lancevar.h> 62133359Sobrien#include <dev/ic/am7990reg.h> 6368349Sobrien#include <dev/ic/am7990var.h> 6468349Sobrien 6568349Sobrien#include "ioconf.h" 6668349Sobrien 6768349Sobrien/* 6868349Sobrien * LANCE registers. 6968349Sobrien * The real stuff is in dev/ic/am7990reg.h 70133359Sobrien */ 71133359Sobrienstruct lereg1 { 72133359Sobrien volatile uint16_t ler1_rdp; /* data port */ 73133359Sobrien volatile uint16_t ler1_rap; /* register select port */ 74133359Sobrien}; 75133359Sobrien 7668349Sobrien/* 7768349Sobrien * Ethernet software status per interface. 7868349Sobrien * The real stuff is in dev/ic/am7990var.h 7968349Sobrien */ 8068349Sobrienstruct le_softc { 8168349Sobrien struct am7990_softc sc_am7990; /* glue to MI code */ 8268349Sobrien 8368349Sobrien struct lereg1 *sc_r1; /* LANCE registers */ 8468349Sobrien}; 8568349Sobrien 8668349Sobrienstatic int le_match(device_t, cfdata_t, void *); 8768349Sobrienstatic void le_attach(device_t, device_t, void *); 8868349Sobrien 8968349SobrienCFATTACH_DECL_NEW(le, sizeof(struct le_softc), 9068349Sobrien le_match, le_attach, NULL, NULL); 9168349Sobrien 9268349Sobrienextern const uint8_t *idrom_addr; 9368349Sobrienextern uint32_t lance_mem_phys; 9468349Sobrien 9568349Sobrien#if defined(_KERNEL_OPT) 9668349Sobrien#include "opt_ddb.h" 9768349Sobrien#endif 9868349Sobrien 9968349Sobrien#ifdef DDB 10068349Sobrien#define integrate 10168349Sobrien#define hide 10268349Sobrien#else 103133359Sobrien#define integrate static inline 104133359Sobrien#define hide static 105133359Sobrien#endif 10668349Sobrien 107133359Sobrienhide void lewrcsr(struct lance_softc *, uint16_t, uint16_t); 10868349Sobrienhide uint16_t lerdcsr(struct lance_softc *, uint16_t); 109133359Sobrienint leintr(int); 110133359Sobrien 111133359Sobrienhide void 112133359Sobrienlewrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) 11368349Sobrien{ 114133359Sobrien struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; 11568349Sobrien 11668349Sobrien ler1->ler1_rap = port; 11768349Sobrien ler1->ler1_rdp = val; 11868349Sobrien} 11968349Sobrien 12068349Sobrienhide uint16_t 12168349Sobrienlerdcsr(struct lance_softc *sc, uint16_t port) 12268349Sobrien{ 12368349Sobrien struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; 12468349Sobrien uint16_t val; 125133359Sobrien 12668349Sobrien ler1->ler1_rap = port; 12768349Sobrien val = ler1->ler1_rdp; 128133359Sobrien return val; 12968349Sobrien} 130133359Sobrien 13168349Sobrienint 132133359Sobrienle_match(device_t parent, cfdata_t cf, void *aux) 133133359Sobrien{ 134159764Sobrien struct hb_attach_args *ha = aux; 135133359Sobrien int addr; 13668349Sobrien 137133359Sobrien if (strcmp(ha->ha_name, "le")) 13868349Sobrien return 0; 139133359Sobrien 14068349Sobrien addr = (ha->ha_address); 141133359Sobrien 142133359Sobrien if (badaddr((void *)addr, 1)) 143133359Sobrien return 0; 14468349Sobrien 145133359Sobrien return 1; 14668349Sobrien} 147133359Sobrien 14868349Sobrienvoid 149133359Sobrienle_attach(device_t parent, device_t self, void *aux) 150133359Sobrien{ 151133359Sobrien struct le_softc *lesc = device_private(self); 15268349Sobrien struct lance_softc *sc = &lesc->sc_am7990.lsc; 153133359Sobrien struct hb_attach_args *ha = aux; 15469216Sobrien const uint8_t *p; 15569216Sobrien 15669216Sobrien sc->sc_dev = self; 15768349Sobrien lesc->sc_r1 = (void *)(ha->ha_address); 158133359Sobrien 15968349Sobrien if (ISIIOPA(ha->ha_address)) { 160133359Sobrien sc->sc_mem = (u_char *)(lance_mem_phys); 16168349Sobrien p = idrom_addr + 0x10; 16268349Sobrien } else { 16368349Sobrien sc->sc_mem = lesc->sc_r1 - 0x10000; 16468349Sobrien p = (const uint8_t *)(lesc->sc_r1 + 0x8010); 16568349Sobrien } 16668349Sobrien 167133359Sobrien sc->sc_memsize = 0x4000; /* 16K */ 16868349Sobrien sc->sc_addr = lance_mem_phys & 0x00ffffff; 169133359Sobrien sc->sc_conf3 = LE_C3_BSWP|LE_C3_BCON; 17068349Sobrien 17168349Sobrien sc->sc_enaddr[0] = (*p++ << 4); 17268349Sobrien sc->sc_enaddr[0] |= *p++ & 0x0f; 17368349Sobrien sc->sc_enaddr[1] = (*p++ << 4); 17468349Sobrien sc->sc_enaddr[1] |= *p++ & 0x0f; 175133359Sobrien sc->sc_enaddr[2] = (*p++ << 4); 176133359Sobrien sc->sc_enaddr[2] |= *p++ & 0x0f; 177133359Sobrien sc->sc_enaddr[3] = (*p++ << 4); 17869216Sobrien sc->sc_enaddr[3] |= *p++ & 0x0f; 179133359Sobrien sc->sc_enaddr[4] = (*p++ << 4); 180133359Sobrien sc->sc_enaddr[4] |= *p++ & 0x0f; 181133359Sobrien sc->sc_enaddr[5] = (*p++ << 4); 182133359Sobrien sc->sc_enaddr[5] |= *p++ & 0x0f; 183133359Sobrien 184133359Sobrien sc->sc_copytodesc = lance_copytobuf_contig; 185133359Sobrien sc->sc_copyfromdesc = lance_copyfrombuf_contig; 186133359Sobrien sc->sc_copytobuf = lance_copytobuf_contig; 187133359Sobrien sc->sc_copyfrombuf = lance_copyfrombuf_contig; 18869216Sobrien sc->sc_zerobuf = lance_zerobuf_contig; 18980588Sobrien 19080588Sobrien sc->sc_rdcsr = lerdcsr; 19169216Sobrien sc->sc_wrcsr = lewrcsr; 19269216Sobrien sc->sc_hwinit = NULL; 19380588Sobrien 19469216Sobrien am7990_config(&lesc->sc_am7990); 19569216Sobrien} 19669216Sobrien 19769216Sobrienint 19869216Sobrienleintr(int unit) 19969216Sobrien{ 20069216Sobrien struct am7990_softc *sc; 201133359Sobrien 202133359Sobrien if (unit >= le_cd.cd_ndevs) /* XXX */ 203133359Sobrien return 0; 204133359Sobrien 205133359Sobrien sc = device_lookup_private(&le_cd, unit); 206133359Sobrien return am7990_intr(sc); 207133359Sobrien} 208133359Sobrien