/*
* Copyright (c) 2003 Jochen Kunz.
* 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.
* 3. The name of Jochen Kunz may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY JOCHEN KUNZ
* ``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 JOCHEN KUNZ
* 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.
*/
/*
* hppa GSC bus MD frontend for the iee(4) Intel i82596 Ethernet driver.
*/
int iee_gsc_cmd(struct iee_softc *, uint32_t);
int iee_gsc_reset(struct iee_softc *);
int
iee_gsc_cmd(struct iee_softc *sc, uint32_t cmd)
{
struct iee_gsc_softc *sc_gsc = (struct iee_gsc_softc *)sc;
int n;
uint16_t ack;
SC_SCB(sc)->scb_cmd = cmd;
IEE_SCBSYNC(sc, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
/* Issue a Channel Attention to force the chip to read the cmd. */
bus_space_write_4(sc_gsc->sc_iot, sc_gsc->sc_ioh, IEE_GSC_CHANATT, 0);
/* Wait for the cmd to finish */
for (n = 0 ; n < 100000; n++) {
DELAY(1);
IEE_SCBSYNC(sc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
ack = SC_SCB(sc)->scb_cmd;
IEE_SCBSYNC(sc, BUS_DMASYNC_PREREAD);
if (ack == 0)
break;
}
if (n < 100000)
return 0;
printf("%s: iee_gsc_cmd: timeout n=%d\n", device_xname(sc->sc_dev), n);
return -1;
}
int
iee_gsc_reset(struct iee_softc *sc)
{
struct iee_gsc_softc *sc_gsc = (struct iee_gsc_softc *)sc;
int n;
uint32_t cmd;
uint16_t ack;
/* Make sure the busy byte is set and the cache is flushed. */
SC_ISCP(sc)->iscp_busy = IEE_ISCP_BUSY;
IEE_ISCPSYNC(sc, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
/* Setup the PORT Command with pointer to SCP. */
cmd = IEE_PORT_SCP | IEE_PHYS_SHMEM(sc->sc_scp_off);
/* Write a word to IEE_GSC_RESET to initiate a Hardware reset. */
bus_space_write_4(sc_gsc->sc_iot, sc_gsc->sc_ioh, IEE_GSC_RESET, 0);
DELAY(1000);
/* Write it to the chip, it wants this in two 16 bit parts. */
if (sc->sc_type == I82596_CA) {
bus_space_write_4(sc_gsc->sc_iot, sc_gsc->sc_ioh, IEE_GSC_PORT,
(cmd & 0xffff));
DELAY(1000);
bus_space_write_4(sc_gsc->sc_iot, sc_gsc->sc_ioh, IEE_GSC_PORT,
(cmd >> 16));
} else {
bus_space_write_4(sc_gsc->sc_iot, sc_gsc->sc_ioh, IEE_GSC_PORT,
(cmd >> 16));
DELAY(1000);
bus_space_write_4(sc_gsc->sc_iot, sc_gsc->sc_ioh, IEE_GSC_PORT,
(cmd & 0xffff));
}
DELAY(1000);
/* Issue a Channel Attention to read SCP */
bus_space_write_4(sc_gsc->sc_iot, sc_gsc->sc_ioh, IEE_GSC_CHANATT, 0);
/* Wait for the chip to initialize and read SCP and ISCP. */
for (n = 0 ; n < 1000; n++) {
IEE_ISCPSYNC(sc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
ack = SC_ISCP(sc)->iscp_busy;
IEE_ISCPSYNC(sc, BUS_DMASYNC_PREREAD);
if (ack != IEE_ISCP_BUSY)
break;
DELAY(100);
}
if (n < 1000) {
/* ACK interrupts we may have caused */
(sc->sc_iee_cmd)(sc, IEE_SCB_ACK);
return 0;
}
printf("%s: iee_gsc_reset timeout busy=0x%x\n",
device_xname(sc->sc_dev), SC_ISCP(sc)->iscp_busy);
return -1;
}