/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Rafal K. Boni.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This keeps track of which ISAs have been through an ie probe sequence.
* A simple static variable isn't enough, since it's conceivable that
* a system might have more than one ISA bus.
*
* The "isa_bus" member is a pointer to the parent ISA bus device struct
* which will unique per ISA bus.
*/
#define MAXCARDS_PER_ISABUS 8 /* If you have more than 8, you lose */
switch (why) {
case CHIP_PROBE:
/* Reset to chip to see if it responds */
bus_space_write_1(esc->sc_regt, esc->sc_regh,
EF_CTRL, EF_CTRL_RESET);
DELAY(100);
bus_space_write_1(esc->sc_regt, esc->sc_regh,
EF_CTRL, EF_CTRL_NORMAL);
DELAY(100);
break;
case CARD_RESET:
/*
* This takes around 10sec, and we can get
* by quite well w/out it...
*/
break;
}
}
/* The currently selected media is always the active media. */
ifmr->ifm_active = ifm->ifm_cur->ifm_media;
}
static int
ef_match(device_t parent, cfdata_t cf, void *aux)
{
struct isa_attach_args * const ia = aux;
int idx;
struct ef_isabus *bus;
bus_space_handle_t ioh;
bus_space_tag_t iot = ia->ia_iot;
if (ISA_DIRECT_CONFIG(ia))
return 0;
if (ef_isa_buses_inited == 0) {
LIST_INIT(&ef_isa_buses);
ef_isa_buses_inited = 1;
}
/* Probe this bus if we haven't done so already. */
for (bus = ef_isa_buses.lh_first; bus != NULL;
bus = bus->isa_link.le_next) {
if (bus->isa_bus == parent)
break;
}
if (bus == NULL) {
bus_addr_t iobase;
/* Mark this bus so we don't probe it again. */
bus = malloc(sizeof(struct ef_isabus), M_DEVBUF, M_WAITOK);
bus->bus_state = 0; /* Nothing done yet */
bus->isa_bus = parent;
LIST_INSERT_HEAD(&ef_isa_buses, bus, isa_link);
if (bus_space_map(iot, ELINK_ID_PORT, 1, 0, &ioh)) {
DPRINTF(("3c507 probe: can't map Etherlink ID port\n"));
return 0;
}
/*
* Reset and put card in CONFIG state without
* changing address.
*/
elink_reset(iot, ioh, device_unit(parent));
elink_idseq(iot, ioh, ELINK_507_POLY);
elink_idseq(iot, ioh, ELINK_507_POLY);
bus_space_write_1(iot, ioh, 0, 0xff);
/* Unmap the ID port */
bus_space_unmap(iot, ioh, 1);
bus->bus_state++; /* Cards now in CONFIG state */
for (iobase = EF_IOBASE_LOW; iobase <= EF_IOBASE_HIGH;
iobase += EF_IOSIZE) {
/* Map the 507's port-space for the probe sequence. */
if (bus_space_map(iot, iobase, EF_IOSIZE,
0, &ioh) != 0)
continue;
/* Now look for the 3Com magic bytes */
if (ef_port_check(iot, ioh)) {
int irq;
uint8_t v;
bus_addr_t maddr;
bus_addr_t msiz1;
bus_space_handle_t memh;
/*
* NOP chains don't give any advantage on this card, in fact they
* seem to slow it down some. As the doctor says, "if it hurts,
* don't do it".
*/
sc->do_xmitnopchain = 0;
/* Find the cards parent bus */
for (bus = ef_isa_buses.lh_first; bus != NULL;
bus = bus->isa_link.le_next) {
if (bus->isa_bus == parent)
break;
}
if (bus == NULL)
panic("%s: Can't find parent bus!", device_xname(self));
/* If the bus hasn't been transitioned to the RUN state, do so now */
if (bus->bus_state == 1) {
if (bus_space_map(iot, ELINK_ID_PORT, 1, 0, &ioh) != 0) {
DPRINTF(("\n%s: Can't map Elink ID port!\n",
device_xname(self)));
return;
}
static int
ef_port_check(bus_space_tag_t iot, bus_space_handle_t ioh)
{
int i;
u_char ch;
const u_char *signature = EF_SIGNATURE;
for (i = 0; i < strlen(signature); i++) {
ch = bus_space_read_1(iot, ioh, i);
if (ch != signature[i])
return 0;
}
/* If card is mapped in high memory (above 15Meg), we can't use it */
ch = bus_space_read_1(iot, ioh, EF_MADDR);
if (ch & EF_MADDR_HIGH)
return 0; /* XXX: maybe we should panic?? */