home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / mint095s / biosfs.c < prev    next >
C/C++ Source or Header  |  1993-08-03  |  30KB  |  1,385 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith. All rights reserved.
  3.  */
  4.  
  5. /* simple biosfs.c */
  6.  
  7. #include "mint.h"
  8.  
  9. extern struct kerinfo kernelinfo;    /* see main.c */
  10.  
  11. static long    bios_root    P_((int drv, fcookie *fc));
  12. static long    bios_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  13. static long    bios_getxattr    P_((fcookie *fc, XATTR *xattr));
  14. static long    bios_chattr    P_((fcookie *fc, int attrib));
  15. static long    bios_chown    P_((fcookie *fc, int uid, int gid));
  16. static long    bios_chmode    P_((fcookie *fc, unsigned mode));
  17. static long    bios_rmdir    P_((fcookie *dir, const char *name));
  18. static long    bios_remove    P_((fcookie *dir, const char *name));
  19. static long    bios_getname    P_((fcookie *root, fcookie *dir, char *pathname));
  20. static long    bios_rename    P_((fcookie *olddir, char *oldname,
  21.                     fcookie *newdir, const char *newname));
  22. static long    bios_opendir    P_((DIR *dirh, int flags));
  23. static long    bios_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *fc));
  24. static long    bios_rewinddir    P_((DIR *dirh));
  25. static long    bios_closedir    P_((DIR *dirh));
  26. static long    bios_pathconf    P_((fcookie *dir, int which));
  27. static long    bios_dfree    P_((fcookie *dir, long *buf));
  28. static DEVDRV *    bios_getdev    P_((fcookie *fc, long *devspecial));
  29. static long    bios_fscntl    P_((fcookie *, const char *, int, long));
  30. static long    bios_symlink    P_((fcookie *, const char *, const char *));
  31. static long    bios_readlink    P_((fcookie *, char *, int));
  32.  
  33. static long    bios_topen    P_((FILEPTR *f));
  34. static long    bios_twrite    P_((FILEPTR *f, const char *buf, long bytes));
  35. static long    bios_tread    P_((FILEPTR *f, char *buf, long bytes));
  36. static long    bios_nwrite    P_((FILEPTR *f, const char *buf, long bytes));
  37. static long    bios_nread    P_((FILEPTR *f, char *buf, long bytes));
  38. static long    bios_ioctl    P_((FILEPTR *f, int mode, void *buf));
  39. static long    bios_select    P_((FILEPTR *f, long p, int mode));
  40. static void    bios_unselect    P_((FILEPTR *f, long p, int mode));
  41. static long    bios_tseek    P_((FILEPTR *f, long where, int whence));
  42.  
  43. long    null_open    P_((FILEPTR *f));
  44. long    null_write    P_((FILEPTR *f, const char *buf, long bytes));
  45. long    null_read    P_((FILEPTR *f, char *buf, long bytes));
  46. long    null_lseek    P_((FILEPTR *f, long where, int whence));
  47. long    null_ioctl    P_((FILEPTR *f, int mode, void *buf));
  48. long    null_datime    P_((FILEPTR *f, short *time, int rwflag));
  49. long    null_close    P_((FILEPTR *f, int pid));
  50. long    null_select    P_((FILEPTR *f, long p, int mode));
  51. void    null_unselect    P_((FILEPTR *f, long p, int mode));
  52.  
  53. static long mouse_open    P_((FILEPTR *f));
  54. static long mouse_read    P_((FILEPTR *f, char *buf, long nbytes));
  55. static long mouse_ioctl P_((FILEPTR *f, int mode, void *buf));
  56. static long mouse_close P_((FILEPTR *f, int pid));
  57. static long mouse_select P_((FILEPTR *f, long p, int mode));
  58. static void mouse_unselect P_((FILEPTR *f, long p, int mode));
  59.  
  60. /* device driver for BIOS terminals */
  61.  
  62. DEVDRV bios_tdevice = {
  63.     bios_topen, bios_twrite, bios_tread, bios_tseek, bios_ioctl,
  64.     null_datime, null_close, bios_select, bios_unselect
  65. };
  66.  
  67. /* device driver for BIOS devices that are not terminals */
  68.  
  69. DEVDRV bios_ndevice = {
  70.     null_open, bios_nwrite, bios_nread, null_lseek, bios_ioctl,
  71.     null_datime, null_close, bios_select, bios_unselect
  72. };
  73.  
  74. DEVDRV null_device = {
  75.     null_open, null_write, null_read, null_lseek, null_ioctl,
  76.     null_datime, null_close, null_select, null_unselect
  77. };
  78.  
  79. DEVDRV mouse_device = {
  80.     mouse_open, null_write, mouse_read, null_lseek, mouse_ioctl,
  81.     null_datime, mouse_close, mouse_select, mouse_unselect
  82. };
  83.  
  84. /* this special driver is checked for in dosfile.c, and indicates that
  85.  * a dup operation is actually wanted rather than an open
  86.  */
  87. DEVDRV fakedev;
  88.  
  89. #ifdef FASTTEXT
  90. extern DEVDRV screen_device;    /* see fasttext.c */
  91. #endif
  92.  
  93. FILESYS bios_filesys = {
  94.     (FILESYS *)0,
  95.     0,
  96.     bios_root,
  97.     bios_lookup, nocreat, bios_getdev, bios_getxattr,
  98.     bios_chattr, bios_chown, bios_chmode,
  99.     nomkdir, bios_rmdir, bios_remove, bios_getname, bios_rename,
  100.     bios_opendir, bios_readdir, bios_rewinddir, bios_closedir,
  101.     bios_pathconf, bios_dfree, nowritelabel, noreadlabel,
  102.     bios_symlink, bios_readlink, nohardlink, bios_fscntl, nodskchng
  103. };
  104.  
  105.  
  106. struct tty con_tty, aux_tty, midi_tty;
  107. struct tty sccb_tty, scca_tty, ttmfp_tty;
  108.  
  109. #define BNAME_MAX    13
  110.  
  111. struct bios_file {
  112.     char     name[BNAME_MAX+1];    /* device name */
  113.     DEVDRV *device;            /* device driver for device */
  114.     short    private;        /* extra info for device driver */
  115.     ushort    flags;            /* flags for device open */
  116.     struct tty *tty;        /* tty structure (if appropriate) */
  117.     struct bios_file *next;
  118. };
  119.  
  120. struct bios_file BDEV[] = {
  121.  
  122. /* "real" bios devices present on all machines */
  123.     {"centr", &bios_ndevice, 0, 0, 0, 0},
  124.     {"console", &bios_tdevice, 2, O_TTY, &con_tty, 0},
  125.     {"midi", &bios_tdevice, 3, O_TTY, &midi_tty, 0},
  126.     {"kbd", &bios_ndevice, 4, 0, 0, 0},
  127. /* devices that duplicate handles */
  128.     {"prn", &fakedev, -3, 0, 0, 0}, /* handle -3 (printer) */
  129.     {"aux", &fakedev, -2, 0, 0, 0}, /* handle -2 (aux. terminal) */
  130.     {"con", &fakedev, -1, 0, 0, 0}, /* handle -1 (control terminal) */
  131.     {"tty", &fakedev, -1, 0, 0, 0}, /* the Unix name for it */
  132.     {"stdin", &fakedev, 0, 0, 0, 0},  /* handle 0 (stdin) */
  133.     {"stdout", &fakedev, 1, 0, 0, 0}, /* handle 1 (stdout) */
  134.     {"stderr", &fakedev, 2, 0, 0, 0}, /* handle 2 (stderr) */
  135.  
  136. /* other miscellaneous devices */
  137.     {"mouse", &mouse_device, 0, 0, 0, 0},
  138.     {"null", &null_device, 0, 0, 0, 0},
  139.  
  140. #ifdef FASTTEXT
  141. /* alternate console driver */
  142.     {"fasttext", &screen_device, 2, O_TTY, &con_tty, 0},
  143. #endif
  144.  
  145. /* serial port things *must* come last, because not all of these
  146.  * are present on all machines (except for modem1, which does however
  147.  * have a different device number on TTs and STs)
  148.  */
  149.     {"modem1", &bios_tdevice, 6, O_TTY, &aux_tty, 0},
  150.     {"modem2", &bios_tdevice, 7, O_TTY, &sccb_tty, 0},
  151.     {"serial1", &bios_tdevice, 8, O_TTY, &ttmfp_tty, 0},
  152.     {"serial2", &bios_tdevice, 9, O_TTY, &scca_tty, 0},
  153.     {"", 0, 0, 0, 0, 0}
  154. };
  155.  
  156. struct bios_file *broot, *bdevlast;
  157.  
  158. /* a file pointer for BIOS device 1, provided only for insurance
  159.  * in case a Bconmap happens and we can't allocate a new FILEPTR;
  160.  * in most cases, we'll want to build a FILEPTR in the usual
  161.  * way.
  162.  */
  163.  
  164. FILEPTR *defaultaux;
  165.  
  166. void
  167. biosfs_init()
  168. {
  169.     struct bios_file *b;
  170.  
  171.     broot = BDEV;
  172.  
  173.     for (b = broot; b->name[0]; b++) {
  174.         b->next = b+1;
  175.  
  176.     /* if not a TT or Mega STE, adjust the MODEM1 device to be BIOS
  177.      * device 1
  178.      * and ignore the remaining devices, since they're not present
  179.      */
  180.         if (!has_bconmap && b->private == 6) {
  181.             b->private = 1;
  182.             b->next = 0;
  183.             break;
  184.         }
  185.     /* SERIAL2 is not present on the Mega STe */
  186.         if (mch == MEGASTE && b->private == 8) {
  187.             b->next = 0;
  188.             break;
  189.         }
  190.             
  191.     }
  192.     bdevlast = b;
  193.     if (b->name[0] == 0) {
  194.         --b;
  195.         b->next = 0;
  196.     }
  197.     defaultaux = new_fileptr();
  198.     defaultaux->links = 1;        /* so it never gets freed */
  199.     defaultaux->flags = O_RDWR;
  200.     defaultaux->pos = 0;
  201.     defaultaux->devinfo = 0;
  202.     defaultaux->fc.fs = &bios_filesys;
  203.     defaultaux->fc.index = 0;
  204.     defaultaux->fc.aux = 1;
  205.     defaultaux->fc.dev = BIOSDRV;
  206.     defaultaux->dev = &bios_ndevice;
  207. }
  208.  
  209. static long
  210. bios_root(drv, fc)
  211.     int drv;
  212.     fcookie *fc;
  213. {
  214.     if (drv == BIOSDRV) {
  215.         fc->fs = &bios_filesys;
  216.         fc->dev = drv;
  217.         fc->index = 0L;
  218.         return 0;
  219.     }
  220.     fc->fs = 0;
  221.     return EINTRN;
  222. }
  223.  
  224. static long
  225. bios_lookup(dir, name, fc)
  226.     fcookie *dir;
  227.     const char *name;
  228.     fcookie *fc;
  229. {
  230.     struct bios_file *b;
  231.  
  232. TRACE("bios_lookup(%s)", name);
  233.  
  234.     if (dir->index != 0) {
  235.         DEBUG("bios_lookup: bad directory");
  236.         return EPTHNF;
  237.     }
  238. /* special case: an empty name in a directory means that directory */
  239. /* so does "." */
  240.     if (!*name || (name[0] == '.' && name[1] == 0)) {
  241.         *fc = *dir;
  242.         return 0;
  243.     }
  244.  
  245. /* another special case: ".." could be a mount point */
  246.     if (!strcmp(name, "..")) {
  247.         *fc = *dir;
  248.         return EMOUNT;
  249.     }
  250.  
  251.     for (b = broot; b; b = b->next) {
  252.         if (!stricmp(b->name, name)) {
  253.             fc->fs = &bios_filesys;
  254.             fc->index = (long)b;
  255.             fc->aux = b->private;
  256.             fc->dev = dir->dev;
  257.             return 0;
  258.         }
  259.     }
  260.     DEBUG("bios_lookup: name(%s) not found", name);
  261.     return EFILNF;
  262. }
  263.  
  264. static long
  265. bios_getxattr(fc, xattr)
  266.     fcookie *fc;
  267.     XATTR *xattr;
  268. {
  269.     struct bios_file *b = (struct bios_file *)fc->index;
  270.  
  271.     xattr->index = fc->index;
  272.     xattr->dev = fc->dev;
  273.     xattr->nlink = 1;
  274.     xattr->uid = xattr->gid = 0;
  275.     xattr->size = xattr->nblocks = 0;
  276.     xattr->blksize = 1;
  277.     xattr->mtime = xattr->atime = xattr->ctime = timestamp;
  278.     xattr->mdate = xattr->adate = xattr->cdate = datestamp;
  279.     if (fc->index == 0) {        /* root directory? */
  280.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  281.         xattr->attr = FA_DIR;
  282.     } else if (b->device == 0) {    /* symbolic link? */
  283.         xattr->mode = S_IFLNK | DEFAULT_DIRMODE;
  284.     } else {
  285. /* BUG: U:\DEV\STDIN, U:\DEV\STDOUT, etc. might not be terminal files */
  286.         xattr->mode = S_IFCHR | DEFAULT_MODE;
  287.         xattr->attr = 0;
  288.     }
  289.     return 0;
  290. }
  291.  
  292. static long
  293. bios_chattr(fc, attrib)
  294.     fcookie *fc;
  295.     int attrib;
  296. {
  297.     return EACCDN;
  298. }
  299.  
  300. static long
  301. bios_chown(fc, uid, gid)
  302.     fcookie *fc;
  303.     int uid, gid;
  304. {
  305.     return EINVFN;
  306. }
  307.  
  308. static long
  309. bios_chmode(fc, mode)
  310.     fcookie *fc;
  311.     unsigned mode;
  312. {
  313.     return EINVFN;
  314. }
  315.  
  316. long
  317. nomkdir(dir, name, mode)
  318.     fcookie *dir;
  319.     const char *name;
  320.     unsigned mode;
  321. {
  322.     return EACCDN;
  323. }
  324.  
  325. static long
  326. bios_rmdir(dir, name)
  327.     fcookie *dir;
  328.     const char *name;
  329. {
  330.     return bios_remove(dir, name);
  331. }
  332.  
  333. /*
  334.  * MAJOR BUG: we don't check here for removal of devices for which there
  335.  * are still open files
  336.  */
  337.  
  338. static long
  339. bios_remove(dir, name)
  340.     fcookie *dir;
  341.     const char *name;
  342. {
  343.     struct bios_file *b, **lastb;
  344.  
  345.     lastb = &broot;
  346.     for (b = broot; b; b = *(lastb = &b->next)) {
  347.         if (!stricmp(b->name, name)) break;
  348.     }
  349.     if (!b) return EFILNF;
  350.  
  351. /* don't allow removal of the basic system devices */
  352.     if (b >= BDEV && b <= bdevlast) {
  353.         return EACCDN;
  354.     }
  355.     *lastb = b->next;
  356.  
  357.     if (b->device == 0 || b->device == &bios_tdevice)
  358.         kfree(b->tty);
  359.  
  360.     kfree(b);
  361.     return 0;
  362. }
  363.  
  364. static long
  365. bios_getname(root, dir, pathname)
  366.     fcookie *root, *dir; char *pathname;
  367. {
  368.     if (dir->index == 0)
  369.         *pathname = 0;
  370.     else
  371.         strcpy(pathname, ((struct bios_file *)dir->index)->name);
  372.     return 0;
  373. }
  374.  
  375. static long
  376. bios_rename(olddir, oldname, newdir, newname)
  377.     fcookie *olddir;
  378.     char *oldname;
  379.     fcookie *newdir;
  380.     const char *newname;
  381. {
  382.     struct bios_file *b;
  383.  
  384. /* BUG: we should check to see if "newname" already exists */
  385.  
  386.     for (b = broot; b; b = b->next) {
  387.         if (!stricmp(b->name, oldname)) {
  388.             strncpy(b->name, newname, BNAME_MAX);
  389.             return 0;
  390.         }
  391.     }
  392.     return EFILNF;
  393. }
  394.  
  395. static long
  396. bios_opendir(dirh, flags)
  397.     DIR *dirh;
  398.     int flags;
  399. {
  400.     if (dirh->fc.index != 0) {
  401.         DEBUG("bios_opendir: bad directory");
  402.         return EPTHNF;
  403.     }
  404.     return 0;
  405. }
  406.  
  407. static long
  408. bios_readdir(dirh, name, namelen, fc)
  409.     DIR *dirh;
  410.     char *name;
  411.     int namelen;
  412.     fcookie *fc;
  413. {
  414.     struct bios_file *b;
  415.     int giveindex = dirh->flags == 0;
  416.     int i;
  417.  
  418.     b = broot;
  419.     i = dirh->index++;
  420.     while(i-- > 0) {
  421.         if (!b) break;
  422.         b = b->next;
  423.     }
  424.     if (!b) {
  425.         return ENMFIL;
  426.     }
  427.     fc->fs = &bios_filesys;
  428.     fc->index = (long)b;
  429.     fc->aux = b->private;
  430.     fc->dev = dirh->fc.dev;
  431.     if (giveindex) {
  432.         namelen -= sizeof(long);
  433.         if (namelen <= 0)
  434.             return ERANGE;
  435.         *((long *)name) = (long) b;
  436.         name += sizeof(long);
  437.     }
  438.     strncpy(name, b->name, namelen-1);
  439.     if (strlen(b->name) >= namelen)
  440.         return ENAMETOOLONG;
  441.     return 0;
  442. }
  443.  
  444. static long
  445. bios_rewinddir(dirh)
  446.     DIR *dirh;
  447. {
  448.     dirh->index = 0;
  449.     return 0;
  450. }
  451.  
  452. static long
  453. bios_closedir(dirh)
  454.     DIR *dirh;
  455. {
  456.     return 0;
  457. }
  458.  
  459. static long
  460. bios_pathconf(dir, which)
  461.     fcookie *dir;
  462.     int which;
  463. {
  464.     switch(which) {
  465.     case -1:
  466.         return DP_MAXREQ;
  467.     case DP_IOPEN:
  468.         return UNLIMITED;    /* no limit on BIOS file descriptors */
  469.     case DP_MAXLINKS:
  470.         return 1;        /* no hard links available */
  471.     case DP_PATHMAX:
  472.         return PATH_MAX;
  473.     case DP_NAMEMAX:
  474.         return BNAME_MAX;
  475.     case DP_ATOMIC:
  476.         return 1;        /* no atomic writes */
  477.     case DP_TRUNC:
  478.         return DP_AUTOTRUNC;    /* names are truncated */
  479.     case DP_CASE:
  480.         return DP_CASEINSENS;    /* not case sensitive */
  481.     default:
  482.         return EINVFN;
  483.     }
  484. }
  485.  
  486. static long
  487. bios_dfree(dir, buf)
  488.     fcookie *dir;
  489.     long *buf;
  490. {
  491.     buf[0] = 0;    /* number of free clusters */
  492.     buf[1] = 0;    /* total number of clusters */
  493.     buf[2] = 1;    /* sector size (bytes) */
  494.     buf[3] = 1;    /* cluster size (sectors) */
  495.     return 0;
  496. }
  497.  
  498. /*
  499.  * BIOS Dcntl() calls:
  500.  * Dcntl(0xde02, "U:\DEV\FOO", &foo_descr): install a new device called
  501.  *     "FOO", which is described by the dev_descr structure "foo_descr".
  502.  *     this structure has the following fields:
  503.  *         DEVDRV *driver        the device driver itself
  504.  *       short  dinfo            info for the device driver
  505.  *       short  flags            flags for the file (e.g. O_TTY)
  506.  *       struct tty *tty        tty structure, if appropriate
  507.  *
  508.  * Dcntl(0xde00, "U:\DEV\BAR", n): install a new BIOS terminal device, with
  509.  *     BIOS device number "n".
  510.  * Dcntl(0xde01, "U:\DEV\BAR", n): install a new non-tty BIOS device, with
  511.  *     BIOS device number "n".
  512.  */
  513.  
  514. static long
  515. bios_fscntl(dir, name, cmd, arg)
  516.     fcookie *dir;
  517.     const char *name;
  518.     int cmd;
  519.     long arg;
  520. {
  521.     struct bios_file *b;
  522.  
  523.     if (cmd == DEV_INSTALL) {
  524.         struct dev_descr *d = (struct dev_descr *)arg;
  525.  
  526.         b = kmalloc(SIZEOF(struct bios_file));
  527.         if (!b) return 0;
  528.         strncpy(b->name, name, BNAME_MAX);
  529.         b->name[BNAME_MAX] = 0;
  530.         b->device = d->driver;
  531.         b->private = d->dinfo;
  532.         b->flags = d->flags;
  533.         b->tty = d->tty;
  534.         b->next = broot;
  535.         broot = b;
  536.         return (long)&kernelinfo;
  537.     }
  538.     if (cmd == DEV_NEWTTY) {
  539.         b = kmalloc(SIZEOF(struct bios_file));
  540.         if (!b) return ENSMEM;
  541.         b->tty = kmalloc(SIZEOF(struct tty));
  542.         if (!b->tty) {
  543.             kfree(b);
  544.             return ENSMEM;
  545.         }
  546.         strncpy(b->name, name, BNAME_MAX);
  547.         b->name[BNAME_MAX] = 0;
  548.         b->device = &bios_tdevice;
  549.         b->private = arg;
  550.         b->flags = O_TTY;
  551.         *b->tty = default_tty;
  552.         b->next = broot;
  553.         broot = b;
  554.         return 0;
  555.     }
  556.     if (cmd == DEV_NEWBIOS) {
  557.         b = kmalloc(SIZEOF(struct bios_file));
  558.         if (!b) return ENSMEM;
  559.         strncpy(b->name, name, BNAME_MAX);
  560.         b->name[BNAME_MAX] = 0;
  561.         b->tty = 0;
  562.         b->device = &bios_ndevice;
  563.         b->private = arg;
  564.         b->flags = 0;
  565.         b->next = broot;
  566.         return 0;
  567.     }
  568.     return EINVFN;
  569. }
  570.  
  571. static long
  572. bios_symlink(dir, name, to)
  573.     fcookie *dir;
  574.     const char *name, *to;
  575. {
  576.     struct bios_file *b;
  577.     long r;
  578.     fcookie fc;
  579.  
  580.     r = bios_lookup(dir, name, &fc);
  581.     if (r == 0) return EACCDN;    /* file already exists */
  582.     if (r != EFILNF) return r;    /* some other error */
  583.  
  584.     b = kmalloc(SIZEOF(struct bios_file));
  585.     if (!b) return EACCDN;
  586.  
  587.     strncpy(b->name, name, BNAME_MAX);
  588.     b->name[BNAME_MAX] = 0;
  589.     b->device = 0;
  590.     b->private = EINVFN;
  591.     b->flags = 0;
  592.     b->tty = kmalloc((long)strlen(to)+1);
  593.     if (!b->tty) {
  594.         kfree(b);
  595.         return EACCDN;
  596.     }
  597.     strcpy((char *)b->tty, to);
  598.     b->next = broot;
  599.     broot = b;
  600.     return 0;
  601. }
  602.  
  603. static long
  604. bios_readlink(fc, buf, buflen)
  605.     fcookie *fc;
  606.     char *buf;
  607.     int buflen;
  608. {
  609.     struct bios_file *b = (struct bios_file *)fc->index;
  610.  
  611.     if (!b) return EINVFN;
  612.     if (b->device) return EINVFN;
  613.  
  614.     strncpy(buf, (char *)b->tty, buflen);
  615.     if (strlen((char *)b->tty) >= buflen)
  616.         return ENAMETOOLONG;
  617.     return 0;
  618. }
  619.  
  620.  
  621. /*
  622.  * routines for file systems that don't support volume labels
  623.  */
  624.  
  625. long
  626. nowritelabel(dir, name)
  627.     fcookie *dir;
  628.     const char *name;
  629. {
  630.     return EACCDN;
  631. }
  632.  
  633. long
  634. noreadlabel(dir, name, namelen)
  635.     fcookie *dir;
  636.     char *name;
  637.     int namelen;
  638. {
  639.     return EFILNF;
  640. }
  641.  
  642. /*
  643.  * routines for file systems that don't support links
  644.  */
  645.  
  646. long
  647. nosymlink(dir, name, to)
  648.     fcookie *dir;
  649.     const char *name, *to;
  650. {
  651.     return EINVFN;
  652. }
  653.  
  654. long
  655. noreadlink(dir, buf, buflen)
  656.     fcookie *dir;
  657.     char *buf;
  658.     int buflen;
  659. {
  660.     return EINVFN;
  661. }
  662.  
  663. long
  664. nohardlink(fromdir, fromname, todir, toname)
  665.     fcookie *fromdir, *todir;
  666.     const char *fromname, *toname;
  667. {
  668.     return EINVFN;
  669. }
  670.  
  671. /* dummy routine for file systems with no Fscntl commands */
  672.  
  673. long
  674. nofscntl(dir, name, cmd, arg)
  675.     fcookie *dir;
  676.     const char *name;
  677.     int cmd;
  678.     long arg;
  679. {
  680.     return EINVFN;
  681. }
  682.  
  683. /*
  684.  * Did the disk change? Not on this drive!
  685.  * However, we have to do Getbpb anyways, because someone has decided
  686.  * to force a media change on our (non-existent) drive.
  687.  */
  688. long
  689. nodskchng(drv)
  690.     int drv;
  691. {
  692.     (void)getbpb(drv);
  693.     return 0;
  694. }
  695.  
  696. long
  697. nocreat(dir, name, mode, attrib, fc)
  698.     fcookie *dir, *fc;
  699.     const char *name;
  700.     unsigned mode;
  701.     int attrib;
  702. {
  703.     return EACCDN;
  704. }
  705.  
  706. static DEVDRV *
  707. bios_getdev(fc, devsp)
  708.     fcookie *fc;
  709.     long *devsp;
  710. {
  711.     struct bios_file *b;
  712.  
  713.     b = (struct bios_file *)fc->index;
  714.  
  715.     if (b->device && b->device != &fakedev)
  716.         *devsp = (long)b->tty;
  717.     else
  718.         *devsp = b->private;
  719.  
  720.     return b->device;    /* return the device driver */
  721. }
  722.  
  723. /*
  724.  * NULL device driver
  725.  */
  726.  
  727. long
  728. null_open(f)
  729.     FILEPTR *f;
  730. {
  731.     return 0;
  732. }
  733.  
  734. long
  735. null_write(f, buf, bytes)
  736.     FILEPTR *f; const char *buf; long bytes;
  737. {
  738.     return bytes;
  739. }
  740.  
  741. long
  742. null_read(f, buf, bytes)
  743.     FILEPTR *f; char *buf; long bytes;
  744. {
  745.     return 0;
  746. }
  747.  
  748. long
  749. null_lseek(f, where, whence)
  750.     FILEPTR *f; long where; int whence;
  751. {
  752.     return (where == 0) ? 0 : ERANGE;
  753. }
  754.  
  755. long
  756. null_ioctl(f, mode, buf)
  757.     FILEPTR *f; int mode; void *buf;
  758. {
  759.     if (mode == FIONREAD) {
  760.         *((long *)buf) = 0;
  761.     }
  762.     else if (mode == FIONWRITE)
  763.         *((long *)buf) = 1;
  764.     else
  765.         return EINVFN;
  766.     return 0;
  767. }
  768.  
  769. long
  770. null_datime(f, timeptr, rwflag)
  771.     FILEPTR *f;
  772.     short *timeptr;
  773.     int rwflag;
  774. {
  775.     if (rwflag)
  776.         return EACCDN;
  777.     *timeptr++ = timestamp;
  778.     *timeptr = datestamp;
  779.     return 0;
  780. }
  781.  
  782. long
  783. null_close(f, pid)
  784.     FILEPTR *f;
  785.     int pid;
  786. {
  787.     return 0;
  788. }
  789.  
  790. long
  791. null_select(f, p, mode)
  792.     FILEPTR *f; long p;
  793.     int mode;
  794. {
  795.     return 1;    /* we're always ready to read/write */
  796. }
  797.  
  798. void
  799. null_unselect(f, p, mode)
  800.     FILEPTR *f;
  801.     long p;
  802.     int mode;
  803. {
  804.     /* nothing to do */
  805. }
  806.  
  807. /*
  808.  * BIOS terminal device driver
  809.  */
  810.  
  811. static long
  812. bios_topen(f)
  813.     FILEPTR *f;
  814. {
  815.     f->flags |= O_TTY;
  816.     return 0;
  817. }
  818.  
  819. /*
  820.  * Note: when a BIOS device is a terminal (i.e. has the O_TTY flag
  821.  * set), bios_read and bios_write will only ever be called indirectly, via
  822.  * tty_read and tty_write. That's why we can afford to play a bit fast and
  823.  * loose with the pointers ("buf" is really going to point to a long) and
  824.  * why we know that "bytes" is divisible by 4.
  825.  */
  826.  
  827. static long
  828. bios_twrite(f, buf, bytes)
  829.     FILEPTR *f; const char *buf; long bytes;
  830. {
  831.     long *r;
  832.     long ret = 0;
  833.     int bdev = f->fc.aux;
  834.  
  835.     r = (long *)buf;
  836.     while (bytes > 0) {
  837.         if ( (f->flags & O_NDELAY) && !bcostat(bdev) )
  838.             break;
  839.  
  840.         if (bconout(bdev, (int)*r) == 0)
  841.             break;
  842.  
  843.         r++; bytes -= 4; ret+= 4;
  844.     }
  845.     (void)checkkeys();
  846.     return ret;
  847. }
  848.  
  849. static long
  850. bios_tread(f, buf, bytes)
  851.     FILEPTR *f; char *buf; long bytes;
  852. {
  853.     long *r, ret = 0;
  854.     int bdev = f->fc.aux;
  855.  
  856.     r = (long *)buf;
  857.  
  858.     while (bytes > 0) {
  859.         if ( (f->flags & O_NDELAY) && !bconstat(bdev) )
  860.             break;
  861.         *r++ = bconin(bdev) & 0x7fffffff;
  862.         bytes -= 4; ret += 4;
  863.     }
  864.     return ret;
  865. }
  866.  
  867. /*
  868.  * read/write routines for BIOS devices that aren't terminals (like the
  869.  * printer & IKBD devices)
  870.  */
  871.  
  872. static long
  873. bios_nwrite(f, buf, bytes)
  874.     FILEPTR *f; const char *buf; long bytes;
  875. {
  876.     long ret = 0;
  877.     int bdev = f->fc.aux;
  878.     int c;
  879.  
  880.     while (bytes > 0) {
  881.         if ( (f->flags & O_NDELAY) && !bcostat(bdev) )
  882.             break;
  883.  
  884.         c = *buf++ & 0x00ff;
  885.  
  886.         if (bconout(bdev, c) == 0)
  887.             break;
  888.  
  889.         bytes--; ret++;
  890.     }
  891.     return ret;
  892. }
  893.  
  894. static long
  895. bios_nread(f, buf, bytes)
  896.     FILEPTR *f; char *buf; long bytes;
  897. {
  898.     long ret = 0;
  899.     int bdev = f->fc.aux;
  900.  
  901.     while (bytes > 0) {
  902.         if ( (f->flags & O_NDELAY) && !bconstat(bdev) )
  903.             break;
  904.         *buf++ = bconin(bdev) & 0xff;
  905.         bytes--; ret++;
  906.     }
  907.     return ret;
  908. }
  909.  
  910. /*
  911.  * BIOS terminal seek code -- this has to match the documented
  912.  * way to do isatty()
  913.  */
  914.  
  915. static long
  916. bios_tseek(f, where, whence)
  917.     FILEPTR *f;
  918.     long where;
  919.     int whence;
  920. {
  921. /* terminals always are at position 0 */
  922.     return 0;
  923. }
  924.  
  925. #define MAXBAUD 16
  926.  
  927. static long baudmap[MAXBAUD] = {
  928. 19200L, 9600L, 4800L, 3600L, 2400L, 2000L, 1800L, 1200L,
  929. 600L, 300L, 200L, 150L, 134L, 110L, 75L, 50L
  930. };
  931.  
  932. static long
  933. bios_ioctl(f, mode, buf)
  934.     FILEPTR *f; int mode; void *buf;
  935. {
  936.     long *r = (long *)buf;
  937.     struct winsize *ws;
  938.     char *aline;
  939.     short dev;
  940.     int i;
  941.  
  942.     if (mode == FIONREAD) {
  943.         if (bconstat(f->fc.aux))
  944.             *r = 1;
  945.         else
  946.             *r = 0;
  947.     }
  948.     else if (mode == FIONWRITE) {
  949.         if (bcostat(f->fc.aux))
  950.             *r = 1;
  951.         else
  952.             *r = 0;
  953.     }
  954.     else if (mode == TIOCFLUSH) {
  955. /* BUG: this should flush the input/output buffers */
  956.         return 0;
  957.     }
  958.     else if (mode == TIOCGWINSZ && f->fc.aux == 2) {
  959.         aline = lineA0();
  960.         ws = (struct winsize *)buf;
  961.         ws->ws_row = *((short *)(aline - 42)) + 1;
  962.         ws->ws_col = *((short *)(aline - 44)) + 1;
  963.     } else if (mode == TIOCIBAUD || mode == TIOCOBAUD) {
  964.         long oldbaud, newbaud;
  965.         dev = f->fc.aux;
  966.  
  967.         newbaud = *r;
  968.         if (dev == 1 || dev >= 6) {
  969.             if (has_bconmap)
  970.                 mapin((dev == 1) ? curproc->bconmap : dev);
  971.             i = rsconf(-2, -1, -1, -1, -1, -1);
  972.             if (i < 0 || i >= MAXBAUD)
  973.                 oldbaud = -1L;
  974.             else
  975.                 oldbaud = baudmap[i];
  976.             *r = oldbaud;
  977.             if (newbaud > 0) {
  978.                 for (i = 0; i < MAXBAUD; i++) {
  979.                     if (baudmap[i] == newbaud) {
  980.                         rsconf(i, -1, -1, -1, -1, -1);
  981.                         return 0;
  982.                     }
  983.                 }
  984.                 return ERANGE;
  985.             } else if (newbaud == 0L) {
  986.     /* drop DTR: works only on modem1 */
  987.                 if (dev == 1 || dev == 6) {
  988.                     Ongibit(0x10);
  989.                     nap(30);
  990.                     Offgibit(0xef);
  991.                 }
  992.             }
  993.             return 0;
  994.         } else if (dev == 2 || dev == 5) {
  995.             /* screen: assume 9600 baud */
  996.             oldbaud = 9600L;
  997.         } else if (dev == 3) {
  998.             /* midi */
  999.             oldbaud = 31250L;
  1000.         } else {
  1001.             oldbaud = -1L;    /* unknown speed */
  1002.         }
  1003.         *r = oldbaud;
  1004.         if (newbaud > 0 && newbaud != oldbaud)
  1005.             return ERANGE;
  1006.         return 0;
  1007.     } else if (mode == TIOCCBRK || mode == TIOCSBRK) {
  1008.         unsigned long bits;
  1009.  
  1010.         dev = f->fc.aux;
  1011.         if (dev == 1 || dev >= 6) {
  1012.             if (has_bconmap)
  1013.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1014.         } else {
  1015.             return EINVFN;
  1016.         }
  1017.         bits = rsconf(-1, -1, -1, -1, -1, -1);    /* get settings */
  1018.         bits = (bits >> 8) & 0x0ff;        /* isolate TSR byte */
  1019.         if (mode == TIOCCBRK)
  1020.             bits &= ~8;
  1021.         else
  1022.             bits |= 8;
  1023.         (void)rsconf(-1, -1, -1, -1, (int)bits, -1);
  1024.     } else if (mode == TIOCGFLAGS || mode == TIOCSFLAGS) {
  1025.         unsigned short oflags, flags;
  1026.         unsigned long bits;
  1027.         unsigned char ucr;
  1028.         short flow;
  1029.  
  1030.         dev = f->fc.aux;
  1031.         if (dev == 1 || dev >= 6) {
  1032.             oflags = ((struct tty *)f->devinfo)->sg.sg_flags;
  1033.             oflags &= (T_TANDEM|T_RTSCTS);
  1034.             if (has_bconmap)
  1035.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1036.             bits = rsconf(-1, -1, -1, -1, -1, -1);    /* get settings */
  1037.             ucr = (bits >> 24L) & 0x0ff;        /* isolate UCR byte */
  1038.             oflags |= (ucr >> 3) & (TF_STOPBITS|TF_CHARBITS);
  1039.             if (ucr & 0x4) {            /* parity on? */
  1040.                 oflags |= (ucr & 0x2) ? T_EVENP : T_ODDP;
  1041.             }
  1042.             if (mode == TIOCSFLAGS) {
  1043.                 flags = (*(unsigned short *)buf);
  1044.                 if (flags & T_EVENP) {
  1045.                     ucr |= 0x6;
  1046.                 } else if (flags & T_ODDP) {
  1047.                     ucr &= ~2;
  1048.                     ucr |= 0x4;
  1049.                 } else {
  1050.                     ucr &= ~6;
  1051.                 }
  1052.                 if (flags & TF_STOPBITS) {
  1053.                     ucr &= ~(0x18);
  1054.                     ucr |= (flags & TF_STOPBITS) << 3;
  1055.                 }
  1056.                 ucr &= ~(0x60);
  1057.                 ucr |= (flags & TF_CHARBITS) << 3;
  1058.                 flow = (flags & (T_RTSCTS|T_TANDEM)) >> 12L;
  1059.                 rsconf(-1, flow, ucr, -1, -1, -1);
  1060.             } else {
  1061.                 *((unsigned short *)buf) = oflags;
  1062.             }
  1063.         } else {
  1064.             return EINVFN;
  1065.         }
  1066.  
  1067.     } else {
  1068.     /* Fcntl will automatically call tty_ioctl to handle
  1069.      * terminal calls that we didn't deal with
  1070.      */
  1071.         return EINVFN;
  1072.     }
  1073.     return 0;
  1074. }
  1075.  
  1076. static long
  1077. bios_select(f, p, mode)
  1078.     FILEPTR *f; long p; int mode;
  1079. {
  1080.     struct tty *tty = (struct tty *)f->devinfo;
  1081.     int dev = f->fc.aux;
  1082.  
  1083.     if (mode == O_RDONLY) {
  1084.         if (bconstat(dev)) {
  1085.             TRACE("bios_select: data present for device %d", dev);
  1086.             return 1;
  1087.         }
  1088.         if (tty) {
  1089.         /* avoid collisions with other processes */
  1090.             if (!tty->rsel)
  1091.                 tty->rsel = p;
  1092.         }
  1093.         return 0;
  1094.     } else if (mode == O_WRONLY) {
  1095.         if (bcostat(dev)) {
  1096.             TRACE("bios_select: ready to output on %d", dev);
  1097.             return 1;
  1098.         }
  1099.         if (tty) {
  1100.             if (!tty->wsel)
  1101.                 tty->wsel = p;
  1102.         }
  1103.         return 0;
  1104.     }
  1105.     /* default -- we don't know this mode, return 0 */
  1106.     return 0;
  1107. }
  1108.  
  1109. static void
  1110. bios_unselect(f, p, mode)
  1111.     FILEPTR *f;
  1112.     long p;
  1113.     int mode;
  1114. {
  1115.     struct tty *tty = (struct tty *)f->devinfo;
  1116.  
  1117.     if (tty) {
  1118.         if (mode == O_RDONLY && tty->rsel == p)
  1119.             tty->rsel = 0;
  1120.         else if (mode == O_WRONLY && tty->wsel == p)
  1121.             tty->wsel = 0;
  1122.     }
  1123. }
  1124.  
  1125. /*
  1126.  * mouse device driver
  1127.  */
  1128.  
  1129. #define MOUSESIZ 128*3
  1130. static unsigned char mousebuf[MOUSESIZ];
  1131. static int mousehead, mousetail;
  1132.  
  1133. long mousersel;    /* is someone calling select() on the mouse? */
  1134.  
  1135. char mshift;        /* shift key status; set by checkkeys() in bios.c */
  1136. short *gcurx = 0,
  1137.       *gcury = 0;    /* mouse pos. variables; used by big screen emulators */
  1138.  
  1139. void
  1140. mouse_handler(buf)
  1141.     const char *buf;    /* must be a *signed* character */
  1142. {
  1143.     unsigned char *mbuf, buttons;
  1144.     int newmtail;
  1145.     short dx, dy;
  1146.  
  1147. /* the Sun mouse driver has 0=down, 1=up, while the atari hardware gives
  1148.    us the reverse. also, we have the "middle" button and the "left"
  1149.    button reversed; so we use this table to convert (and also to add the
  1150.    0x80 to indicate a mouse packet)
  1151.  */
  1152.     static int _cnvrt[8] = {
  1153.         0x87, 0x86, 0x83, 0x82, 0x85, 0x84, 0x81, 0x80
  1154.     };
  1155.  
  1156.     mbuf = &mousebuf[mousetail];
  1157.     newmtail = mousetail + 3;
  1158.     if (newmtail >= MOUSESIZ)
  1159.         newmtail = 0;
  1160.     if (newmtail == mousehead)
  1161.         return;            /* buffer full */
  1162.  
  1163.     buttons = *buf++ & 0x7;        /* convert to SUN format */
  1164.     if (mshift & 0x3) {        /* a shift key held down? */
  1165.     /* if so, convert shift+button to a "middle" button */
  1166.         if (buttons == 0x1 || buttons == 0x2)
  1167.             buttons = 0x4;
  1168.         else if (buttons == 0x3)
  1169.             buttons = 0x7;
  1170.     }
  1171.     *mbuf++ = _cnvrt[buttons];    /* convert to Sun format */
  1172.     dx = *buf++;
  1173.     *mbuf++ = dx;            /* copy X delta */
  1174.     dy = *buf++;
  1175.     *mbuf++ = -dy;            /* invert Y delta for Sun format */
  1176.     mousetail = newmtail;
  1177.     *gcurx += dx;            /* update line A variables */
  1178.     *gcury += dy;
  1179. /*
  1180.  * if someone has called select() waiting for mouse input, wake them
  1181.  * up
  1182.  */
  1183.     if (mousersel) {
  1184.         wakeselect(mousersel);
  1185.     }
  1186. }
  1187.  
  1188. extern void newmvec();        /* in intr.s */
  1189. static long oldvec = 0;
  1190.  
  1191. static long
  1192. mouse_open(f)
  1193.     FILEPTR *f;
  1194. {
  1195.     char *aline;
  1196.  
  1197.     static char parameters[] = {
  1198.         0,         /* Y=0 in lower corner */
  1199.         0,        /* normal button handling */
  1200.         1, 1        /* X, Y scaling factors */
  1201.     };
  1202.  
  1203.     if (oldvec)        /* mouse in use */
  1204.         return EACCDN;
  1205.  
  1206. /* initialize pointers to line A variables */
  1207.     if (!gcurx) {
  1208.         aline = lineA0();
  1209.         if (aline == 0)    {    /* should never happen */
  1210.             ALERT("unable to read line A variables");
  1211.             return -1;
  1212.         }
  1213.         gcurx = (short *)(aline - 0x25a);
  1214.         gcury = (short *)(aline - 0x258);
  1215.         *gcurx = *gcury = 32;    /* magic number -- what MGR uses */
  1216.     }
  1217.  
  1218.     oldvec = syskey->mousevec;
  1219.     Initmous(1, parameters, newmvec);
  1220.     mousehead = mousetail = 0;
  1221.     return 0;
  1222. }
  1223.  
  1224. static long
  1225. mouse_close(f, pid)
  1226.     FILEPTR *f;
  1227.     int pid;
  1228. {
  1229.     static char parameters[] = {
  1230.         0,         /* Y=0 in lower corner */
  1231.         0,        /* normal button handling */
  1232.         1, 1        /* X, Y scaling factors */
  1233.     };
  1234.  
  1235.     if (!f) return EIHNDL;
  1236.     if (f->links <= 0) {
  1237.         if (!oldvec) {
  1238.             DEBUG("Mouse not open!!");
  1239.             return -1;
  1240.         }
  1241.         Initmous(1, parameters, (void *)oldvec);    /* gratuitous (void *) for Lattice */
  1242.         oldvec = 0;
  1243.     }
  1244.     return 0;
  1245. }
  1246.  
  1247. static long
  1248. mouse_read(f, buf, nbytes)
  1249.     FILEPTR *f;
  1250.     char *buf;
  1251.     long nbytes;
  1252. {
  1253.     long count = 0;
  1254.     int mhead;
  1255.     unsigned char *foo;
  1256.  
  1257.     mhead = mousehead;
  1258.     foo = &mousebuf[mhead];
  1259.  
  1260.     if (mhead == mousetail) {
  1261.         if (f->flags & O_NDELAY)
  1262.             return 0;
  1263.         do {
  1264.             TRACE("yielding in mouse_read");
  1265.             yield();
  1266.         } while (mhead == mousetail);
  1267.     }
  1268.  
  1269.     while ( (mhead != mousetail) && (nbytes > 0)) {
  1270.         *buf++ = *foo++;
  1271.         mhead++;
  1272.         if (mhead >= MOUSESIZ) {
  1273.             mhead = 0;
  1274.             foo = mousebuf;
  1275.         }
  1276.         count++;
  1277.         --nbytes;
  1278.     }
  1279.     mousehead = mhead;
  1280.     return count;
  1281. }
  1282.  
  1283. static long
  1284. mouse_ioctl(f, mode, buf)
  1285.     FILEPTR *f;
  1286.     int mode;
  1287.     void *buf;
  1288. {
  1289.     long r;
  1290.  
  1291.     if (mode == FIONREAD) {
  1292.         r = mousetail - mousehead;
  1293.         if (r < 0) r += MOUSESIZ;
  1294.         *((long *)buf) = r;
  1295.     }
  1296.     else
  1297.         return EINVFN;
  1298.     return 0;
  1299. }
  1300.  
  1301. static long
  1302. mouse_select(f, p, mode)
  1303.     FILEPTR *f;
  1304.     long p;
  1305.     int mode;
  1306. {
  1307.     if (mode != O_RDONLY)
  1308.         return 1;    /* we can always take output :-) */
  1309.  
  1310.     if (mousetail - mousehead)
  1311.         return 1;    /* input waiting already */
  1312.  
  1313.     if (!mousersel)
  1314.         mousersel = p;
  1315.     return 0;
  1316. }
  1317.  
  1318. static void
  1319. mouse_unselect(f, p, mode)
  1320.     FILEPTR *f;
  1321.     long p;
  1322.     int mode;
  1323. {
  1324.     if (mode == O_RDONLY && mousersel == p)
  1325.         mousersel = 0;
  1326. }
  1327.  
  1328.  
  1329. /*
  1330.  * UTILITY ROUTINE called by Bconmap() in xbios.c:
  1331.  * this sets handle -1 of process p to a file handle
  1332.  * that has BIOS device "dev". Returns 0 on failure,
  1333.  * non-zero on success.
  1334.  */
  1335.  
  1336. int
  1337. set_auxhandle(p, dev)
  1338.     PROC *p;
  1339.     int dev;
  1340. {
  1341.     FILEPTR *f;
  1342.     struct bios_file *b;
  1343.  
  1344.     f = new_fileptr();
  1345.     if (f) {
  1346.         f->links = 1;
  1347.         f->flags = O_RDWR;
  1348.         f->pos = 0;
  1349.         f->devinfo = 0;
  1350.         f->fc.fs = &bios_filesys;
  1351.         f->fc.aux = dev;
  1352.         f->fc.dev = BIOSDRV;
  1353.         for (b = broot; b; b = b->next) {
  1354.             if (b->private == dev &&
  1355.                 (b->device == &bios_tdevice ||
  1356.                  b->device == &bios_ndevice)) {
  1357.                 f->fc.index = (long)b;
  1358.                 f->dev = b->device;
  1359.                 if (b->device != &fakedev)
  1360.                     f->devinfo = (long)b->tty;
  1361.                 goto found_device;
  1362.             }
  1363.         }
  1364.         f->fc.index = 0;
  1365.         f->dev = &bios_ndevice;
  1366. found_device:
  1367.         if ((*f->dev->open)(f) < 0) {
  1368.             f->links = 0;
  1369.             dispose_fileptr(f);
  1370.             return 0;
  1371.         }
  1372.     } else {
  1373. /* no memory! use the fake FILEPTR we
  1374.  * set up in biosfs_init
  1375.  */
  1376.         f = defaultaux;
  1377.         f->links++;
  1378.     }
  1379.  
  1380.     (void)do_pclose(p, p->aux);
  1381.     p->aux = f;
  1382.  
  1383.     return 1;
  1384. }
  1385.