home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddrivers.zip / UTILS / KPRINTF.C < prev    next >
C/C++ Source or Header  |  1992-12-10  |  7KB  |  248 lines

  1. /* kprintf, kernel printf function */
  2. /*
  3.    This code is released to the public domain. You are free to modify
  4.     and use it as you wish, but you may not charge anything for it.
  5. */
  6.  
  7.  
  8. /* for kprintf(), define COLOR_SYSTEM if you are using a color adapter. If
  9.    you are using a monochrome adapter, comment out the next #define.
  10.    N.B. OS/2 2.0 can only run with a COLOR_SYSTEM, and thus this constant
  11.    should always be defined. */
  12. #define COLOR_SYSTEM
  13.  
  14. //#define DEBUG1        /* init */
  15.  
  16. /* most of the time when DEBUGx is defined, the debugging method is mainly
  17.    print message to screen using kprintf(). In order to use kprintf(), 
  18.    KERNEL_PRINTF must be defined. Note: if the DEBUGx does not use kprintf(),
  19.    there is no need to include it in the following OR'ed list.
  20. */
  21. #if defined(DEBUG1) || defined(DEBUG2) || defined(DEBUG3) || defined(DEBUG4)
  22. #define KERNEL_PRINTF
  23. #endif
  24.  
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <errno.h>
  28. #include <conio.h>
  29. #include <ctype.h>
  30. #include "drvlib.h"
  31.  
  32. /* for kprintf */
  33. #ifdef COLOR_SYSTEM
  34. #define SCR_BASE    0xB8000L
  35. #else
  36. #define SCR_BASE    0xB0000L        /* monochrome */
  37. #endif
  38.  
  39. /*******************************
  40. *
  41.     WARNING: Device Header must be the first data structure in the data
  42.     segment. Make sure there is no variable declaration placed before
  43.     this structure declaration. In addition, please make sure no auto-string
  44.     initialization in this program. These string will be placed in the beginning
  45.     of the data segment by the MS C compiler.
  46.  
  47.     All followings examples are on the allocation of "this is a test" in DS.
  48.     The unacceptable forms are:
  49.         char *message = "this is a test";
  50.         string_pointer = "this is a test";
  51.  
  52.     Ok forms are:
  53.         char message[] = "this is a test"
  54.         kprintf("this is a test");
  55.  
  56. *
  57. ********************************/
  58.  
  59. /* devhdr here */
  60.  
  61. /*************************************
  62.     Free to declare globals after this point.
  63. *************************************/
  64.  
  65. FPFUNCTION DevHlp;
  66. #ifdef KERNEL_PRINTF
  67. SEL GDTsel;
  68. char far *scr_ptr;
  69. ULONG SCR_TOP, SCR_BOTTOM;
  70. #endif
  71.  
  72. /* the following two variables are basically used by kprintf(). But other can
  73.    use the buffer too, but have to keep in mind to block interrupt if necessary
  74. */
  75. char buffer[120];
  76. char digitbuf[16];
  77.  
  78. #ifdef KERNEL_PRINTF
  79. void kprintf(char *, ...);
  80. #endif
  81.  
  82. /*
  83.     The C compiler will put any constant string in the first routine in the
  84.     source file to the beginning of the data segment. This will displace the
  85.     DEVHDR data structure from being placed in the very beginning of the
  86.     data segment. For example, if main() is the first routine in the source
  87.     file, the statement 'kprintf("this is a test");' will have the constant
  88.     string being placed at ORG 0 of data segment by the compiler. On contrary,
  89.     if ioctl() is the next routine, the same statement will have a very
  90.     different behavior: the constant string will be placed following all the
  91.     global defines, which is the way we want. The reason to define a dummy
  92.     routine in here is to allow kprintf to be used in any routines without
  93.     worrying the DEVHDR business.
  94. */
  95. xxxxxxx(){}
  96.  
  97. main (PREQPACKET rp, int lindex)
  98. {
  99.     int rc;
  100.  
  101.     switch(rp->RPcommand) {
  102.         case RPINIT:
  103.             return(init(rp, lindex));
  104.  
  105.         default:
  106.             return(RPDONE | RPERR | ERROR_BAD_COMMAND);
  107.  
  108.     } /* switch request packet */
  109. } /* main */
  110.  
  111.  
  112. init (PREQPACKET rp, int device)
  113. {
  114.     int rc;
  115.  
  116.     DevHlp = rp->s.Init.DevHlp;
  117.     
  118. #ifdef KERNEL_PRINTF
  119.     /* map screen to LDT, as we can't use GDT at init time */
  120.     PhysToUVirt(SCR_BASE, 0x1000, 1, &scr_ptr);
  121.     SCR_TOP = (ULONG) scr_ptr;
  122.     SCR_BOTTOM = (ULONG) scr_ptr + (80 * 22 * 2);
  123.     AllocGDTSelector(1, &GDTsel);
  124.     /* and now we can use kprintf() in INIT time */
  125. #endif
  126.  
  127.     /* drvr ... */
  128.     rc = DosPutMessage(1, sizeof(init_str1) - 1, init_str1);
  129.     if (rc)
  130.         init_abort(rp, errmsg1);
  131.  
  132. #ifdef DEBUG1
  133.     kprintf("rc = %d, semaphore = %x:%x ", rc, SELECTOROF(IR_LS_semaphore),
  134.         OFFSETOF(IR_LS_semaphore));
  135. #endif
  136.  
  137.     /* ready to quit INIT */
  138.  
  139. #ifdef KERNEL_PRINTF
  140.     /* free the screen pointer for kprintf() from LDT entry */
  141.     PhysToUVirt((ULONG) scr_ptr & 0xFFFF0000UL, 0x1000, 2, &scr_ptr);
  142.     /* then remap the same pointer to use GDT */
  143.     /* the screen size is 80 * 25 then times 2 (char and attr) */
  144.     PhysToGDTSelector(SCR_BASE, 4000, GDTsel, &error);
  145.     scr_ptr = MAKEP(GDTsel, 80 << 1);
  146.     SCR_TOP = (ULONG) scr_ptr;        /* brk up the statement just to avoid 
  147.                 C compiler warning. */
  148.     SCR_BOTTOM = (ULONG) scr_ptr + (80 * 22 * 2);
  149. #endif
  150.  
  151.     rp->s.InitExit.units = 0;        /* must be 0 for character device */
  152.     SegLimit(HIUSHORT((void far *) init), &rp->s.InitExit.finalCS);
  153.     SegLimit(HIUSHORT((void far *) init_str1), &rp->s.InitExit.finalDS);
  154.     rp->s.InitExit.BPBarray = NULL;
  155.     return(RPDONE);
  156.  
  157. } /* init */
  158.  
  159.  
  160. init_abort (PREQPACKET rp, char *errmsg)
  161. {
  162.     int i;
  163.  
  164.     Beep(500,200);
  165.     DosPutMessage(1, strlen(errmsg), errmsg);
  166.     DosPutMessage(1, sizeof(init_err_final) - 1, init_err_final);
  167.  
  168. #ifdef KERNEL_PRINTF
  169.     /* free the screen pointer for kprintf() from LDT entry */
  170.     PhysToUVirt((ULONG) scr_ptr & 0xFFFF0000UL, 0x1000, 2, &scr_ptr);
  171.     /* free GDT */
  172.     FreeGDTSelector(GDTsel);
  173. #endif
  174.     rp->s.InitExit.finalCS = (OFF) 0;
  175.     rp->s.InitExit.finalDS = (OFF) 0;
  176.  
  177.     RHT_INTR_INTV = 0;        /* this will make sure all sequence device's
  178.             INIT will also return error and so the driver will not be
  179.             installed. */
  180.     return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  181.  
  182. } /* init_abort */
  183.  
  184.  
  185. #ifdef KERNEL_PRINTF
  186. /**************************************
  187.  
  188.     kprintf() allow DD to print stuff on the screen while in kernel mode.
  189.     It can't scroll screen. When pointer is almost at the bottom, output
  190.     will be wrap back to the beginning of the screen.
  191.  
  192.     kprintf() takes only the %x, %d and %s formatter. Please make sure to
  193.     use the right case (lower case). Note: since the DD can't assume SS
  194.     as DGROUP, you cannot print %s from stack's value. In other words, 
  195.     this routine will not print right if the string is on the stack.
  196.     The string must be in the DS.
  197.  
  198.     Note: output starts from the second line on the screen as OS/2 will
  199.     overprint the top line when cmd.exe takes control.
  200.  
  201. ***************************************/
  202. void kprintf (char *str, ...)
  203. {
  204.     char *ptr, *xptr;
  205.     int far *argumentp;
  206.  
  207.     buffer[0] = 0;
  208.     argumentp = (int far *) (((ULONG) (int far *) &str) + sizeof(int));
  209.     ptr = str;
  210.     while ((xptr = strchr(ptr, '%')) != (char *) NULL) {
  211.         *xptr = 0;
  212.         strcat(buffer, ptr);
  213.         *xptr++ = '%';
  214.         if (*xptr == 'x') {
  215.             itoa(*argumentp++, digitbuf, 16);
  216.             strcat(buffer, digitbuf);
  217.         } else if (*xptr == 'd') {
  218.             itoa(*argumentp++, digitbuf, 10);
  219.             strcat(buffer, digitbuf);
  220.         } else if (*xptr == 's') {
  221.             strcat(buffer, (char *) *argumentp++);
  222.         } else {
  223.             strcat(buffer, "%");
  224.             if (*xptr == 0) {    /* str ends in % with nothing follows */
  225.                 ptr = xptr;        /* so the strcat will cat nothing */
  226.                 break;
  227.             }
  228.         }
  229.         ptr = xptr + 1;
  230.     }
  231.     strcat(buffer, ptr);
  232.  
  233.     /* print it out */
  234.     /* disable intr while modifying global data */
  235.     spl5();        /* cli */
  236.     ptr = buffer;
  237.     while (*ptr) {
  238.         *scr_ptr = *ptr++;
  239.         scr_ptr += 2;
  240.         if ((ULONG) scr_ptr > SCR_BOTTOM)
  241.             scr_ptr = (char far *) SCR_TOP;
  242.     }
  243.     splx();        /* sti */
  244.  
  245. } /* kprint */
  246. #endif        /* KERNEL_PRINTF */
  247.  
  248.