|
|
1.1 ! root 1: /* ! 2: ! 3: * A simple device driver for u:\dev\clock. Reading from this ! 4: ! 5: * device produces a single line containing the current time, in the ! 6: ! 7: * format: ! 8: ! 9: * MM/DD/YY hh:mm:ss\r\n ! 10: ! 11: * Writing to it will change the time to the given one. ! 12: ! 13: * ! 14: ! 15: * This program is written by Eric R. Smith and is hereby placed in ! 16: ! 17: * the public domain. ! 18: ! 19: * ! 20: ! 21: * COMPILER NOTE: I've assumed that you're using a compiler (like gcc ! 22: ! 23: * or Lattice) that preserves registers d2 and a2 across function calls. ! 24: ! 25: * If your compiler uses these registers as scratch registers (e.g. ! 26: ! 27: * MWC, Alcyon) then you'll have to provide assembly language wrapper ! 28: ! 29: * functions that the kernel can call. ! 30: ! 31: * This code also assumes that sizeof(int) == 2. ! 32: ! 33: * ! 34: ! 35: * for gcc: compile with gcc -mshort -O clockdev.c -o clockdev.prg ! 36: ! 37: * for lcc: compile with -bn -b0 -r0 -v -w -t= clockdev.c -oclockdev.prg ! 38: ! 39: */ ! 40: ! 41: ! 42: ! 43: #ifdef __GNUC__ ! 44: ! 45: #include <minimal.h> ! 46: ! 47: #endif ! 48: ! 49: #include <osbind.h> ! 50: ! 51: #include <basepage.h> ! 52: ! 53: #include "mintbind.h" ! 54: ! 55: #include "filesys.h" ! 56: ! 57: #include "atarierr.h" ! 58: ! 59: ! 60: ! 61: #ifdef LATTICE ! 62: ! 63: #define BP _pbase ! 64: ! 65: #else ! 66: ! 67: #define BP _base ! 68: ! 69: #endif ! 70: ! 71: ! 72: ! 73: /* the name of the device we're installing */ ! 74: ! 75: char name[] = "U:\\DEV\\CLOCK"; ! 76: ! 77: ! 78: ! 79: /* kernel information */ ! 80: ! 81: struct kerinfo *kernel; ! 82: ! 83: #define CCONWS (void)(*kernel->dos_tab[0x09]) ! 84: ! 85: #define RWABS (*kernel->bios_tab[4]) ! 86: ! 87: #define GETBPB (void *)(*kernel->bios_tab[7]) ! 88: ! 89: #define TGETTIME (*kernel->dos_tab[0x2c]) ! 90: ! 91: #define TGETDATE (*kernel->dos_tab[0x2a]) ! 92: ! 93: #define TSETTIME (*kernel->dos_tab[0x2d]) ! 94: ! 95: #define TSETDATE (*kernel->dos_tab[0x2b]) ! 96: ! 97: ! 98: ! 99: #define SPRINTF (*kernel->sprintf) ! 100: ! 101: #define DEBUG (*kernel->debug) ! 102: ! 103: #define ALERT (*kernel->alert) ! 104: ! 105: #define TRACE (*kernel->trace) ! 106: ! 107: #define FATAL (*kernel->fatal) ! 108: ! 109: ! 110: ! 111: /* assumption: 16 bit integers */ ! 112: ! 113: #define word int ! 114: ! 115: ! 116: ! 117: /* device driver information */ ! 118: ! 119: static long clock_open P_((FILEPTR *)), ! 120: ! 121: clock_write P_((FILEPTR *, char *, long)), ! 122: ! 123: clock_read P_((FILEPTR *, char *, long)), ! 124: ! 125: clock_lseek P_((FILEPTR *, long, word)), ! 126: ! 127: clock_ioctl P_((FILEPTR *, word, void *)), ! 128: ! 129: clock_datime P_((FILEPTR *, word *, word)), ! 130: ! 131: clock_close P_((FILEPTR *)); ! 132: ! 133: ! 134: ! 135: static long clock_select(); ! 136: ! 137: static void clock_unselect(); ! 138: ! 139: ! 140: ! 141: DEVDRV clock_device = { ! 142: ! 143: clock_open, clock_write, clock_read, clock_lseek, clock_ioctl, ! 144: ! 145: clock_datime, clock_close, clock_select, clock_unselect, ! 146: ! 147: 0, 0, 0 ! 148: ! 149: }; ! 150: ! 151: ! 152: ! 153: struct dev_descr devinfo = { ! 154: ! 155: &clock_device, 0, 0, (struct tty *)0, 0L, 0L, 0L, 0L ! 156: ! 157: }; ! 158: ! 159: ! 160: ! 161: #ifdef LATTICE ! 162: ! 163: BASEPAGE *BP; ! 164: ! 165: ! 166: ! 167: void ! 168: ! 169: start(BASEPAGE *bp) ! 170: ! 171: { ! 172: ! 173: BP = bp; ! 174: ! 175: ! 176: ! 177: main(); ! 178: ! 179: } ! 180: ! 181: #endif ! 182: ! 183: ! 184: ! 185: /* ! 186: ! 187: * the main program just installs the device, and then does Ptermres ! 188: ! 189: * to remain resident ! 190: ! 191: */ ! 192: ! 193: ! 194: ! 195: main() ! 196: ! 197: { ! 198: ! 199: kernel = (struct kerinfo *)Dcntl(DEV_INSTALL, name, &devinfo); ! 200: ! 201: if (!kernel || ((long)kernel) == -32) { ! 202: ! 203: Cconws("Unable to install clock device\r\n"); ! 204: ! 205: Pterm(1); ! 206: ! 207: } ! 208: ! 209: Ptermres(256L + BP->p_tlen + BP->p_dlen + BP->p_blen, 0); ! 210: ! 211: } ! 212: ! 213: ! 214: ! 215: /* ! 216: ! 217: * here are the actual device driver functions ! 218: ! 219: */ ! 220: ! 221: ! 222: ! 223: /* ! 224: ! 225: * utility functions: ! 226: ! 227: * getclock(buf): get the current date and time and write it into ! 228: ! 229: * the pointed to buffer in the format "MM/DD/YY hh:mm:ss\r\n" ! 230: ! 231: * ! 232: ! 233: * setclock(buf): set the current date and time from the ASCII ! 234: ! 235: * string pointed to by buf, which must have the same format ! 236: ! 237: * as that returned by getdate ! 238: ! 239: */ ! 240: ! 241: ! 242: ! 243: void ! 244: ! 245: getclock(buf) ! 246: ! 247: char *buf; ! 248: ! 249: { ! 250: ! 251: int DD, MM, YY, hh, ss, mm; ! 252: ! 253: unsigned date, time; ! 254: ! 255: ! 256: ! 257: date = TGETDATE(); ! 258: ! 259: time = TGETTIME(); ! 260: ! 261: ! 262: ! 263: DD = date & 31; ! 264: ! 265: MM = (date >> 5) & 15; ! 266: ! 267: YY = 80 + ( (date >> 9) & 127 ); if (YY > 99) YY -= 100; ! 268: ! 269: ! 270: ! 271: ss = (time & 31) << 1; ! 272: ! 273: mm = (time >> 5) & 63; ! 274: ! 275: hh = (time >> 11) & 31; ! 276: ! 277: ! 278: ! 279: SPRINTF(buf, "%02d/%02d/%02d %02d:%02d:%02d\r\n", MM, DD, YY, ! 280: ! 281: hh, mm, ss); ! 282: ! 283: } ! 284: ! 285: ! 286: ! 287: static int ! 288: ! 289: getint(buf) ! 290: ! 291: char *buf; ! 292: ! 293: { ! 294: ! 295: int val = 0; ! 296: ! 297: ! 298: ! 299: val = *buf++ - '0'; ! 300: ! 301: val = 10 * val + *buf - '0'; ! 302: ! 303: return val; ! 304: ! 305: } ! 306: ! 307: ! 308: ! 309: void ! 310: ! 311: setclock(buf) ! 312: ! 313: char *buf; ! 314: ! 315: { ! 316: ! 317: int DD, MM, YY, hh, mm, ss; ! 318: ! 319: unsigned time, date; ! 320: ! 321: ! 322: ! 323: MM = getint(buf); buf += 3; ! 324: ! 325: if (MM < 1 || MM > 12) return; ! 326: ! 327: DD = getint(buf); buf += 3; ! 328: ! 329: if (DD < 1 || DD > 31) return; ! 330: ! 331: YY = getint(buf); buf += 3; ! 332: ! 333: if (YY < 80 || YY > 99) return; ! 334: ! 335: hh = getint(buf); buf += 3; ! 336: ! 337: if (hh < 0 || hh > 23) return; ! 338: ! 339: mm = getint(buf); buf += 3; ! 340: ! 341: if (mm < 0 || mm > 59) return; ! 342: ! 343: ss = getint(buf); ! 344: ! 345: if (ss < 0 || ss > 59) return; ! 346: ! 347: ! 348: ! 349: time = (hh << 11) | (mm << 5) | (ss >> 1); ! 350: ! 351: date = ((YY - 80) << 9) | (MM << 5) | DD; ! 352: ! 353: TSETTIME(time); ! 354: ! 355: TSETDATE(date); ! 356: ! 357: } ! 358: ! 359: ! 360: ! 361: #define NBYTES 19 /* strlen("DD/MM/YY hh:mm:ss\r\n") */ ! 362: ! 363: ! 364: ! 365: static long ! 366: ! 367: clock_open(f) ! 368: ! 369: FILEPTR *f; ! 370: ! 371: { ! 372: ! 373: return 0; ! 374: ! 375: } ! 376: ! 377: ! 378: ! 379: static long ! 380: ! 381: clock_write(f, buf, bytes) ! 382: ! 383: FILEPTR *f; char *buf; long bytes; ! 384: ! 385: { ! 386: ! 387: static char writebuf[NBYTES]; ! 388: ! 389: static int bufptr = 0; ! 390: ! 391: long wrote = 0; ! 392: ! 393: ! 394: ! 395: while (bytes-- > 0 && bufptr < NBYTES) { ! 396: ! 397: /* ignore CR/LF at beginning of line */ ! 398: ! 399: if (bufptr == 0 && (*buf == '\r' || *buf == '\n')) ! 400: ! 401: buf++; ! 402: ! 403: else ! 404: ! 405: writebuf[bufptr++] = *buf++; ! 406: ! 407: wrote++; ! 408: ! 409: } ! 410: ! 411: ! 412: ! 413: /* do we have a complete date now? if so, set the clock */ ! 414: ! 415: if (bufptr == NBYTES) { ! 416: ! 417: setclock(writebuf); ! 418: ! 419: bufptr = 0; ! 420: ! 421: } ! 422: ! 423: return wrote; ! 424: ! 425: } ! 426: ! 427: ! 428: ! 429: static long ! 430: ! 431: clock_read(f, buf, bytes) ! 432: ! 433: FILEPTR *f; char *buf; long bytes; ! 434: ! 435: { ! 436: ! 437: /* SPRINTF will stuff one too many bytes in here (the \0) */ ! 438: ! 439: static char readbuf[NBYTES+1]; ! 440: ! 441: int where; ! 442: ! 443: long total = 0; ! 444: ! 445: ! 446: ! 447: getclock(readbuf); ! 448: ! 449: while (f->pos < NBYTES) { ! 450: ! 451: *buf++ = readbuf[f->pos++]; ! 452: ! 453: total++; ! 454: ! 455: } ! 456: ! 457: return total; ! 458: ! 459: } ! 460: ! 461: ! 462: ! 463: static long ! 464: ! 465: clock_lseek(f, where, whence) ! 466: ! 467: FILEPTR *f; long where; int whence; ! 468: ! 469: { ! 470: ! 471: long newplace; ! 472: ! 473: ! 474: ! 475: switch(whence) { ! 476: ! 477: case 0: ! 478: ! 479: newplace = where; ! 480: ! 481: break; ! 482: ! 483: case 1: ! 484: ! 485: newplace = f->pos + where; ! 486: ! 487: break; ! 488: ! 489: case 2: ! 490: ! 491: newplace = (NBYTES-1) - where; ! 492: ! 493: break; ! 494: ! 495: } ! 496: ! 497: ! 498: ! 499: if (newplace < 0 || newplace >= NBYTES) ! 500: ! 501: return ERANGE; ! 502: ! 503: ! 504: ! 505: f->pos = newplace; ! 506: ! 507: return newplace; ! 508: ! 509: } ! 510: ! 511: ! 512: ! 513: static long ! 514: ! 515: clock_ioctl(f, mode, buf) ! 516: ! 517: FILEPTR *f; int mode; void *buf; ! 518: ! 519: { ! 520: ! 521: if (mode == FIONREAD || mode == FIONWRITE) { ! 522: ! 523: *((long *)buf) = (NBYTES-1) - f->pos; ! 524: ! 525: return 0; ! 526: ! 527: } ! 528: ! 529: else ! 530: ! 531: return EINVFN; ! 532: ! 533: } ! 534: ! 535: ! 536: ! 537: static long ! 538: ! 539: clock_datime(f, timeptr, rwflag) ! 540: ! 541: FILEPTR *f; ! 542: ! 543: word *timeptr; ! 544: ! 545: int rwflag; ! 546: ! 547: { ! 548: ! 549: if (rwflag) ! 550: ! 551: return EACCDN; ! 552: ! 553: *timeptr++ = TGETTIME(); ! 554: ! 555: *timeptr = TGETDATE(); ! 556: ! 557: return 0; ! 558: ! 559: } ! 560: ! 561: ! 562: ! 563: static long ! 564: ! 565: clock_close(f) ! 566: ! 567: FILEPTR *f; ! 568: ! 569: { ! 570: ! 571: return 0; ! 572: ! 573: } ! 574: ! 575: ! 576: ! 577: static long ! 578: ! 579: clock_select() ! 580: ! 581: { ! 582: ! 583: return 1; /* we're always ready for I/O */ ! 584: ! 585: } ! 586: ! 587: ! 588: ! 589: static void ! 590: ! 591: clock_unselect() ! 592: ! 593: { ! 594: ! 595: /* nothing for us to do here */ ! 596: ! 597: } ! 598:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.