+ timeout(vvtimeout, (caddr_t) 0, VV_FLYWHEEL);
+ for (i = 0; i < NVV; i++) {
+ vs = &vv_softc[i];
+ addr = (struct vvreg *)vvinfo[i]->ui_addr;
+ if ((vs->vs_if.if_flags & IFF_UP) == 0)
+ continue;
+ switch (vs->vs_major) {
+
+ /*
+ * MODE0: generally OK, just check error rate
+ */
+ case MODE0:
+ if (vs->vs_dropped < VV_ERRORTHRESHOLD) {
+ vs->vs_dropped = 0;
+ continue;
+ }
+ /* suspend reads for a while */
+ vvtrprintf("vv%d going MODE1 in vvtimeout\n",i);
+ vs->vs_major = MODE1;
+ vs->vs_iactive = PAUSE; /* no new reads */
+ vs->vs_retry = VV_MODE1ATTEMPTS;
+ vs->vs_delayclock = VV_MODE1DELAY;
+ vs->vs_minor = 0;
+ continue;
+
+ /*
+ * MODE1: excessive error rate observed
+ * Scheme: try simply suspending reads for a
+ * short while a small number of times
+ */
+ case MODE1:
+ if (vs->vs_delayclock > 0) {
+ vs->vs_delayclock--;
+ continue;
+ }
+ switch (vs->vs_minor) {
+
+ case 0: /* reenable reads */
+ vvtrprintf("vv%d M1m0\n",i);
+ vs->vs_dropped = 0;
+ vs->vs_iactive = ACTIVE;
+ vs->vs_minor = 1; /* next state */
+ ubainfo = vs->vs_ifuba.ifu_r.ifrw_info;
+ addr->vviba = (u_short) ubainfo;
+ addr->vviea = (u_short) (ubainfo >> 16);
+ addr->vviwc =
+ -(sizeof (struct vv_header) + VVMTU) >> 1;
+ addr->vvicsr = VV_RST | VV_CONF;
+ addr->vvicsr |= VV_IEN | VV_DEN | VV_ENB;
+ continue;
+
+ case 1: /* see if it worked */
+ vvtrprintf("vv%d M1m1\n",i);
+ if (vs->vs_dropped < VV_ERRORTHRESHOLD) {
+ vs->vs_dropped = 0;
+ vs->vs_major = MODE0; /* yeah!! */
+ continue;
+ }
+ if (vs->vs_retry -- > 0) {
+ vs->vs_dropped = 0;
+ vs->vs_iactive = PAUSE;
+ vs->vs_delayclock = VV_MODE1DELAY;
+ vs->vs_minor = 0; /* recheck */
+ continue;
+ }
+ vs->vs_major = MODE2;
+ vs->vs_minor = 0;
+ vs->vs_dropped = 0;
+ vs->vs_iactive = OPEN;
+ vs->vs_delayrange = VV_MODE2DELAY;
+ vs->vs_delayclock = VV_MODE2DELAY;
+ /* fall thru ... */
+ }