Added reset code and converted many panics into call to reset.

Finished ray_stop and ray_unload.

A little more macro tidying.
This commit is contained in:
Duncan Barclay 2000-03-05 22:24:30 +00:00
parent 1942c15d8e
commit bd0f7bd72d

View File

@ -50,7 +50,9 @@
*
* The first fixes the brain deadness of pccardd (where it reads the
* CIS for common memory, sets it all up and then throws it all away
* assuming the card is an ed driver...).
* assuming the card is an ed driver...). Note that this could be
* dangerous (because it doesn't interact with pccardd) if you
* use other memory mapped cards at the same time.
*
* The second option ensures that common memory is remapped whenever
* we are going to access it (we can't just do it once, as something
@ -114,14 +116,22 @@
/*
* TODO
*
* _stop
* _reset
* havenet checking
* unload
* shutdown
* _stop - mostly done
* would be nice to understand shutdown/power save to prevent RX
* _reset - done
* just needs calling in the right places
* converted most panic to resets
* may be needed in a couple of other places when I do more commands
* havenet - mostly done
* i think i've got all the places to set it right, but not so sure
* we reset it in all the right places
* _unload - done
* recreated most of stop but as card is unplugged don't try and
* access it
*
* TX bpf
* RX bpf
* shutdown
* promisoius
* multicast
* ifp->if_hdr length
@ -161,9 +171,9 @@
* 31 IOCTL calls
* 51 MBUFs dumped/packet types reported
*/
#define RAY_DEBUG 6
#define RAY_DEBUG 101
#define RAY_CCS_TIMEOUT (hz/2) /* Timeout for CCS commands - only used for downloading startup parameters */
#define RAY_DOWNLOAD_TIMEOUT (hz/2) /* Timeout for CCS commands - only used for downloading startup parameters */
#define RAY_NEED_STARTJOIN_TIMO 0 /* Might be needed with build 4 */
#define RAY_SJ_TIMEOUT (90*hz) /* Timeout for failing STARTJOIN commands - only used with RAY_NEED_STARTJOIN_TIMO */
@ -173,6 +183,11 @@
#define RAY_NEED_CM_REMAPPING 1 /* Needed until pccard maps more than one memory area */
#define RAY_DUMP_CM_ON_GIFMEDIA 1 /* Dump some common memory when the SIOCGIFMEDIA ioctl is issued - a nasty hack for debugging and will be placed by an ioctl and control program */
#define RAY_RESET_TIMEOUT (5*hz) /* Timeout for resetting the card */
#define RAY_SIMPLE_TX 1 /* Simple TX routine */
#define RAY_DECENT_TX 0 /* Decent TX routine - tbd */
/*
* XXX build options - move to LINT
*/
@ -416,6 +431,8 @@ static void ray_download_params __P((struct ray_softc *sc));
static void ray_download_timo __P((void *xsc));
static u_int8_t ray_free_ccs __P((struct ray_softc *sc, size_t ccs));
static int ray_issue_cmd __P((struct ray_softc *sc, size_t ccs, u_int track));
static void ray_reset __P((struct ray_softc *sc));
static void ray_reset_timo __P((void *xsc));
static void ray_rcs_intr __P((struct ray_softc *sc, size_t ccs));
static void ray_rx __P((struct ray_softc *sc, size_t rcs));
static void ray_start_done __P((struct ray_softc *sc, size_t ccs, u_int8_t status));
@ -473,14 +490,22 @@ static void ray_dump_mbuf __P((struct ray_softc *sc, struct mbuf *m, char *s));
bcopy((vp), (sc)->maddr + (off), (n))
/*
* Macro's
* Macro's and constants
*/
#ifndef RAY_CCS_TIMEOUT
#define RAY_CCS_TIMEOUT (hz / 2)
#ifndef RAY_DOWNLOAD_TIMEOUT
#define RAY_DOWNLOAD_TIMEOUT (hz / 2)
#endif
#ifndef RAY_START_TIMEOUT
#define RAY_START_TIMEOUT (hz / 2)
#endif
#ifndef RAY_RESET_TIMEOUT
#define RAY_RESET_TIMEOUT (10 * hz)
#endif
#if RAY_SIMPLE_TX
#define RAY_IFQ_MAXLEN (2)
#else if RAY_DECENT_TX
#define RAY_IFQ_MAXLEN (RAY_CCS_TX_LAST+1)
#endif
#define RAY_CCS_FREE(sc, ccs) \
SRAM_WRITE_FIELD_1((sc), (ccs), ray_cmd, c_status, RAY_CCS_STATUS_FREE)
#define RAY_ECF_READY(sc) (!(ray_read_reg(sc, RAY_ECFIR) & RAY_ECFIR_IRQ))
@ -533,6 +558,10 @@ ray_pccard_init (dev_p)
#if RAY_NEED_CM_FIXUP
doRemap = 0;
if (sc->md.start = 0x0) {
printf("ray%d: pccardd did not map CM - giving up\n", sc->unit);
return(ENXIO);
}
if (sc->md.flags != MDF_ACTIVE) {
printf("ray%d: Fixing up CM flags from 0x%x to 0x40\n",
sc->unit, sc->md.flags);
@ -588,19 +617,38 @@ ray_pccard_unload (dev_p)
RAY_DPRINTFN(5, ("ray%d: PCCard unload\n", dev_p->isahd.id_unit));
sc = &ray_softc[dev_p->isahd.id_unit];
ifp = &sc->arpcom.ac_if;
if (sc->gone) {
printf("ray%d: already unloaded\n", sc->unit);
return;
}
/* XXX shouldn't we call _stop? */
/* Cleardown interface */
ifp = &sc->arpcom.ac_if;
ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
if_down(ifp); /* XXX probably should be if_detach but I don't know if it works in 3.1 */
/*
* Clear out timers and sort out driver state
*/
untimeout(ray_download_timo, sc, sc->timerh);
untimeout(ray_reset_timo, sc, sc->timerh);
#if RAY_NEED_STARTJOIN_TIMO
untimeout(ray_start_join_timo, sc, sc->sj_timerh);
#endif /* RAY_NEED_STARTJOIN_TIMO */
untimeout(ray_start_timo, sc, sc->start_timerh);
sc->sc_havenet = 0;
/* Mark card as gone */
/*
* Mark as not running
*/
ifp->if_flags &= ~IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
/*
* Cleardown interface
*/
if_down(ifp); /* XXX should be if_detach for -current */
/*
* Mark card as gone
*/
sc->gone = 1;
printf("ray%d: unloaded\n", sc->unit);
@ -695,9 +743,11 @@ ray_attach (dev_p)
if (sc->gone) {
printf("ray%d: unloaded before attach!\n", sc->unit);
return(0);
return(1);
}
printf(" maddr 0x%x\n", sc->maddr);
RAY_DHEX8((u_int8_t *)sc->maddr, sizeof(sc->sc_ecf_startup));
/*
* Read startup results, check the card is okay and work out what
* version we are using.
@ -717,20 +767,18 @@ ray_attach (dev_p)
"\007RERSERVED1"
"\008TEST_COMPLETE"
);
return(0);
return(1);
}
if (sc->sc_version != RAY_ECFS_BUILD_4 &&
sc->sc_version != RAY_ECFS_BUILD_5
) {
printf("ray%d: unsupported firmware version 0x%0x\n", sc->unit,
ep->e_fw_build_string);
return(0);
return(1);
}
if (bootverbose || RAY_DEBUG) {
printf("ray%d: Start Up Results\n", sc->unit);
if (RAY_DEBUG > 10)
RAY_DHEX8((u_int8_t *)sc->maddr + RAY_ECF_TO_HOST_BASE, 0x40);
if (sc->sc_version == RAY_ECFS_BUILD_4)
printf(" Firmware version 4\n");
else
@ -789,7 +837,7 @@ ray_attach (dev_p)
ifp->if_ioctl = ray_ioctl;
ifp->if_watchdog = ray_watchdog;
ifp->if_init = ray_init;
ifp->if_snd.ifq_maxlen = RAY_CCS_TX_LAST;
ifp->if_snd.ifq_maxlen = RAY_IFQ_MAXLEN;
/*
* If this logical interface has already been attached,
@ -856,6 +904,8 @@ ray_start (ifp)
if ((ifp->if_flags & IFF_RUNNING) == 0 || !sc->sc_havenet)
return;
if (!RAY_ECF_READY(sc)) {
RAY_DPRINTFN(1, ("ray%d: ray_start busy, schedule a timeout\n",
sc->unit));
sc->start_timerh = timeout(ray_start_timo, sc, RAY_START_TIMEOUT);
return;
} else
@ -1325,10 +1375,10 @@ ray_watchdog (ifp)
/* XXX may need to have remedial action here
for example
ray_reset - may be useful elsewhere
ray_stop
...
ray_init
ray_reset
ray_stop
...
ray_init
do we only use on TX?
if so then we should clear OACTIVE etc.
@ -1474,12 +1524,16 @@ ray_init (xsc)
/*
* Network stop.
*
* Assumes that a ray_init is used to restart the card.
*
*/
static void
ray_stop (sc)
struct ray_softc *sc;
{
struct ifnet *ifp;
int s;
RAY_DPRINTFN(5, ("ray%d: Network stop\n", sc->unit));
RAY_MAP_CM(sc);
@ -1491,18 +1545,86 @@ ray_stop (sc)
ifp = &sc->arpcom.ac_if;
/* XXX how do we clear ccs etc. properly */
/* XXX how do we inhibit interrupts properly */
/* XXX do these matter are we always restated with an _init? */
/*
* Clear out timers and sort out driver state
*/
untimeout(ray_download_timo, sc, sc->timerh);
untimeout(ray_reset_timo, sc, sc->timerh);
#if RAY_NEED_STARTJOIN_TIMO
untimeout(ray_start_join_timo, sc, sc->sj_timerh);
#endif /* RAY_NEED_STARTJOIN_TIMO */
untimeout(ray_start_timo, sc, sc->start_timerh);
sc->sc_havenet = 0;
/* Mark as not running */
/*
* Inhibit card - if we can't prevent reception then do not worry;
* stopping a NIC only guarantees no TX.
*/
s = splimp();
/* XXX what does the SHUTDOWN command do? Or power saving in COR */
splx(s);
/*
* Mark as not running
*/
ifp->if_flags &= ~IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
return;
}
/*
* Reset the card
*
* I'm using the soft reset command in the COR register. I'm not sure
* if the sequence is right but it does seem to do the right thing. A
* nano second after reset is written the flashing light goes out, and
* a few seconds after the default is written the main card light goes
* out. We wait a while and then re-init the card.
*/
static void
ray_reset (sc)
struct ray_softc *sc;
{
struct ifnet *ifp;
RAY_DPRINTFN(5, ("ray%d: ray_reset\n", sc->unit));
RAY_MAP_CM(sc);
ifp = &sc->arpcom.ac_if;
if (ifp->if_flags & IFF_RUNNING)
ray_stop(sc);
printf("ray%d: resetting card\n", sc->unit);
ray_attr_write((sc), RAY_COR, RAY_COR_RESET);
ray_attr_write((sc), RAY_COR, RAY_COR_DEFAULT);
sc->timerh = timeout(ray_reset_timo, sc, RAY_RESET_TIMEOUT);
return;
}
/*
* Finishing resetting and restarting the card
*/
static void
ray_reset_timo (xsc)
void *xsc;
{
struct ray_softc *sc = xsc;
RAY_DPRINTFN(5, ("ray%d: ray_reset_timo\n", sc->unit));
RAY_MAP_CM(sc);
if (!RAY_ECF_READY(sc)) {
RAY_DPRINTFN(1, ("ray%d: ray_reset_timo still busy, re-schedule\n",
sc->unit));
sc->timerh = timeout(ray_reset_timo, sc, RAY_RESET_TIMEOUT);
return;
}
RAY_HCS_CLEAR_INTR(sc);
ray_init(sc);
return;
}
@ -1628,8 +1750,9 @@ ray_rcs_intr (sc, rcs)
break;
case RAY_ECMD_REJOIN_DONE:
RAY_DPRINTFN(20, ("ray%d: ray_rcs_intr got UPDATE_PARAMS\n",
RAY_DPRINTFN(20, ("ray%d: ray_rcs_intr got REJOIN_DONE\n",
sc->unit));
sc->sc_havenet = 1; /* Should not be here but in function */
XXX;
break;
@ -2029,11 +2152,11 @@ PUT2(MIB5(mib_cw_min), RAY_MIB_CW_MIN_V5);
MIB5(mib_privacy_can_join) = sc->sc_priv_start;
MIB5(mib_basic_rate_set[0]) = sc->sc_priv_join;
/* XXX I don't really want to panic here but we must ensure that the
* XXX card is idle - maybe stop it and reset it? */
if (!RAY_ECF_READY(sc))
panic("ray%d: ray_download_params something is already happening\n",
if (!RAY_ECF_READY(sc)) {
printf("ray%d: ray_download_params something is already happening\n",
sc->unit);
ray_reset(sc);
}
if (sc->sc_version == RAY_ECFS_BUILD_4)
ray_write_region(sc, RAY_HOST_TO_ECF_BASE,
@ -2048,14 +2171,18 @@ PUT2(MIB5(mib_cw_min), RAY_MIB_CW_MIN_V5);
* command just gets serviced, so we use a timeout to complete the
* sequence.
*/
if (!ray_alloc_ccs(sc, &sc->sc_ccs, RAY_CMD_START_PARAMS, SCP_UPD_STARTUP))
panic("ray%d: ray_download_params can't get a CCS\n", sc->unit);
if (!ray_alloc_ccs(sc, &sc->sc_ccs,
RAY_CMD_START_PARAMS, SCP_UPD_STARTUP)) {
printf("ray%d: ray_download_params can't get a CCS\n", sc->unit);
ray_reset(sc);
}
if (!ray_issue_cmd(sc, sc->sc_ccs, SCP_UPD_STARTUP))
panic("ray%d: ray_download_params can't issue command\n", sc->unit);
sc->timerh = timeout(ray_download_timo, sc, RAY_CCS_TIMEOUT);
if (!ray_issue_cmd(sc, sc->sc_ccs, SCP_UPD_STARTUP)) {
printf("ray%d: ray_download_params can't issue command\n", sc->unit);
ray_reset(sc);
}
sc->timerh = timeout(ray_download_timo, sc, RAY_DOWNLOAD_TIMEOUT);
RAY_DPRINTFN(15, ("ray%d: Download now awaiting timeout\n", sc->unit));
return;
@ -2081,10 +2208,13 @@ ray_download_timo (xsc)
cmd = SRAM_READ_FIELD_1(sc, sc->sc_ccs, ray_cmd, c_cmd);
RAY_DPRINTFN(20, ("ray%d: check rayidx %d ccs 0x%x cmd 0x%x status %d\n",
sc->unit, RAY_CCS_INDEX(sc->sc_ccs), sc->sc_ccs, cmd, status));
if ((cmd != RAY_CMD_START_PARAMS) || (status != RAY_CCS_STATUS_FREE))
printf("ray%d: Download ccs odd cmd = 0x%02x, status = 0x%02x",
if ((cmd != RAY_CMD_START_PARAMS) ||
((status != RAY_CCS_STATUS_FREE) && (status != RAY_CCS_STATUS_BUSY))
) {
printf("ray%d: Download ccs odd cmd = 0x%02x, status = 0x%02x\n",
sc->unit, cmd, status);
/*XXX so what do we do? reset or retry? */
ray_init(sc);
}
/*
* If the card is still busy, re-schedule ourself
@ -2092,7 +2222,7 @@ ray_download_timo (xsc)
if (status == RAY_CCS_STATUS_BUSY) {
RAY_DPRINTFN(1, ("ray%d: ray_download_timo still busy, re-schedule\n",
sc->unit));
sc->timerh = timeout(ray_download_timo, sc, RAY_CCS_TIMEOUT);
sc->timerh = timeout(ray_download_timo, sc, RAY_DOWNLOAD_TIMEOUT);
return;
}
@ -2109,17 +2239,21 @@ ray_download_timo (xsc)
else
cmd = RAY_CMD_JOIN_NET;
if (!ray_alloc_ccs(sc, &ccs, cmd, SCP_UPD_STARTJOIN))
panic("ray%d: ray_download_timo can't get a CCS to start/join net\n",
if (!ray_alloc_ccs(sc, &ccs, cmd, SCP_UPD_STARTJOIN)) {
printf("ray%d: ray_download_timo can't get a CCS to start/join net\n",
sc->unit);
ray_reset(sc);
}
SRAM_WRITE_FIELD_1(sc, ccs, ray_cmd_net, c_upd_param, 0);
if (!ray_issue_cmd(sc, ccs, SCP_UPD_STARTJOIN))
panic("ray%d: ray_download_timo can't issue start/join\n", sc->unit);
if (!ray_issue_cmd(sc, ccs, SCP_UPD_STARTJOIN)) {
printf("ray%d: ray_download_timo can't issue start/join\n", sc->unit);
ray_reset(sc);
}
#if RAY_NEED_STARTJOIN_TIMO
sc->sj_timerh = timeout(ray_start_join_timo, sc, RAY_CCS_TIMEOUT);
sc->sj_timerh = timeout(ray_start_join_timo, sc, RAY_SJ_TIMEOUT);
#endif /* RAY_NEED_STARTJOIN_TIMO */
RAY_DPRINTFN(15, ("ray%d: Start-join awaiting interrupt/timeout\n",
@ -2155,6 +2289,20 @@ ray_start_join_done (sc, ccs, status)
ray_cmd_done(sc, SCP_UPD_STARTJOIN);
#endif /* XXX_TRACKING */
/*
* XXX This switch and the following test are badly done. I
* XXX need to take remedial action in each case branch and
* XXX return from there. Then remove the test.
* XXX FAIL comment
* XXX if we fired the start command we successfully set the card up
* XXX so just restart ray_start_join sequence and dont reset the card
* XXX may need to split download_done for this
* XXX FREE
* XXX not sure
* XXX BUSY
* XXX maybe timeout but why would we get an interrupt when
* XXX the card is not finished?
*/
switch (status) {
case RAY_CCS_STATUS_FREE:
@ -2170,11 +2318,6 @@ ray_start_join_done (sc, ccs, status)
printf("ray%d: ray_start_join_done status is FAIL - why?\n",
sc->unit);
sc->sc_havenet = 0;
#if XXX
if we fired the start command we successfully set the card up
so just restart ray_start_join sequence and dont reset the card
may need to split download_done for this
#endif
break;
default:
@ -2182,7 +2325,6 @@ ray_start_join_done (sc, ccs, status)
sc->unit, status);
break;
}
if (status != RAY_CCS_STATUS_COMPLETE)
return;
@ -2546,4 +2688,4 @@ ray_read_reg (sc, reg)
return(byte);
}
#endif /* NRAY */
#endif /* NRAY */