static void floppykproc(void *) { FDrive *dp; while(waserror()) ; for(;;){ for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){ if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5 && canqlock(&fl)){ if(TK2SEC(m->ticks - dp->lasttouched) > 5) floppyoff(dp); qunlock(&fl); } } tsleep(&up->sleep, return0, 0, 1000); } }
static void floppyalarm(Alarm* a) { FDrive *dp; for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++) { if((fl.motor&MOTORBIT(dp->dev)) && TK2SEC(m->ticks - dp->lasttouched) > 5) floppyoff(dp); } alarm(5*1000, floppyalarm, 0); cancel(a); }
/* * ps/2 mouse message is three bytes * * byte 0 - 0 0 SDY SDX 1 M R L * byte 1 - DX * byte 2 - DY * * shift & right button is the same as middle button * * Intellimouse and AccuPoint with extra buttons deliver * byte 3 - 00 or 01 or FF according to extra button state. * extra buttons are mapped in this code to buttons 4 and 5. * AccuPoint generates repeated events for these buttons; * it and Intellimouse generate 'down' events only, so * user-level code is required to generate button 'up' events * if they are needed by the application. * Also on laptops with AccuPoint AND external mouse, the * controller may deliver 3 or 4 bytes according to the type * of the external mouse; code must adapt. * * On the NEC Versa series (and perhaps others?) we seem to * lose a byte from the packet every once in a while, which * means we lose where we are in the instruction stream. * To resynchronize, if we get a byte more than two seconds * after the previous byte, we assume it's the first in a packet. */ static void ps2mouseputc(int c, int shift) { static short msg[4]; static int nb; static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 3, 2, 3, 6, 7 }; static ulong lasttick; ulong m; int buttons, dx, dy; shift |= mouseshifted; m = MACHP(0)->ticks; if(TK2SEC(m - lasttick) > 2) nb = 0; lasttick = m; if(nb==0 && (c&0xc8)!=0x08) if(intellimouse && (c==0x00 || c==0x01 || c==0xFF)){ packetsize = 4; return; } msg[nb] = c; if(++nb == packetsize){ nb = 0; if(msg[0] & 0x10) msg[1] |= 0xFF00; if(msg[0] & 0x20) msg[2] |= 0xFF00; buttons = b[(msg[0]&7) | (shift ? 8 : 0)]; if(intellimouse && packetsize==4){ if((msg[3]&0xc8) == 0x08){ packetsize = 3; msg[0] = msg[3]; nb = 1; }else{ if((msg[3] >> 3) & 1) buttons |= 1<<3; else if(msg[3] & 0x7) buttons |= 1<<4; } }
long seconds(void) { return boottime + TK2SEC(MACHP(0)->ticks); }
static long conswrite(Chan *c, void *va, long n, vlong offset) { vlong t; long l, bp; char *a = va; Cmdbuf *cb; Cmdtab *ct; char buf[256]; int x; switch((ulong)c->qid.path){ case Qcons: /* * Can't page fault in putstrn, so copy the data locally. */ l = n; while(l > 0){ bp = l; if(bp > sizeof buf) bp = sizeof buf; memmove(buf, a, bp); putstrn0(a, bp, 1); a += bp; l -= bp; } break; case Qconsctl: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, a, n); buf[n] = 0; for(a = buf; a;){ if(strncmp(a, "rawon", 5) == 0){ qlock(&kbd); flushkbdline(kbdq); kbd.raw = 1; qunlock(&kbd); } else if(strncmp(a, "rawoff", 6) == 0){ qlock(&kbd); kbd.raw = 0; kbd.x = 0; qunlock(&kbd); } if(a = strchr(a, ' ')) a++; } break; case Qkeyboard: for(x=0; x<n; ) { Rune r; x += chartorune(&r, &a[x]); kbdputc(kbdq, r); } break; case Qtime: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, a, n); buf[n] = 0; t = strtoll(buf, 0, 0)/1000000; boottime = t - TK2SEC(MACHP(0)->ticks); break; case Qhostowner: if(!iseve()) error(Eperm); if(offset != 0 || n >= sizeof(buf)) error(Ebadarg); memmove(buf, a, n); buf[n] = '\0'; if(n > 0 && buf[n-1] == '\n') buf[--n] = 0; if(n <= 0) error(Ebadarg); renameuser(eve, buf); renameproguser(eve, buf); kstrdup(&eve, buf); kstrdup(&up->env->user, buf); break; case Quser: if(!iseve()) error(Eperm); if(offset != 0) error(Ebadarg); if(n <= 0 || n >= sizeof(buf)) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; if(buf[n-1] == '\n') buf[n-1] = 0; kstrdup(&up->env->user, buf); break; case Qjit: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, va, n); buf[n] = '\0'; x = atoi(buf); if(x < 0 || x > 9) error(Ebadarg); cflag = x; return n; case Qnull: break; case Qsysname: if(offset != 0) error(Ebadarg); if(n <= 0 || n >= sizeof(buf)) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; if(buf[n-1] == '\n') buf[n-1] = 0; kstrdup(&sysname, buf); break; case Qsysctl: if(!iseve()) error(Eperm); cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, sysctlcmd, nelem(sysctlcmd)); switch(ct->index){ case CMreboot: reboot(); break; case CMhalt: halt(); break; case CMpanic: panic("sysctl"); case CMconsole: consoleprint = strcmp(cb->f[1], "off") != 0; break; case CMbroken: keepbroken = 1; break; case CMnobroken: keepbroken = 0; break; } poperror(); free(cb); break; default: print("conswrite: %llud\n", c->qid.path); error(Egreg); } return n; }
/* * ps/2 mouse message is three bytes * * byte 0 - 0 0 SDY SDX 1 M R L * byte 1 - DX * byte 2 - DY * * shift & right button is the same as middle button * * Intellimouse and AccuPoint with extra buttons deliver * byte 3 - 00 or 01 or FF according to extra button state. * extra buttons are mapped in this code to buttons 4 and 5. * AccuPoint generates repeated events for these buttons; * it and Intellimouse generate 'down' events only, so * user-level code is required to generate button 'up' events * if they are needed by the application. * Also on laptops with AccuPoint AND external mouse, the * controller may deliver 3 or 4 bytes according to the type * of the external mouse; code must adapt. * * On the NEC Versa series (and perhaps others?) we seem to * lose a byte from the packet every once in a while, which * means we lose where we are in the instruction stream. * To resynchronize, if we get a byte more than two seconds * after the previous byte, we assume it's the first in a packet. */ static void ps2mouseputc(int c, int shift) { static short msg[4]; static int nb; static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 3, 2, 3, 6, 7 }; static ulong lasttick; ulong m; int buttons, dx, dy; /* * non-ps2 keyboards might not set shift * but still set mouseshifted. */ shift |= mouseshifted; /* * Resynchronize in stream with timing; see comment above. */ m = MACHP(0)->ticks; if(TK2SEC(m - lasttick) > 2) nb = 0; lasttick = m; /* * check byte 0 for consistency */ if(nb==0 && (c&0xc8)!=0x08) if(intellimouse && (c==0x00 || c==0x01 || c==0xFF)){ /* last byte of 4-byte packet */ packetsize = 4; return; } msg[nb] = c; if(++nb == packetsize){ nb = 0; if(msg[0] & 0x10) msg[1] |= 0xFF00; if(msg[0] & 0x20) msg[2] |= 0xFF00; buttons = b[(msg[0]&7) | (shift ? 8 : 0)]; if(intellimouse && packetsize==4){ if((msg[3]&0xc8) == 0x08){ /* first byte of 3-byte packet */ packetsize = 3; msg[0] = msg[3]; nb = 1; /* fall through to emit previous packet */ }else{ /* The AccuPoint on the Toshiba 34[48]0CT * encodes extra buttons as 4 and 5. They repeat * and don't release, however, so user-level * timing code is required. Furthermore, * intellimice with 3buttons + scroll give a * two's complement number in the lower 4 bits * (bit 4 is sign extension) that describes * the amount the scroll wheel has moved during * the last sample. Here we use only the sign to * decide whether the wheel is moving up or down * and generate a single button 4 or 5 click * accordingly. */ if((msg[3] >> 3) & 1) buttons |= 1<<3; else if(msg[3] & 0x7) buttons |= 1<<4; } }