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