home *** CD-ROM | disk | FTP | other *** search
/ Vectronix 2 / VECTRONIX2.iso / FILES_01 / PC_V11_B.LZH / DEMO_PC / CLOCKDEV.C < prev    next >
C/C++ Source or Header  |  1991-12-15  |  6KB  |  286 lines

  1. /*
  2.  * A simple device driver for u:\dev\clock. Reading from this
  3.  * device produces a single line containing the current time, in the
  4.  * format:
  5.  * MM/DD/YY hh:mm:ss\r\n
  6.  * Writing to it will change the time to the given one.
  7.  *
  8.  * This program is written by Eric R. Smith and is hereby placed in
  9.  * the public domain.
  10.  *
  11.  * COMPILER NOTE: I've assumed that you're using a compiler (like gcc
  12.  * or Lattice) that preserves registers d2 and a2 across function calls.
  13.  * If your compiler uses these registers as scratch registers (e.g.
  14.  * MWC, Alcyon) then you'll have to provide assembly language wrapper
  15.  * functions that the kernel can call.
  16.  * This code also assumes that sizeof(int) == 2.
  17.  *
  18.  * for gcc: compile with gcc -mshort -O clockdev.c -o clockdev.prg
  19.  */
  20.  
  21. #ifdef __GNUC__
  22. #include <minimal.h>
  23. #endif
  24. #include <osbind.h>
  25. #include <basepage.h>
  26. #include "mintbind.h"
  27. #include "filesys.h"
  28. #include "atarierr.h"
  29.  
  30. #ifdef LATTICE
  31. #define BP _pbase
  32. #else
  33. #define BP _base
  34. #endif
  35.  
  36. /* the name of the device we're installing */
  37. char name[] = "U:\\DEV\\CLOCK";
  38.  
  39. /* kernel information */
  40. struct kerinfo *kernel;
  41. #define CCONWS (void)(*kernel->dos_tab[0x09])
  42. #define RWABS (*kernel->bios_tab[4])
  43. #define GETBPB (void *)(*kernel->bios_tab[7])
  44. #define TGETTIME (*kernel->dos_tab[0x2c])
  45. #define TGETDATE (*kernel->dos_tab[0x2a])
  46. #define TSETTIME (*kernel->dos_tab[0x2d])
  47. #define TSETDATE (*kernel->dos_tab[0x2b])
  48.  
  49. #define SPRINTF (*kernel->sprintf)
  50. #define DEBUG (*kernel->debug)
  51. #define ALERT (*kernel->alert)
  52. #define TRACE (*kernel->trace)
  53. #define FATAL (*kernel->fatal)
  54.  
  55. /* assumption: 16 bit integers */
  56. #define word int
  57.  
  58. /* device driver information */
  59. static long    clock_open    P_((FILEPTR *)),
  60.         clock_write    P_((FILEPTR *, char *, long)),
  61.         clock_read    P_((FILEPTR *, char *, long)),
  62.         clock_lseek    P_((FILEPTR *, long, word)),
  63.         clock_ioctl    P_((FILEPTR *, word, void *)),
  64.         clock_datime    P_((FILEPTR *, word *, word)),
  65.         clock_close    P_((FILEPTR *));
  66.  
  67. static long     clock_select();
  68. static void    clock_unselect();
  69.  
  70. DEVDRV clock_device = {
  71.     clock_open, clock_write, clock_read, clock_lseek, clock_ioctl,
  72.     clock_datime, clock_close, clock_select, clock_unselect,
  73.     0, 0, 0
  74. };
  75.  
  76. struct dev_descr devinfo = {
  77.     &clock_device, 0, 0, (struct tty *)0, 0L, 0L, 0L, 0L
  78. };
  79.  
  80. /*
  81.  * the main program just installs the device, and then does Ptermres
  82.  * to remain resident
  83.  */
  84.  
  85. main()
  86. {
  87.     kernel = (struct kerinfo *)Dcntl(DEV_INSTALL, name, &devinfo);
  88.     if (!kernel || ((long)kernel) == -32) {
  89.         Cconws("Unable to install clock device\r\n");
  90.         Pterm(1);
  91.     }
  92.     Ptermres(256L + BP->p_tlen + BP->p_dlen + BP->p_blen, 0);
  93. }
  94.  
  95. /*
  96.  * here are the actual device driver functions
  97.  */
  98.  
  99. /*
  100.  * utility functions:
  101.  * getclock(buf): get the current date and time and write it into
  102.  * the pointed to buffer in the format "MM/DD/YY hh:mm:ss\r\n"
  103.  *
  104.  * setclock(buf): set the current date and time from the ASCII
  105.  * string pointed to by buf, which must have the same format
  106.  * as that returned by getdate
  107.  */
  108.  
  109. void
  110. getclock(buf)
  111.     char *buf;
  112. {
  113.     int DD, MM, YY, hh, ss, mm;
  114.     unsigned date, time;
  115.  
  116.     date = TGETDATE();
  117.     time = TGETTIME();
  118.  
  119.     DD = date & 31;
  120.     MM = (date >> 5) & 15;
  121.     YY = 80 + ( (date >> 9) & 127 ); if (YY > 99) YY -= 100;
  122.  
  123.     ss = (time & 31) << 1;
  124.     mm = (time >> 5) & 63;
  125.     hh = (time >> 11) & 31;
  126.  
  127.     SPRINTF(buf, "%02d/%02d/%02d %02d:%02d:%02d\r\n", MM, DD, YY,
  128.         hh, mm, ss);
  129. }
  130.  
  131. static int
  132. getint(buf)
  133.     char *buf;
  134. {
  135.     int val = 0;
  136.  
  137.     val = *buf++ - '0';
  138.     val = 10 * val + *buf - '0';
  139.     return val;
  140. }
  141.  
  142. void
  143. setclock(buf)
  144.     char *buf;
  145. {
  146.     int DD, MM, YY, hh, mm, ss;
  147.     unsigned time, date;
  148.  
  149.     MM = getint(buf); buf += 3;
  150.     if (MM < 1 || MM > 12) return;
  151.     DD = getint(buf); buf += 3;
  152.     if (DD < 1 || DD > 31) return;
  153.     YY = getint(buf); buf += 3;
  154.     if (YY < 80 || YY > 99) return;
  155.     hh = getint(buf); buf += 3;
  156.     if (hh < 0 || hh > 23) return;
  157.     mm = getint(buf); buf += 3;
  158.     if (mm < 0 || mm > 59) return;
  159.     ss = getint(buf);
  160.     if (ss < 0 || ss > 59) return;
  161.  
  162.     time = (hh << 11) | (mm << 5) | (ss >> 1);
  163.     date = ((YY - 80) << 9) | (MM << 5) | DD;
  164.     TSETTIME(time);
  165.     TSETDATE(date);
  166. }
  167.  
  168. #define NBYTES 19    /* strlen("DD/MM/YY hh:mm:ss\r\n") */
  169.  
  170. static long
  171. clock_open(f)
  172.     FILEPTR *f;
  173. {
  174.     return 0;
  175. }
  176.  
  177. static long
  178. clock_write(f, buf, bytes)
  179.     FILEPTR *f; char *buf; long bytes;
  180. {
  181.     static char writebuf[NBYTES];
  182.     static int  bufptr = 0;
  183.     long wrote = 0;
  184.  
  185.     while (bytes-- > 0 && bufptr < NBYTES) {
  186. /* ignore CR/LF at beginning of line */
  187.         if (bufptr == 0 && (*buf == '\r' || *buf == '\n'))
  188.             buf++;
  189.         else
  190.             writebuf[bufptr++] = *buf++;
  191.         wrote++;
  192.     }
  193.  
  194. /* do we have a complete date now? if so, set the clock */
  195.     if (bufptr == NBYTES) {
  196.         setclock(writebuf);
  197.         bufptr = 0;
  198.     }
  199.     return wrote;
  200. }
  201.  
  202. static long
  203. clock_read(f, buf, bytes)
  204.     FILEPTR *f; char *buf; long bytes;
  205. {
  206.     static char readbuf[NBYTES];
  207.     int where;
  208.     long total = 0;
  209.  
  210.     getclock(readbuf);
  211.     while (f->pos < NBYTES) {
  212.         *buf++ = readbuf[f->pos++];
  213.         total++;
  214.     }
  215.     return total;
  216. }
  217.  
  218. static long
  219. clock_lseek(f, where, whence)
  220.     FILEPTR *f; long where; int whence;
  221. {
  222.     long newplace;
  223.  
  224.     switch(whence) {
  225.     case 0:
  226.         newplace = where;
  227.         break;
  228.     case 1:
  229.         newplace = f->pos + where;
  230.         break;
  231.     case 2:
  232.         newplace = (NBYTES-1) - where;
  233.         break;
  234.     }
  235.  
  236.     if (newplace < 0 || newplace >= NBYTES)
  237.         return ERANGE;
  238.  
  239.     f->pos = newplace;
  240.     return newplace;
  241. }
  242.  
  243. static long
  244. clock_ioctl(f, mode, buf)
  245.     FILEPTR *f; int mode; void *buf;
  246. {
  247.     if (mode == FIONREAD || mode == FIONWRITE) {
  248.         *((long *)buf) = (NBYTES-1) - f->pos;
  249.         return 0;
  250.     }
  251.     else
  252.         return EINVFN;
  253. }
  254.  
  255. static long
  256. clock_datime(f, timeptr, rwflag)
  257.     FILEPTR *f;
  258.     word *timeptr;
  259.     int rwflag;
  260. {
  261.     if (rwflag)
  262.         return EACCDN;
  263.     *timeptr++ = TGETTIME();
  264.     *timeptr = TGETDATE();
  265.     return 0;
  266. }
  267.  
  268. static long
  269. clock_close(f)
  270.     FILEPTR *f;
  271. {
  272.     return 0;
  273. }
  274.  
  275. static long
  276. clock_select()
  277. {
  278.     return 1;    /* we're always ready for I/O */
  279. }
  280.  
  281. static void
  282. clock_unselect()
  283. {
  284.     /* nothing for us to do here */
  285. }
  286.