/* Copyright 1991,1992 Eric R. Smith. All rights reserved. */ /* simple biosfs.c */ #include "mint.h" extern struct kerinfo kernelinfo; /* see main.c */ static long bios_root P_((int drv, fcookie *fc)); static long bios_lookup P_((fcookie *dir, const char *name, fcookie *fc)); static long bios_getxattr P_((fcookie *fc, XATTR *xattr)); static long bios_chattr P_((fcookie *fc, int attrib)); static long bios_chown P_((fcookie *fc, int uid, int gid)); static long bios_chmode P_((fcookie *fc, unsigned mode)); static long bios_rmdir P_((fcookie *dir, const char *name)); static long bios_remove P_((fcookie *dir, const char *name)); static long bios_getname P_((fcookie *root, fcookie *dir, char *pathname)); static long bios_rename P_((fcookie *olddir, char *oldname, fcookie *newdir, const char *newname)); static long bios_opendir P_((DIR *dirh, int flags)); static long bios_readdir P_((DIR *dirh, char *nm, int nmlen, fcookie *fc)); static long bios_rewinddir P_((DIR *dirh)); static long bios_closedir P_((DIR *dirh)); static long bios_pathconf P_((fcookie *dir, int which)); static long bios_dfree P_((fcookie *dir, long *buf)); static DEVDRV * bios_getdev P_((fcookie *fc, long *devspecial)); static long bios_fscntl P_((fcookie *, const char *, int, long)); static long bios_symlink P_((fcookie *, const char *, const char *)); static long bios_readlink P_((fcookie *, char *, int)); static long bios_topen P_((FILEPTR *f)); static long bios_twrite P_((FILEPTR *f, const char *buf, long bytes)); static long bios_tread P_((FILEPTR *f, char *buf, long bytes)); static long bios_nwrite P_((FILEPTR *f, const char *buf, long bytes)); static long bios_nread P_((FILEPTR *f, char *buf, long bytes)); static long bios_ioctl P_((FILEPTR *f, int mode, void *buf)); static long bios_select P_((FILEPTR *f, long p, int mode)); static void bios_unselect P_((FILEPTR *f, long p, int mode)); static long bios_tseek P_((FILEPTR *f, long where, int whence)); long null_open P_((FILEPTR *f)); long null_write P_((FILEPTR *f, const char *buf, long bytes)); long null_read P_((FILEPTR *f, char *buf, long bytes)); long null_lseek P_((FILEPTR *f, long where, int whence)); long null_ioctl P_((FILEPTR *f, int mode, void *buf)); long null_datime P_((FILEPTR *f, short *time, int rwflag)); long null_close P_((FILEPTR *f, int pid)); long null_select P_((FILEPTR *f, long p, int mode)); void null_unselect P_((FILEPTR *f, long p, int mode)); static long mouse_open P_((FILEPTR *f)); static long mouse_read P_((FILEPTR *f, char *buf, long nbytes)); static long mouse_ioctl P_((FILEPTR *f, int mode, void *buf)); static long mouse_close P_((FILEPTR *f, int pid)); static long mouse_select P_((FILEPTR *f, long p, int mode)); static void mouse_unselect P_((FILEPTR *f, long p, int mode)); /* device driver for BIOS terminals */ DEVDRV bios_tdevice = { bios_topen, bios_twrite, bios_tread, bios_tseek, bios_ioctl, null_datime, null_close, bios_select, bios_unselect }; /* device driver for BIOS devices that are not terminals */ DEVDRV bios_ndevice = { null_open, bios_nwrite, bios_nread, null_lseek, bios_ioctl, null_datime, null_close, bios_select, bios_unselect }; DEVDRV null_device = { null_open, null_write, null_read, null_lseek, null_ioctl, null_datime, null_close, null_select, null_unselect }; DEVDRV mouse_device = { mouse_open, null_write, mouse_read, null_lseek, mouse_ioctl, null_datime, mouse_close, mouse_select, mouse_unselect }; /* this special driver is checked for in dosfile.c, and indicates that * a dup operation is actually wanted rather than an open */ DEVDRV fakedev; #ifdef FASTTEXT extern DEVDRV screen_device; /* see fasttext.c */ #endif FILESYS bios_filesys = { (FILESYS *)0, 0, bios_root, bios_lookup, nocreat, bios_getdev, bios_getxattr, bios_chattr, bios_chown, bios_chmode, nomkdir, bios_rmdir, bios_remove, bios_getname, bios_rename, bios_opendir, bios_readdir, bios_rewinddir, bios_closedir, bios_pathconf, bios_dfree, nowritelabel, noreadlabel, bios_symlink, bios_readlink, nohardlink, bios_fscntl, nodskchng }; struct tty con_tty, aux_tty, midi_tty; struct tty sccb_tty, scca_tty, ttmfp_tty; #define BNAME_MAX 13 struct bios_file { char name[BNAME_MAX+1]; /* device name */ DEVDRV *device; /* device driver for device */ short private; /* extra info for device driver */ ushort flags; /* flags for device open */ struct tty *tty; /* tty structure (if appropriate) */ struct bios_file *next; }; struct bios_file BDEV[] = { /* "real" bios devices present on all machines */ {"centr", &bios_ndevice, 0, 0, 0, 0}, {"console", &bios_tdevice, 2, O_TTY, &con_tty, 0}, {"midi", &bios_tdevice, 3, O_TTY, &midi_tty, 0}, {"kbd", &bios_ndevice, 4, 0, 0, 0}, /* devices that duplicate handles */ {"prn", &fakedev, -3, 0, 0, 0}, /* handle -3 (printer) */ {"aux", &fakedev, -2, 0, 0, 0}, /* handle -2 (aux. terminal) */ {"con", &fakedev, -1, 0, 0, 0}, /* handle -1 (control terminal) */ {"tty", &fakedev, -1, 0, 0, 0}, /* the Unix name for it */ {"stdin", &fakedev, 0, 0, 0, 0}, /* handle 0 (stdin) */ {"stdout", &fakedev, 1, 0, 0, 0}, /* handle 1 (stdout) */ {"stderr", &fakedev, 2, 0, 0, 0}, /* handle 2 (stderr) */ /* other miscellaneous devices */ {"mouse", &mouse_device, 0, 0, 0, 0}, {"null", &null_device, 0, 0, 0, 0}, #ifdef FASTTEXT /* alternate console driver */ {"fasttext", &screen_device, 2, O_TTY, &con_tty, 0}, #endif /* serial port things *must* come last, because not all of these * are present on all machines (except for modem1, which does however * have a different device number on TTs and STs) */ {"modem1", &bios_tdevice, 6, O_TTY, &aux_tty, 0}, {"modem2", &bios_tdevice, 7, O_TTY, &sccb_tty, 0}, {"serial1", &bios_tdevice, 8, O_TTY, &ttmfp_tty, 0}, {"serial2", &bios_tdevice, 9, O_TTY, &scca_tty, 0}, {"", 0, 0, 0, 0, 0} }; struct bios_file *broot, *bdevlast; /* a file pointer for BIOS device 1, provided only for insurance * in case a Bconmap happens and we can't allocate a new FILEPTR; * in most cases, we'll want to build a FILEPTR in the usual * way. */ FILEPTR *defaultaux; void biosfs_init() { struct bios_file *b; broot = BDEV; for (b = broot; b->name[0]; b++) { b->next = b+1; /* if not a TT or Mega STE, adjust the MODEM1 device to be BIOS * device 1 * and ignore the remaining devices, since they're not present */ if (!has_bconmap && b->private == 6) { b->private = 1; b->next = 0; break; } /* SERIAL2 is not present on the Mega STe */ if (mch == MEGASTE && b->private == 8) { b->next = 0; break; } } bdevlast = b; if (b->name[0] == 0) { --b; b->next = 0; } defaultaux = new_fileptr(); defaultaux->links = 1; /* so it never gets freed */ defaultaux->flags = O_RDWR; defaultaux->pos = 0; defaultaux->devinfo = 0; defaultaux->fc.fs = &bios_filesys; defaultaux->fc.index = 0; defaultaux->fc.aux = 1; defaultaux->fc.dev = BIOSDRV; defaultaux->dev = &bios_ndevice; } static long bios_root(drv, fc) int drv; fcookie *fc; { if (drv == BIOSDRV) { fc->fs = &bios_filesys; fc->dev = drv; fc->index = 0L; return 0; } fc->fs = 0; return EINTRN; } static long bios_lookup(dir, name, fc) fcookie *dir; const char *name; fcookie *fc; { struct bios_file *b; TRACE("bios_lookup(%s)", name); if (dir->index != 0) { DEBUG("bios_lookup: bad directory"); return EPTHNF; } /* special case: an empty name in a directory means that directory */ /* so does "." */ if (!*name || (name[0] == '.' && name[1] == 0)) { *fc = *dir; return 0; } /* another special case: ".." could be a mount point */ if (!strcmp(name, "..")) { *fc = *dir; return EMOUNT; } for (b = broot; b; b = b->next) { if (!stricmp(b->name, name)) { fc->fs = &bios_filesys; fc->index = (long)b; fc->aux = b->private; fc->dev = dir->dev; return 0; } } DEBUG("bios_lookup: name(%s) not found", name); return EFILNF; } static long bios_getxattr(fc, xattr) fcookie *fc; XATTR *xattr; { struct bios_file *b = (struct bios_file *)fc->index; xattr->index = fc->index; xattr->dev = fc->dev; xattr->nlink = 1; xattr->uid = xattr->gid = 0; xattr->size = xattr->nblocks = 0; xattr->blksize = 1; xattr->mtime = xattr->atime = xattr->ctime = timestamp; xattr->mdate = xattr->adate = xattr->cdate = datestamp; if (fc->index == 0) { /* root directory? */ xattr->mode = S_IFDIR | DEFAULT_DIRMODE; xattr->attr = FA_DIR; } else if (b->device == 0) { /* symbolic link? */ xattr->mode = S_IFLNK | DEFAULT_DIRMODE; } else { /* BUG: U:\DEV\STDIN, U:\DEV\STDOUT, etc. might not be terminal files */ xattr->mode = S_IFCHR | DEFAULT_MODE; xattr->attr = 0; } return 0; } static long bios_chattr(fc, attrib) fcookie *fc; int attrib; { return EACCDN; } static long bios_chown(fc, uid, gid) fcookie *fc; int uid, gid; { return EINVFN; } static long bios_chmode(fc, mode) fcookie *fc; unsigned mode; { return EINVFN; } long nomkdir(dir, name, mode) fcookie *dir; const char *name; unsigned mode; { return EACCDN; } static long bios_rmdir(dir, name) fcookie *dir; const char *name; { return bios_remove(dir, name); } /* * MAJOR BUG: we don't check here for removal of devices for which there * are still open files */ static long bios_remove(dir, name) fcookie *dir; const char *name; { struct bios_file *b, **lastb; lastb = &broot; for (b = broot; b; b = *(lastb = &b->next)) { if (!stricmp(b->name, name)) break; } if (!b) return EFILNF; /* don't allow removal of the basic system devices */ if (b >= BDEV && b <= bdevlast) { return EACCDN; } *lastb = b->next; if (b->device == 0 || b->device == &bios_tdevice) kfree(b->tty); kfree(b); return 0; } static long bios_getname(root, dir, pathname) fcookie *root, *dir; char *pathname; { if (dir->index == 0) *pathname = 0; else strcpy(pathname, ((struct bios_file *)dir->index)->name); return 0; } static long bios_rename(olddir, oldname, newdir, newname) fcookie *olddir; char *oldname; fcookie *newdir; const char *newname; { struct bios_file *b; /* BUG: we should check to see if "newname" already exists */ for (b = broot; b; b = b->next) { if (!stricmp(b->name, oldname)) { strncpy(b->name, newname, BNAME_MAX); return 0; } } return EFILNF; } static long bios_opendir(dirh, flags) DIR *dirh; int flags; { if (dirh->fc.index != 0) { DEBUG("bios_opendir: bad directory"); return EPTHNF; } return 0; } static long bios_readdir(dirh, name, namelen, fc) DIR *dirh; char *name; int namelen; fcookie *fc; { struct bios_file *b; int giveindex = dirh->flags == 0; int i; b = broot; i = dirh->index++; while(i-- > 0) { if (!b) break; b = b->next; } if (!b) { return ENMFIL; } fc->fs = &bios_filesys; fc->index = (long)b; fc->aux = b->private; fc->dev = dirh->fc.dev; if (giveindex) { namelen -= sizeof(long); if (namelen <= 0) return ERANGE; *((long *)name) = (long) b; name += sizeof(long); } strncpy(name, b->name, namelen-1); if (strlen(b->name) >= namelen) return ENAMETOOLONG; return 0; } static long bios_rewinddir(dirh) DIR *dirh; { dirh->index = 0; return 0; } static long bios_closedir(dirh) DIR *dirh; { return 0; } static long bios_pathconf(dir, which) fcookie *dir; int which; { switch(which) { case -1: return DP_MAXREQ; case DP_IOPEN: return UNLIMITED; /* no limit on BIOS file descriptors */ case DP_MAXLINKS: return 1; /* no hard links available */ case DP_PATHMAX: return PATH_MAX; case DP_NAMEMAX: return BNAME_MAX; case DP_ATOMIC: return 1; /* no atomic writes */ case DP_TRUNC: return DP_AUTOTRUNC; /* names are truncated */ case DP_CASE: return DP_CASEINSENS; /* not case sensitive */ default: return EINVFN; } } static long bios_dfree(dir, buf) fcookie *dir; long *buf; { buf[0] = 0; /* number of free clusters */ buf[1] = 0; /* total number of clusters */ buf[2] = 1; /* sector size (bytes) */ buf[3] = 1; /* cluster size (sectors) */ return 0; } /* * BIOS Dcntl() calls: * Dcntl(0xde02, "U:\DEV\FOO", &foo_descr): install a new device called * "FOO", which is described by the dev_descr structure "foo_descr". * this structure has the following fields: * DEVDRV *driver the device driver itself * short dinfo info for the device driver * short flags flags for the file (e.g. O_TTY) * struct tty *tty tty structure, if appropriate * * Dcntl(0xde00, "U:\DEV\BAR", n): install a new BIOS terminal device, with * BIOS device number "n". * Dcntl(0xde01, "U:\DEV\BAR", n): install a new non-tty BIOS device, with * BIOS device number "n". */ static long bios_fscntl(dir, name, cmd, arg) fcookie *dir; const char *name; int cmd; long arg; { struct bios_file *b; if (cmd == DEV_INSTALL) { struct dev_descr *d = (struct dev_descr *)arg; b = kmalloc(SIZEOF(struct bios_file)); if (!b) return 0; strncpy(b->name, name, BNAME_MAX); b->name[BNAME_MAX] = 0; b->device = d->driver; b->private = d->dinfo; b->flags = d->flags; b->tty = d->tty; b->next = broot; broot = b; return (long)&kernelinfo; } if (cmd == DEV_NEWTTY) { b = kmalloc(SIZEOF(struct bios_file)); if (!b) return ENSMEM; b->tty = kmalloc(SIZEOF(struct tty)); if (!b->tty) { kfree(b); return ENSMEM; } strncpy(b->name, name, BNAME_MAX); b->name[BNAME_MAX] = 0; b->device = &bios_tdevice; b->private = arg; b->flags = O_TTY; *b->tty = default_tty; b->next = broot; broot = b; return 0; } if (cmd == DEV_NEWBIOS) { b = kmalloc(SIZEOF(struct bios_file)); if (!b) return ENSMEM; strncpy(b->name, name, BNAME_MAX); b->name[BNAME_MAX] = 0; b->tty = 0; b->device = &bios_ndevice; b->private = arg; b->flags = 0; b->next = broot; return 0; } return EINVFN; } static long bios_symlink(dir, name, to) fcookie *dir; const char *name, *to; { struct bios_file *b; long r; fcookie fc; r = bios_lookup(dir, name, &fc); if (r == 0) return EACCDN; /* file already exists */ if (r != EFILNF) return r; /* some other error */ b = kmalloc(SIZEOF(struct bios_file)); if (!b) return EACCDN; strncpy(b->name, name, BNAME_MAX); b->name[BNAME_MAX] = 0; b->device = 0; b->private = EINVFN; b->flags = 0; b->tty = kmalloc((long)strlen(to)+1); if (!b->tty) { kfree(b); return EACCDN; } strcpy((char *)b->tty, to); b->next = broot; broot = b; return 0; } static long bios_readlink(fc, buf, buflen) fcookie *fc; char *buf; int buflen; { struct bios_file *b = (struct bios_file *)fc->index; if (!b) return EINVFN; if (b->device) return EINVFN; strncpy(buf, (char *)b->tty, buflen); if (strlen((char *)b->tty) >= buflen) return ENAMETOOLONG; return 0; } /* * routines for file systems that don't support volume labels */ long nowritelabel(dir, name) fcookie *dir; const char *name; { return EACCDN; } long noreadlabel(dir, name, namelen) fcookie *dir; char *name; int namelen; { return EFILNF; } /* * routines for file systems that don't support links */ long nosymlink(dir, name, to) fcookie *dir; const char *name, *to; { return EINVFN; } long noreadlink(dir, buf, buflen) fcookie *dir; char *buf; int buflen; { return EINVFN; } long nohardlink(fromdir, fromname, todir, toname) fcookie *fromdir, *todir; const char *fromname, *toname; { return EINVFN; } /* dummy routine for file systems with no Fscntl commands */ long nofscntl(dir, name, cmd, arg) fcookie *dir; const char *name; int cmd; long arg; { return EINVFN; } /* * Did the disk change? Not on this drive! * However, we have to do Getbpb anyways, because someone has decided * to force a media change on our (non-existent) drive. */ long nodskchng(drv) int drv; { (void)getbpb(drv); return 0; } long nocreat(dir, name, mode, attrib, fc) fcookie *dir, *fc; const char *name; unsigned mode; int attrib; { return EACCDN; } static DEVDRV * bios_getdev(fc, devsp) fcookie *fc; long *devsp; { struct bios_file *b; b = (struct bios_file *)fc->index; if (b->device && b->device != &fakedev) *devsp = (long)b->tty; else *devsp = b->private; return b->device; /* return the device driver */ } /* * NULL device driver */ long null_open(f) FILEPTR *f; { return 0; } long null_write(f, buf, bytes) FILEPTR *f; const char *buf; long bytes; { return bytes; } long null_read(f, buf, bytes) FILEPTR *f; char *buf; long bytes; { return 0; } long null_lseek(f, where, whence) FILEPTR *f; long where; int whence; { return (where == 0) ? 0 : ERANGE; } long null_ioctl(f, mode, buf) FILEPTR *f; int mode; void *buf; { if (mode == FIONREAD) { *((long *)buf) = 0; } else if (mode == FIONWRITE) *((long *)buf) = 1; else return EINVFN; return 0; } long null_datime(f, timeptr, rwflag) FILEPTR *f; short *timeptr; int rwflag; { if (rwflag) return EACCDN; *timeptr++ = timestamp; *timeptr = datestamp; return 0; } long null_close(f, pid) FILEPTR *f; int pid; { return 0; } long null_select(f, p, mode) FILEPTR *f; long p; int mode; { return 1; /* we're always ready to read/write */ } void null_unselect(f, p, mode) FILEPTR *f; long p; int mode; { /* nothing to do */ } /* * BIOS terminal device driver */ static long bios_topen(f) FILEPTR *f; { f->flags |= O_TTY; return 0; } /* * Note: when a BIOS device is a terminal (i.e. has the O_TTY flag * set), bios_read and bios_write will only ever be called indirectly, via * tty_read and tty_write. That's why we can afford to play a bit fast and * loose with the pointers ("buf" is really going to point to a long) and * why we know that "bytes" is divisible by 4. */ static long bios_twrite(f, buf, bytes) FILEPTR *f; const char *buf; long bytes; { long *r; long ret = 0; int bdev = f->fc.aux; r = (long *)buf; while (bytes > 0) { if ( (f->flags & O_NDELAY) && !bcostat(bdev) ) break; if (bconout(bdev, (int)*r) == 0) break; r++; bytes -= 4; ret+= 4; } (void)checkkeys(); return ret; } static long bios_tread(f, buf, bytes) FILEPTR *f; char *buf; long bytes; { long *r, ret = 0; int bdev = f->fc.aux; r = (long *)buf; while (bytes > 0) { if ( (f->flags & O_NDELAY) && !bconstat(bdev) ) break; *r++ = bconin(bdev) & 0x7fffffff; bytes -= 4; ret += 4; } return ret; } /* * read/write routines for BIOS devices that aren't terminals (like the * printer & IKBD devices) */ static long bios_nwrite(f, buf, bytes) FILEPTR *f; const char *buf; long bytes; { long ret = 0; int bdev = f->fc.aux; int c; while (bytes > 0) { if ( (f->flags & O_NDELAY) && !bcostat(bdev) ) break; c = *buf++ & 0x00ff; if (bconout(bdev, c) == 0) break; bytes--; ret++; } return ret; } static long bios_nread(f, buf, bytes) FILEPTR *f; char *buf; long bytes; { long ret = 0; int bdev = f->fc.aux; while (bytes > 0) { if ( (f->flags & O_NDELAY) && !bconstat(bdev) ) break; *buf++ = bconin(bdev) & 0xff; bytes--; ret++; } return ret; } /* * BIOS terminal seek code -- this has to match the documented * way to do isatty() */ static long bios_tseek(f, where, whence) FILEPTR *f; long where; int whence; { /* terminals always are at position 0 */ return 0; } #define MAXBAUD 16 static long baudmap[MAXBAUD] = { 19200L, 9600L, 4800L, 3600L, 2400L, 2000L, 1800L, 1200L, 600L, 300L, 200L, 150L, 134L, 110L, 75L, 50L }; static long bios_ioctl(f, mode, buf) FILEPTR *f; int mode; void *buf; { long *r = (long *)buf; struct winsize *ws; char *aline; short dev; int i; if (mode == FIONREAD) { if (bconstat(f->fc.aux)) *r = 1; else *r = 0; } else if (mode == FIONWRITE) { if (bcostat(f->fc.aux)) *r = 1; else *r = 0; } else if (mode == TIOCFLUSH) { /* BUG: this should flush the input/output buffers */ return 0; } else if (mode == TIOCGWINSZ && f->fc.aux == 2) { aline = lineA0(); ws = (struct winsize *)buf; ws->ws_row = *((short *)(aline - 42)) + 1; ws->ws_col = *((short *)(aline - 44)) + 1; } else if (mode == TIOCIBAUD || mode == TIOCOBAUD) { long oldbaud, newbaud; dev = f->fc.aux; newbaud = *r; if (dev == 1 || dev >= 6) { if (has_bconmap) mapin((dev == 1) ? curproc->bconmap : dev); i = rsconf(-2, -1, -1, -1, -1, -1); if (i < 0 || i >= MAXBAUD) oldbaud = -1L; else oldbaud = baudmap[i]; *r = oldbaud; if (newbaud > 0) { for (i = 0; i < MAXBAUD; i++) { if (baudmap[i] == newbaud) { rsconf(i, -1, -1, -1, -1, -1); return 0; } } return ERANGE; } else if (newbaud == 0L) { /* drop DTR: works only on modem1 */ if (dev == 1 || dev == 6) { Ongibit(0x10); nap(30); Offgibit(0xef); } } return 0; } else if (dev == 2 || dev == 5) { /* screen: assume 9600 baud */ oldbaud = 9600L; } else if (dev == 3) { /* midi */ oldbaud = 31250L; } else { oldbaud = -1L; /* unknown speed */ } *r = oldbaud; if (newbaud > 0 && newbaud != oldbaud) return ERANGE; return 0; } else if (mode == TIOCCBRK || mode == TIOCSBRK) { unsigned long bits; dev = f->fc.aux; if (dev == 1 || dev >= 6) { if (has_bconmap) mapin((dev == 1) ? curproc->bconmap : dev); } else { return EINVFN; } bits = rsconf(-1, -1, -1, -1, -1, -1); /* get settings */ bits = (bits >> 8) & 0x0ff; /* isolate TSR byte */ if (mode == TIOCCBRK) bits &= ~8; else bits |= 8; (void)rsconf(-1, -1, -1, -1, (int)bits, -1); } else if (mode == TIOCGFLAGS || mode == TIOCSFLAGS) { unsigned short oflags, flags; unsigned long bits; unsigned char ucr; short flow; dev = f->fc.aux; if (dev == 1 || dev >= 6) { oflags = ((struct tty *)f->devinfo)->sg.sg_flags; oflags &= (T_TANDEM|T_RTSCTS); if (has_bconmap) mapin((dev == 1) ? curproc->bconmap : dev); bits = rsconf(-1, -1, -1, -1, -1, -1); /* get settings */ ucr = (bits >> 24L) & 0x0ff; /* isolate UCR byte */ oflags |= (ucr >> 3) & (TF_STOPBITS|TF_CHARBITS); if (ucr & 0x4) { /* parity on? */ oflags |= (ucr & 0x2) ? T_EVENP : T_ODDP; } if (mode == TIOCSFLAGS) { flags = (*(unsigned short *)buf); if (flags & T_EVENP) { ucr |= 0x6; } else if (flags & T_ODDP) { ucr &= ~2; ucr |= 0x4; } else { ucr &= ~6; } if (flags & TF_STOPBITS) { ucr &= ~(0x18); ucr |= (flags & TF_STOPBITS) << 3; } ucr &= ~(0x60); ucr |= (flags & TF_CHARBITS) << 3; flow = (flags & (T_RTSCTS|T_TANDEM)) >> 12L; rsconf(-1, flow, ucr, -1, -1, -1); } else { *((unsigned short *)buf) = oflags; } } else { return EINVFN; } } else { /* Fcntl will automatically call tty_ioctl to handle * terminal calls that we didn't deal with */ return EINVFN; } return 0; } static long bios_select(f, p, mode) FILEPTR *f; long p; int mode; { struct tty *tty = (struct tty *)f->devinfo; int dev = f->fc.aux; if (mode == O_RDONLY) { if (bconstat(dev)) { TRACE("bios_select: data present for device %d", dev); return 1; } if (tty) { /* avoid collisions with other processes */ if (!tty->rsel) tty->rsel = p; } return 0; } else if (mode == O_WRONLY) { if (bcostat(dev)) { TRACE("bios_select: ready to output on %d", dev); return 1; } if (tty) { if (!tty->wsel) tty->wsel = p; } return 0; } /* default -- we don't know this mode, return 0 */ return 0; } static void bios_unselect(f, p, mode) FILEPTR *f; long p; int mode; { struct tty *tty = (struct tty *)f->devinfo; if (tty) { if (mode == O_RDONLY && tty->rsel == p) tty->rsel = 0; else if (mode == O_WRONLY && tty->wsel == p) tty->wsel = 0; } } /* * mouse device driver */ #define MOUSESIZ 128*3 static unsigned char mousebuf[MOUSESIZ]; static int mousehead, mousetail; long mousersel; /* is someone calling select() on the mouse? */ char mshift; /* shift key status; set by checkkeys() in bios.c */ short *gcurx = 0, *gcury = 0; /* mouse pos. variables; used by big screen emulators */ void mouse_handler(buf) const char *buf; /* must be a *signed* character */ { unsigned char *mbuf, buttons; int newmtail; short dx, dy; /* the Sun mouse driver has 0=down, 1=up, while the atari hardware gives us the reverse. also, we have the "middle" button and the "left" button reversed; so we use this table to convert (and also to add the 0x80 to indicate a mouse packet) */ static int _cnvrt[8] = { 0x87, 0x86, 0x83, 0x82, 0x85, 0x84, 0x81, 0x80 }; mbuf = &mousebuf[mousetail]; newmtail = mousetail + 3; if (newmtail >= MOUSESIZ) newmtail = 0; if (newmtail == mousehead) return; /* buffer full */ buttons = *buf++ & 0x7; /* convert to SUN format */ if (mshift & 0x3) { /* a shift key held down? */ /* if so, convert shift+button to a "middle" button */ if (buttons == 0x1 || buttons == 0x2) buttons = 0x4; else if (buttons == 0x3) buttons = 0x7; } *mbuf++ = _cnvrt[buttons]; /* convert to Sun format */ dx = *buf++; *mbuf++ = dx; /* copy X delta */ dy = *buf++; *mbuf++ = -dy; /* invert Y delta for Sun format */ mousetail = newmtail; *gcurx += dx; /* update line A variables */ *gcury += dy; /* * if someone has called select() waiting for mouse input, wake them * up */ if (mousersel) { wakeselect(mousersel); } } extern void newmvec(); /* in intr.s */ static long oldvec = 0; static long mouse_open(f) FILEPTR *f; { char *aline; static char parameters[] = { 0, /* Y=0 in lower corner */ 0, /* normal button handling */ 1, 1 /* X, Y scaling factors */ }; if (oldvec) /* mouse in use */ return EACCDN; /* initialize pointers to line A variables */ if (!gcurx) { aline = lineA0(); if (aline == 0) { /* should never happen */ ALERT("unable to read line A variables"); return -1; } gcurx = (short *)(aline - 0x25a); gcury = (short *)(aline - 0x258); *gcurx = *gcury = 32; /* magic number -- what MGR uses */ } oldvec = syskey->mousevec; Initmous(1, parameters, newmvec); mousehead = mousetail = 0; return 0; } static long mouse_close(f, pid) FILEPTR *f; int pid; { static char parameters[] = { 0, /* Y=0 in lower corner */ 0, /* normal button handling */ 1, 1 /* X, Y scaling factors */ }; if (!f) return EIHNDL; if (f->links <= 0) { if (!oldvec) { DEBUG("Mouse not open!!"); return -1; } Initmous(1, parameters, (void *)oldvec); /* gratuitous (void *) for Lattice */ oldvec = 0; } return 0; } static long mouse_read(f, buf, nbytes) FILEPTR *f; char *buf; long nbytes; { long count = 0; int mhead; unsigned char *foo; mhead = mousehead; foo = &mousebuf[mhead]; if (mhead == mousetail) { if (f->flags & O_NDELAY) return 0; do { TRACE("yielding in mouse_read"); yield(); } while (mhead == mousetail); } while ( (mhead != mousetail) && (nbytes > 0)) { *buf++ = *foo++; mhead++; if (mhead >= MOUSESIZ) { mhead = 0; foo = mousebuf; } count++; --nbytes; } mousehead = mhead; return count; } static long mouse_ioctl(f, mode, buf) FILEPTR *f; int mode; void *buf; { long r; if (mode == FIONREAD) { r = mousetail - mousehead; if (r < 0) r += MOUSESIZ; *((long *)buf) = r; } else return EINVFN; return 0; } static long mouse_select(f, p, mode) FILEPTR *f; long p; int mode; { if (mode != O_RDONLY) return 1; /* we can always take output :-) */ if (mousetail - mousehead) return 1; /* input waiting already */ if (!mousersel) mousersel = p; return 0; } static void mouse_unselect(f, p, mode) FILEPTR *f; long p; int mode; { if (mode == O_RDONLY && mousersel == p) mousersel = 0; } /* * UTILITY ROUTINE called by Bconmap() in xbios.c: * this sets handle -1 of process p to a file handle * that has BIOS device "dev". Returns 0 on failure, * non-zero on success. */ int set_auxhandle(p, dev) PROC *p; int dev; { FILEPTR *f; struct bios_file *b; f = new_fileptr(); if (f) { f->links = 1; f->flags = O_RDWR; f->pos = 0; f->devinfo = 0; f->fc.fs = &bios_filesys; f->fc.aux = dev; f->fc.dev = BIOSDRV; for (b = broot; b; b = b->next) { if (b->private == dev && (b->device == &bios_tdevice || b->device == &bios_ndevice)) { f->fc.index = (long)b; f->dev = b->device; if (b->device != &fakedev) f->devinfo = (long)b->tty; goto found_device; } } f->fc.index = 0; f->dev = &bios_ndevice; found_device: if ((*f->dev->open)(f) < 0) { f->links = 0; dispose_fileptr(f); return 0; } } else { /* no memory! use the fake FILEPTR we * set up in biosfs_init */ f = defaultaux; f->links++; } (void)do_pclose(p, p->aux); p->aux = f; return 1; }