/*
* Copyright (c) 1998-2004 Michael Shalayeff
* All rights reserved.
*
* 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 AUTHOR ``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 AUTHOR OR HIS RELATIVES 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 MIND, 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.
*/
/*
* Referencies:
* 1. 82596DX and 82596SX High-Performance 32-bit Local Area Network Coprocessor
* Intel Corporation, November 1996, Order Number: 290219-006
*
* 2. 712 I/O Subsystem ERS Rev 1.0
* Hewlett-Packard, June 17 1992, Dwg No. A-A2263-66510-31
*/
/* Reset the adapter. */
void
ie_gsc_reset(struct ie_softc *sc, int what)
{
struct ie_gsc_softc *gsc = (struct ie_gsc_softc *)sc;
int i;
switch (what) {
case CHIP_PROBE:
bus_space_write_4(gsc->iot, gsc->ioh, IE_GSC_REG_RESET, 0);
break;
case CARD_RESET:
bus_space_write_4(gsc->iot, gsc->ioh, IE_GSC_REG_RESET, 0);
/*
* Per [2] 4.6.2.1
* delay for 10 system clocks + 5 transmit clocks,
* NB: works for system clocks over 10MHz
*/
DELAY(1000);
/*
* After the hardware reset:
* inform i825[89]6 about new SCP address,
* which must be at least 16-byte aligned
*/
ie_gsc_port(sc, IE_PORT_ALT_SCP);
ie_gsc_attend(sc, what);
for (i = 9000; i-- && ie_gsc_read16(sc, IE_ISCP_BUSY(sc->iscp));
DELAY(100))
pdcache(0, (vaddr_t)sc->sc_maddr + sc->iscp,
IE_ISCP_SZ);
#if I82596_DEBUG
if (i < 0) {
printf("timeout for PORT command (%x)%s\n",
ie_gsc_read16(sc, IE_ISCP_BUSY(sc->iscp)),
(gsc->flags & IEGSC_GECKO)? " on gecko":"");
return;
}
#endif
break;
}
}
/* Do a channel attention on the adapter. */
void
ie_gsc_attend(struct ie_softc *sc, int why)
{
struct ie_gsc_softc *gsc = (struct ie_gsc_softc *)sc;
/* Run an i82596 PORT command on the adapter. */
void
ie_gsc_port(struct ie_softc *sc, u_int cmd)
{
struct ie_gsc_softc *gsc = (struct ie_gsc_softc *)sc;
switch (cmd) {
case IE_PORT_RESET:
case IE_PORT_DUMP:
break;
case IE_PORT_SELF_TEST:
cmd |= (sc->sc_dmamap->dm_segs[0].ds_addr + 0);
break;
case IE_PORT_ALT_SCP:
cmd |= (sc->sc_dmamap->dm_segs[0].ds_addr + sc->scp);
break;
}
if (ga->ga_type.iodc_sv_model == HPPA_FIO_GLAN)
gsc->flags |= IEGSC_GECKO;
/* Map the GSC registers. */
if (bus_space_map(ga->ga_iot, ga->ga_hpa,
IE_GSC_BANK_SZ, 0, &gsc->ioh)) {
printf(": can't map i/o space\n");
return;
}
/* Set up some initial glue. */
sc->sc_dev = self;
gsc->iot = ga->ga_iot;
gsc->iemt = ga->ga_dmatag;
sc->bt = ga->ga_iot;
sc->sc_msize = IE_SIZE;
/*
* Allocate one contiguous segment of physical memory
* to be used with the i82596. Since we're running the
* chip in i82586 mode, we're restricted to 24-bit
* physical addresses.
*/
if (bus_dmamem_alloc(gsc->iemt, sc->sc_msize, PAGE_SIZE, 0,
&seg, 1, &rseg, BUS_DMA_NOWAIT | BUS_DMA_24BIT)) {
printf (": can't allocate %d bytes of DMA memory\n",
sc->sc_msize);
return;
}
/* Map that physical memory into kernel virtual space. */
if (bus_dmamem_map(gsc->iemt, &seg, rseg, sc->sc_msize,
(void **)&sc->sc_maddr, BUS_DMA_NOWAIT)) {
printf (": can't map DMA memory\n");
bus_dmamem_free(gsc->iemt, &seg, rseg);
return;
}
/* Create a DMA map for the memory. */
if (bus_dmamap_create(gsc->iemt, sc->sc_msize, rseg, sc->sc_msize,
0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) {
printf(": can't create DMA map\n");
bus_dmamem_unmap(gsc->iemt,
(void *)sc->sc_maddr, sc->sc_msize);
bus_dmamem_free(gsc->iemt, &seg, rseg);
return;
}
/* Load the mapped DMA memory into the DMA map. */
if (bus_dmamap_load(gsc->iemt, sc->sc_dmamap, sc->sc_maddr,
sc->sc_msize, NULL, BUS_DMA_NOWAIT)) {
printf(": can't load DMA map\n");
bus_dmamap_destroy(gsc->iemt, sc->sc_dmamap);
bus_dmamem_unmap(gsc->iemt,
(void *)sc->sc_maddr, sc->sc_msize);
bus_dmamem_free(gsc->iemt, &seg, rseg);
return;
}
#if 1
/* XXX - this should go away. */
sc->bh = (bus_space_handle_t)sc->sc_maddr;
#endif
/*
* We use low memory to set up SCP, ICSP and SCB data
* structures. The remaining pages become the buffer area
* (managed in i82586.c).
*/
/*
* Since we have an i82596, we can control where where
* the chip looks for SCP. We plan to use the first
* two 32-bit words of memory for the self-test, so the
* SCP can go after that.
*/
sc->scp = IE_GSC_ALIGN(8);