home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / sys / next / programm / 5703 < prev    next >
Encoding:
Text File  |  1992-08-19  |  7.2 KB  |  137 lines

  1. Newsgroups: comp.sys.next.programmer
  2. Path: sparky!uunet!gumby!destroyer!ncar!unmvax!ctm
  3. From: ctm@ardi.com (Clifford T. Matthews)
  4. Subject: Re: _IO, _IOR, _IOW and _IOWR functions
  5. Message-ID: <1992Aug19.220946.13633@unmvax.cs.unm.edu>
  6. Keywords: pedantic, long
  7. Sender: ctm@unmvax.cs.unm.edu (Clifford T. Matthews)
  8. Organization: ARDI
  9. Date: Wed, 19 Aug 92 22:09:46 GMT
  10. Lines: 125
  11.  
  12. Dear curious/bored folks,
  13.  
  14. The "routines" that the subject line alludes to are actually macros that
  15. are used to create "magic cookies" for the ioctl system call.  By magic
  16. cookie, I mean a unique integer identifier.  Here's a brief top-of-my-head
  17. history of ioctls and such:
  18.  
  19. In general, UNIX allows you to do three different things with devices:
  20. read, write, and "everything else".  Reading and writing need no further
  21. explanation; "everything else" (done with the "ioctl" system call) varies
  22. from device to device, but includes things like setting the input and output
  23. speed for terminals, setting the density for tapes as well as werid stuff
  24. like raw scsi commands (you need root to do these, which is good).
  25.  
  26. In general, UNIX has little abbreviations for the devices that it supports.
  27. The NeXT has support for things like "sd" (SCSI drive), "od" (optical drive),
  28. "zs" (zilog serial communications controler (terminal port)) and so on.  When
  29. you need to do low-level accesses to these things you wind up writing code
  30. that looks like:
  31.  
  32.     int filedescriptor;
  33.     char buf[1024];
  34.  
  35.     filedescriptor = open("/dev/rsd0h", O_RDONLY);
  36.     nread = read(filedescriptor, buf, sizeofbuff);
  37.     ...
  38.     err = close(filedescriptor);
  39.     ...
  40.  
  41. In the above example "/dev/rsd0h" identifies that you want to open up
  42. the first logical SCSI drive (drive 0).  The "h" means the special
  43. partition that allows you to get to normally inaccessible portions of
  44. the disk and the "r" preceeding the "sd" means you want "raw" access,
  45. i.e. you'll be bypassing the normal UNIX block buffering cache.
  46.  
  47. You can read about raw SCSI access in the "sd" man page.  If you do, you
  48. will see that you can do other things with disks, like eject them.
  49. To do so, you use the DKIOCEJECT ioctl argument, as in:
  50.  
  51.     err = ioctl(filedescriptor, DKIOCEJECT, (char *) 0);
  52.  
  53. In the above example the third argument to the ioctl is zero, cast as a
  54. pointer to char.  We do that because DKIOCEJECT doesn't need any extra
  55. information to do it's job.  The file descriptor that is passed in is
  56. sufficient to identify which disk to eject.  However, some ioctls need
  57. extra information, or return extra information, or both.  We're now
  58. ready to look at _IO, _IOR, _IOW and _IOWR.
  59.  
  60. It turns out that if you "grep DKIOCEJECT /usr/include/nextdev/*.h",
  61. you'll see that DKIOEJECT is a #define that looks like this:
  62.  
  63. #define     DKIOCEJECT      _IO('d', 21)                    /* eject disk */
  64.  
  65. _IO is just a macro that generates a unique number that the implementors
  66. of ioctl for disks can look at.  The 'd' is a single character that serves
  67. to identify what kind of device the ioctl is relevant to 'd' in this case
  68. stands for disk.  As long as people are consistent and there's no collision,
  69. it doesn't matter what the letter is.  The second argument, 21, is just
  70. a unique number that keeps DKIOCEJECT separate from the other 'd' ioctls.
  71. If you "grep _IO /usr/include/nextdev/disk.h", you'll get this for output:
  72.  
  73. #define DKIOCGLABEL     _IO('d', 0)                     /* read label */
  74. #define DKIOCSLABEL     _IO('d', 1)                     /* write label */
  75. #define DKIOCGBITMAP    _IO('d', 2)                     /* read bitmap */
  76. #define DKIOCSBITMAP    _IO('d', 3)                     /* write bitmap */
  77. #define DKIOCREQ        _IOWR('d', 4, struct disk_req)  /* cmd request */
  78. #define DKIOCINFO       _IOR('d', 5, struct drive_info) /* get drive info */
  79. #define DKIOCZSTATS     _IO('d',7)                      /* zero statistics */
  80. #define DKIOCGSTATS     _IO('d', 8)                     /* get statistics */
  81. #define DKIOCRESET      _IO('d', 9)                     /* reset disk */
  82. #define DKIOCGFLAGS     _IOR('d', 11, int)              /* get driver flags */
  83. #define DKIOCSFLAGS     _IOW('d', 12, int)              /* set driver flags */
  84. #define DKIOCSDCWIRE    _IOW('d', 14, struct sdc_wire)  /* sdc wire memory */
  85. #define DKIOCSDCLOCK    _IO('d', 15)                    /* sdc lock */
  86. #define DKIOCSDCUNLOCK  _IO('d', 16)                    /* sdc unlock */
  87. #define DKIOCGFREEVOL   _IOR('d', 17, int)              /* get free volume # */
  88. #define DKIOCGBBT       _IO('d', 18)                    /* read bad blk tbl */
  89. #define DKIOCSBBT       _IO('d', 19)                    /* write bad blk tbl */
  90. #define DKIOCMNOTIFY    _IOW('d', 20, int)              /* message on insert */
  91. #define DKIOCEJECT      _IO('d', 21)                    /* eject disk */
  92. #define DKIOCPANELPRT   _IOW('d', 22, int)              /* register Panel 
  93. #define DKIOCSFORMAT    _IOW('d', 23, int)              /* set 'Formatted' flag 
  94. #define DKIOCGFORMAT    _IOR('d', 23, int)              /* get 'Formatted' flag 
  95.  
  96. See, someone just arbitrarily assigned numbers for the various special things
  97. that you may want to do to disks.  Not all of the #defines are _IO, there's
  98. also _IOR, _IOW and _IOWR.  Those used when the ioctl needs to read information
  99. from the device, write information to the device or both, respectively.
  100. With those three variants of _IO, a little more is being done then creating
  101. a unique number; the nunmber of bytes that need to be copied between
  102. "user space" (i.e. your program) and "kernel space" (i.e. the UNIX operating
  103. system) is also rolled into the "magic cookie".  Specifically those three
  104. variants use sizeof(arg3) to determine how many bytes are going to need to
  105. be transferred.  So in reality, the magic cookie consists of four things:
  106.  
  107.     The type of device we're operating with/on
  108.     A unique number identifying the type of operation we're doing
  109.     a pair of direction flags no direction, read, write, both
  110.         and
  111.     the number of bytes that will be moved.
  112.  
  113. So now the question is what can you do with _IO and friends?  Basically Nothing.
  114. There is no point to rolling your own "magic cookies", because the device
  115. drivers only know about the ioctls that are available through their (slightly)
  116. less cryptic names (i.e. "DKIOCEJECT" vs. "_IO('d', 21)").  However, there
  117. are rare times when you may want to know what kind of "ioctl"s an application
  118. is using.  In that case, you can find the #defines for "_IO" and friends and
  119. figure out what the various magic cookies for the various ioctl calls, and
  120. then use gdb on the mystery program and take a look at the args on the stack
  121. when ioctl is called.
  122.  
  123. As always, if a routine requires super-user privs to function, you should be
  124. very wary of using it; when you're doing low-level accesses to disks and
  125. what not, you can really do a lot of damage in a short time.
  126.  
  127. BTW, I enjoy learning about things via the net, but I really like to see
  128. references rather than information; I try to do unto others ..., but in
  129. this case I'm not really sure what a relevant reference would be, perhaps
  130. a book about programming the kernel, or the design/history of UNIX.  The
  131. trouble is, I was hacking UNIX kernels before those books were published,
  132. so I'm not adequately familar with the books to tell you whether or not
  133. they go into such little details.
  134.  
  135.     --Cliff[ord T. Matthews]
  136.     ctm@ardi.com
  137.