home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / mmap-2.2.3 / part02 < prev    next >
Text File  |  1993-12-27  |  40KB  |  1,211 lines

  1. Newsgroups: comp.sources.unix
  2. From: thomas@aeon.in-berlin.de (Thomas Wolfram)
  3. Subject: v27i194: mmap-2.2.3 - A SVR3.2 Memory Mapped I/O Driver v2.2.3, Part02/02
  4. References: <1.757030996.11792@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: thomas@aeon.in-berlin.de (Thomas Wolfram)
  9. Posting-Number: Volume 27, Issue 194
  10. Archive-Name: mmap-2.2.3/part02
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 2 (of 2)."
  19. # Contents:  mmap-2.2.3/mmap.7 mmap-2.2.3/mmap.c mmap-2.2.3/mmap.man
  20. # Wrapped by thomas@aeon on Mon Dec 27 21:18:39 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'mmap-2.2.3/mmap.7' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'mmap-2.2.3/mmap.7'\"
  24. else
  25. echo shar: Extracting \"'mmap-2.2.3/mmap.7'\" \(12533 characters\)
  26. sed "s/^X//" >'mmap-2.2.3/mmap.7' <<'END_OF_FILE'
  27. X
  28. X
  29. X
  30. X          mmap(7L)                     386/ix                      mmap(7L)
  31. X
  32. X
  33. X
  34. X          NAME
  35. X               mmap - MMMMMMMMAAAAPPPP ioctl commands (memory mapped I/O support)
  36. X
  37. X          SYNOPSIS
  38. X               #include <sys/types.h>
  39. X               #ifndef SCO
  40. X               #include <sys/at_ansi.h>
  41. X               #include <sys/kd.h>
  42. X               #else
  43. X               #include <sys/vtkd.h>
  44. X               #endif
  45. X               #include <sys/sysmacros.h>
  46. X               #include <sys/immu.h>
  47. X               #include <sys/region.h>
  48. X               #include <sys/mmap.h>
  49. X
  50. X               int ioctl(fildes, command, arg);
  51. X               int fildes, command;
  52. X
  53. X          DESCRIPTION
  54. X               _M_M_A_P is a pseudo device driver which provides memory mapped
  55. X               I/O for user processes, i.e. direct mapping of physical
  56. X               memory ranges into the user's virtual address space for fast
  57. X               access. It is especially useful for accessing the linear
  58. X               frame buffers of certain graphic hardware from the user
  59. X               level.
  60. X
  61. X               To executing the _M_M_A_P _i_o_c_t_l commands _f_i_l_d_e_s must be an open
  62. X               file descriptor [see _o_p_e_n(_2)] that refers to the special
  63. X               character device /_d_e_v/_m_m_a_p. The effective user ID of the
  64. X               calling process must be superuser.
  65. X               The driver uses shared memory type regions for mapping. So
  66. X               the maximum number of regions the driver can attach to a
  67. X               process is limited by the maximum number of shared memory
  68. X               regions which can be attached to the process [see _s_h_m_g_e_t(_2),
  69. X               _s_h_m_o_p(_2), _s_h_m_c_t_l(_2)]. This number is a tunable system param-
  70. X               eter (_S_H_M_S_E_G) [see _k_c_o_n_f_i_g(_1), _i_d_t_u_n_e(_1_M)].
  71. X               The number of regions which the driver is able to map
  72. X               system-wide (i.e. to all running processes) is limited too.
  73. X               This number is also a tunable system parameter (_N_M_M_A_P_R_E_G).
  74. X
  75. X               Note, the _M_M_A_P driver grows the virtual address space of the
  76. X               calling process by itself. Allocating address space before
  77. X               with _m_a_l_l_o_c(_3) isn't necessary and will not work.
  78. X               The mapping regions allocated by the driver will always be
  79. X               sharable, never private to a process. Regions can be of type
  80. X               read/write or read/only.  This depends from the _m_o_d_e
  81. X               /_d_e_v/_m_m_a_p is opened [see _o_p_e_n(_2)].  Once a region is allo-
  82. X               cated and mapped to a process it will normally remain in the
  83. X               system (until reboot) even if the last process which pointed
  84. X               at it detaches it from its address space. (This is not much
  85. X               waste since the _M_M_A_P driver allocates no physical pages for
  86. X               the mapping region.)  But with the _U_N_M_A_P_R_M ioctl removing
  87. X
  88. X
  89. X          Rev. 2.2.3, 22 November 1993                               Page 1
  90. X
  91. X
  92. X
  93. X
  94. X
  95. X
  96. X          mmap(7L)                     386/ix                      mmap(7L)
  97. X
  98. X
  99. X
  100. X               after unmapping can be requested [see below and _m_m_a_p_r_m(_1_L)].
  101. X               If a process wants to map in the same memory range like
  102. X               another one (e.g. if it's the same program which is running
  103. X               again) it will be attached with the already existing region
  104. X               by the driver. Same applies if the processes which requests
  105. X               the same mapping are running simultaneously.
  106. X
  107. X             Ioctl Calls
  108. X               The following ioctl commands can be used:
  109. X
  110. X               MMMMAAAAPPPP
  111. X                 This call maps physical memory into the virtual address
  112. X                 space of the user process. The following structure,
  113. X                 defined in <sys/kd.h> [see _d_i_s_p_l_a_y(_7)], is pointed to by
  114. X                 the argument _a_r_g to the ioctl:
  115. X
  116. X                 struct kd_memloc {
  117. X                      char  *vaddr;     /* virtual address to map to */
  118. X                      char  *physaddr;  /* physical address to map from */
  119. X                      long  length;     /* size in bytes to map */
  120. X                      long  ioflg;      /* not used by the _M_M_A_P driver */
  121. X                 };
  122. X
  123. X                 The _v_a_d_d_r argument is the linear address in the process
  124. X                 where the physical memory range will appear. This address
  125. X                 must be on a boundary specified by the machine dependant
  126. X                 constant _M_M_A_P_L_B_A, defined in <sys/mmap.h>. If _v_a_d_d_r is
  127. X                 equal to zero the address is selected by the driver
  128. X                 itself.
  129. X                 The _p_h_y_s_a_d_d_r argument is the physical address of the
  130. X                 memory range that will be mapped in. It must be on a page
  131. X                 boundary.
  132. X                 The _l_e_n_g_t_h argument is the size of the memory range that
  133. X                 will be mapped in. It will be rounded up to a multiple of
  134. X                 the size of a page by the driver.
  135. X                 On success the ioctl will return the virtual address where
  136. X                 the memory is mapped in. It will fail if one or more of
  137. X                 the following is true:
  138. X
  139. X                   [EPERM]        The effective user ID of the calling pro-
  140. X                                  cess is not superuser.
  141. X
  142. X                   [EFAULT]       The user address pointed to by _a_r_g is
  143. X                                  illegal.
  144. X
  145. X                   [EINVAL]       The _v_a_d_d_r argument is not equal to zero,
  146. X                                  and the value is an illegal address (not
  147. X                                  on a MMAPLBA boundary, already used in
  148. X                                  the process or not below _M_A_X_U_V_A_D_R, as
  149. X                                  defined in <sys/immu.h>).
  150. X
  151. X                   [EINVAL]       The _p_h_y_s_a_d_d_r argument is not on a page
  152. X                                  boundary.
  153. X
  154. X
  155. X          Rev. 2.2.3, 22 November 1993                               Page 2
  156. X
  157. X
  158. X
  159. X
  160. X
  161. X
  162. X          mmap(7L)                     386/ix                      mmap(7L)
  163. X
  164. X
  165. X
  166. X                   [ENOMEM]       The _v_a_d_d_r argument is equal to zero and
  167. X                                  the driver is not able to find a proper
  168. X                                  region in the user's address space where
  169. X                                  the memory range would fit in.
  170. X
  171. X                   [ENOMEM]       The size of the user's virtual address
  172. X                                  space would exceed the system-imposed
  173. X                                  limit.
  174. X
  175. X                   [ENOMEM]       Not enough system internal space avail-
  176. X                                  able to grow the user's virtual address
  177. X                                  space.
  178. X
  179. X                   [EMFILE]       The number of shared memory segments
  180. X                                  attached to the calling process would
  181. X                                  exceed the system-imposed limit.
  182. X
  183. X                   [EMFILE]       The number of all memory mapped regions
  184. X                                  in the system would exceed the driver-
  185. X                                  imposed limit.
  186. X
  187. X               UUUUNNNNMMMMAAAAPPPP
  188. X                 This call unmaps previously mapped physical memory from
  189. X                 the calling process.  The argument _a_r_g to the ioctl must
  190. X                 be the virtual address as returned by the previous _M_A_P
  191. X                 ioctl.
  192. X                 It will fail if one or more of the following is true:
  193. X
  194. X                   [EPERM]        The effective user ID of the calling pro-
  195. X                                  cess is not superuser.
  196. X
  197. X                   [EINVAL]       If _a_r_g is not the start address of a
  198. X                                  region mapped by the driver to the cal-
  199. X                                  ling process.
  200. X
  201. X               UUUUNNNNMMMMAAAAPPPPRRRRMMMM
  202. X                 Same like _U_N_M_A_P but removes the concerning region from the
  203. X                 systems internal list, if no other process is still using
  204. X                 it [see _m_m_a_p_r_m(_1_L)].
  205. X
  206. X               GGGGEEEETTTTNNNNMMMMMMMMRRRREEEEGGGG
  207. X                 This call returns the number of the memory mapped I/O
  208. X                 regions which exists currently in the system [_s_e_e
  209. X                 _m_m_a_p_s_t_a_t(_1_L)]. It requires no argument. It will fail if
  210. X                 one or more of the following is true:
  211. X
  212. X                   [EPERM]        The effective user ID of the calling pro-
  213. X                                  cess is not superuser.
  214. X
  215. X               GGGGEEEETTTTMMMMMMMMRRRREEEEGGGG
  216. X                 This call returns the current status of the _M_M_A_P driver.
  217. X                 The argument _a_r_g must be a pointer to an array of elements
  218. X                 of the following type (defined in <sys/mmap.h>):
  219. X
  220. X
  221. X          Rev. 2.2.3, 22 November 1993                               Page 3
  222. X
  223. X
  224. X
  225. X
  226. X
  227. X
  228. X          mmap(7L)                     386/ix                      mmap(7L)
  229. X
  230. X
  231. X
  232. X                 typedef struct mmapinfo {
  233. X                      paddr_t physaddr; /* physical address */
  234. X                      long  length;     /* size in bytes */
  235. X                      short refcnt;     /* number of users */
  236. X                      /* pointing currently at this region */
  237. X                 } mmapinfo_t;
  238. X
  239. X                 which is filled by the driver for every region currently
  240. X                 exists.  The array must have as much elements as the
  241. X                 number returned by the _G_E_T_N_M_M_R_E_G ioctl states [see
  242. X                 _m_m_a_p_s_t_a_t(_1_L)].  The command will fail if one or more of
  243. X                 the following is true:
  244. X
  245. X                   [EPERM]        The effective user ID of the calling pro-
  246. X                                  cess is not superuser.
  247. X
  248. X                   [EFAULT]       The user address pointed to by _a_r_g is
  249. X                                  illegal.
  250. X
  251. X
  252. X
  253. X               GGGGEEEETTTTVVVVEEEERRRRSSSSIIIIOOOONNNN
  254. X                 Returns version number of driver, e.g. version 2.2.1 would
  255. X                 be returned as 0x0221.
  256. X
  257. X          FILES
  258. X               /_d_e_v/_m_m_a_p
  259. X                 Character device interface to the driver.
  260. X
  261. X          SEE ALSO
  262. X               open(2), ioctl(2), display(7), shmget(2), shmop(2),
  263. X               shmctl(2), kconfig(1), idtune(1M), intro(2), mmapstat(1L),
  264. X               mmaprm(1L).
  265. X
  266. X          DIAGNOSTICS
  267. X               Upon sucessful completion, the return value is as follows:
  268. X
  269. X                    The _M_A_P ioctl returns the user's address where the phy-
  270. X                    sical memory is mapped in.
  271. X
  272. X                    The _U_N_M_A_P and _U_N_M_A_P_R_M ioctl's return a value of 0.
  273. X
  274. X                    The _G_E_T_N_M_M_R_E_G ioctl returns the number of memory mapped
  275. X                    I/O regions which exists currently in the system.
  276. X
  277. X                    The _G_E_T_M_M_R_E_G ioctl returns a value of 0.
  278. X
  279. X                    The _G_E_T_V_E_R_S_I_O_N ioctl returns the version number.
  280. X
  281. X               Otherwise, a value of -1 is returned, and _e_r_r_n_o [see
  282. X               _i_n_t_r_o(_2)] is set to indicate the error.
  283. X
  284. X          BUGS
  285. X
  286. X
  287. X          Rev. 2.2.3, 22 November 1993                               Page 4
  288. X
  289. X
  290. X
  291. X
  292. X
  293. X
  294. X          mmap(7L)                     386/ix                      mmap(7L)
  295. X
  296. X
  297. X
  298. X               Please report bugs to:  wwwwoooollllffff@@@@pppprrrrzzzz....ttttuuuu----bbbbeeeerrrrlllliiiinnnn....ddddeeee or
  299. X               tttthhhhoooommmmaaaassss@@@@aaaaeeeeoooonnnn....iiiinnnn----bbbbeeeerrrrlllliiiinnnn....ddddeeee.
  300. X
  301. X          COPYING
  302. X               Copyright (c) 1993 Thomas Wolfram
  303. X
  304. X          AUTHOR
  305. X               Thomas Wolfram
  306. X
  307. X
  308. X
  309. X
  310. X
  311. X
  312. X
  313. X
  314. X
  315. X
  316. X
  317. X
  318. X
  319. X
  320. X
  321. X
  322. X
  323. X
  324. X
  325. X
  326. X
  327. X
  328. X
  329. X
  330. X
  331. X
  332. X
  333. X
  334. X
  335. X
  336. X
  337. X
  338. X
  339. X
  340. X
  341. X
  342. X
  343. X
  344. X
  345. X
  346. X
  347. X
  348. X
  349. X
  350. X
  351. X
  352. X
  353. X          Rev. 2.2.3, 22 November 1993                               Page 5
  354. X
  355. X
  356. X
  357. END_OF_FILE
  358. echo shar: 599 control characters may be missing from \"'mmap-2.2.3/mmap.7'\"
  359. if test 12533 -ne `wc -c <'mmap-2.2.3/mmap.7'`; then
  360.     echo shar: \"'mmap-2.2.3/mmap.7'\" unpacked with wrong size!
  361. fi
  362. # end of 'mmap-2.2.3/mmap.7'
  363. fi
  364. if test -f 'mmap-2.2.3/mmap.c' -a "${1}" != "-c" ; then 
  365.   echo shar: Will not clobber existing file \"'mmap-2.2.3/mmap.c'\"
  366. else
  367. echo shar: Extracting \"'mmap-2.2.3/mmap.c'\" \(15554 characters\)
  368. sed "s/^X//" >'mmap-2.2.3/mmap.c' <<'END_OF_FILE'
  369. X/*
  370. X * Copyright (c) 1993 by Thomas Wolfram, Berlin, Germany.
  371. X *
  372. X * Permission to use, copy, modify, distribute, and sell this software and its
  373. X * documentation for any purpose is hereby granted without fee, provided that
  374. X * the above copyright notice appear in all copies and that both that
  375. X * copyright notice and this permission notice appear in supporting
  376. X * documentation, and that the name of Thomas Wolfram be used in
  377. X * advertising or publicity pertaining to distribution of the software without
  378. X * specific, written prior permission.  Thomas Wolfram makes no
  379. X * representations about the suitability of this software for any purpose.
  380. X * It is provided "as is" without express or implied warranty.
  381. X *
  382. X * THOMAS WOLFRAM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  383. X * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  384. X * EVENT SHALL THOMAS WOLFRAM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  385. X * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  386. X * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  387. X * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  388. X * PERFORMANCE OF THIS SOFTWARE.
  389. X *
  390. X * Author: Thomas Wolfram, thomas@aeon.in-berlin.de, wolf@prz.tu-berlin.de
  391. X */
  392. X
  393. X#if !defined (M_I286)
  394. X#ident    "@(#)mmap.c - MMAP v2.2.3, Copyright (c) Thomas Wolfram 1993"
  395. X#endif
  396. X
  397. X#define MMAP_MAJ 2
  398. X#define MMAP_MIN 2
  399. X#define MMAP_PL  3
  400. X#define MMAPVERSION MMAP_MAJ*256 + MMAP_MIN*16 + MMAP_PL
  401. X
  402. X#include <sys/types.h>
  403. X#include <sys/file.h>
  404. X#include <sys/param.h>
  405. X#include <sys/dir.h>
  406. X#include <sys/signal.h>
  407. X#include <sys/user.h>
  408. X
  409. X#include <sys/errno.h>
  410. X
  411. X#ifndef SCO
  412. X#include <sys/at_ansi.h>    /* get typedef needed in kd.h    */
  413. X#include <sys/kd.h>        /* get struct kd_memloc        */
  414. X#else
  415. X#include <sys/vtkd.h>
  416. X#endif
  417. X
  418. X#include <sys/sysmacros.h>
  419. X#include <sys/immu.h>
  420. X#include <sys/region.h>
  421. X#include <sys/proc.h>
  422. X
  423. X#include <sys/ipc.h>        /* get typedef needed in shm.h    */
  424. X#include <sys/shm.h>        /* get shminfo            */
  425. X
  426. X#include <sys/mmap.h>
  427. X
  428. X/* For SCO, page locking is done not per-page table entry, but
  429. X * per-pfdat.
  430. X */
  431. X#ifndef PG_LOCK
  432. X#define PG_LOCK 0
  433. X#endif
  434. X
  435. X#define False 0
  436. X#define True  1
  437. X
  438. X/* Move address x to previous and next low boundary address.
  439. X */
  440. X#define prev_ba(x) (caddr_t)((uint)x & ~(MMAPLBA-1))
  441. X#define next_ba(x) (caddr_t)(((uint)x + MMAPLBA) & ~(MMAPLBA-1))
  442. X
  443. X/* Nowhere else declared. */
  444. Xextern dbd_t *finddbd();
  445. X
  446. X/* System's shared memory info structure.
  447. X */
  448. Xextern struct shminfo shminfo;
  449. X
  450. X/* Physical addresses of I/O regions memory mapped by the driver.
  451. X * Defined in space.c.
  452. X */
  453. Xextern mmapreg_t mmapreg[];
  454. X
  455. X/* Size of this array for use by the driver. Defined in space.c.
  456. X */
  457. Xextern uint nmmapreg;
  458. X
  459. Xint mmapinit();
  460. Xint mmapioctl();
  461. X
  462. Xstatic caddr_t FindVirtAddr();
  463. X
  464. X
  465. X/* Number of I/O regions memory mapped currently by the driver. */
  466. Xstatic map_cnt    = 0;
  467. X
  468. Xstatic struct kd_memloc memDesc;
  469. Xstatic mmapinfo_t ibuf;
  470. X
  471. X
  472. Xint mmapinit()
  473. X{
  474. X    printf("Memory Mapped I/O Driver v%d.%d.%d installed.\n",
  475. X       MMAP_MAJ, MMAP_MIN, MMAP_PL);
  476. X    printf("Copyright (c) 1993 Thomas Wolfram\n\n");
  477. X
  478. X}
  479. X
  480. Xint mmapioctl(dev, cmd, arg, mode)
  481. X    int dev;
  482. X    int cmd;
  483. X    int arg;
  484. X    int mode;
  485. X{
  486. X    /* Don't put this much variables at the kernel stack. Although it
  487. X     * wouldn't matter, probably...
  488. X     */
  489. X    static reg_t        *Reg_p;
  490. X    static preg_t       *PReg_p;
  491. X    static pde_t      *pte;        /* page table entry        */
  492. X    static dbd_t      *dbdte;    /* disk block descriptor entry    */
  493. X    static unsigned char   accmode;
  494. X    static int              FreeReg;
  495. X    register uint       i, off;
  496. X    register paddr_t       pmem;
  497. X
  498. X    
  499. X    /* Only superuser is allowed to do that. U.u_error is set to
  500. X     * EPERM if not superuser.
  501. X     */
  502. X    if(!suser())
  503. X    return;
  504. X
  505. X    /* Default for unmapping is don't freeing the region */
  506. X    FreeReg = False;
  507. X
  508. X    switch(cmd) {
  509. X
  510. X    /* Map physical memory into process address space.
  511. X         */
  512. X    case MAP:
  513. X
  514. X        /* Get the memory description block from user space.
  515. X         */
  516. X        if(copyin((caddr_t)arg, &memDesc, sizeof(memDesc)) == -1) {
  517. X        u.u_error = EFAULT;
  518. X        break;
  519. X        }
  520. X
  521. X        /* Physical address must be page aligned.
  522. X         */
  523. X        if(poff(memDesc.physaddr) != 0) {
  524. X        u.u_error = EINVAL;
  525. X        break;
  526. X        }
  527. X
  528. X        /* Check whether we already reached the limit of
  529. X         * attachable shared memory regions of this process.
  530. X         */
  531. X        if(!(u.u_nshmseg < shminfo.shmseg)) {
  532. X        u.u_error = EMFILE;
  533. X        break;
  534. X        }
  535. X
  536. X        /* If no mapping address given by the user try to find one.
  537. X         */
  538. X        if(memDesc.vaddr == (caddr_t)0) {
  539. X        if((memDesc.vaddr = FindVirtAddr(memDesc.length)) == NULL) {
  540. X            u.u_error = ENOMEM;
  541. X            break;
  542. X        }
  543. X        }
  544. X
  545. X        /* Check whether this physical range is already mapped to
  546. X         * a region. If so use it and don't allocate a new region.
  547. X         */
  548. X        Reg_p = NULL;
  549. X        for(i = 0; i < map_cnt; i++) {
  550. X        if((paddr_t)memDesc.physaddr == mmapreg[i].physaddr &&
  551. X               btoc(memDesc.length)  == mmapreg[i].Reg_p->r_pgsz) {
  552. X            Reg_p = mmapreg[i].Reg_p;
  553. X            break;
  554. X        }
  555. X        }
  556. X
  557. X
  558. X        if(Reg_p != NULL) {
  559. X
  560. X        /* If we have still such a region lock it.
  561. X         */
  562. X        reglock(Reg_p);
  563. X
  564. X        /* XXXX This is a ugly hack.
  565. X         * If our region isn't any longer referenced by a process
  566. X         * it's possible that vhand steals the page tables of our
  567. X         * region. Attaching such a region with swapped-out page
  568. X         * tables doesn't work, because the page directory entries
  569. X         * of the process get a present-bit set to 1 and valid re-
  570. X         * ferences to page tables but which contain entries of in-
  571. X         * valid non-present pages. And the related dbd tables still
  572. X         * contain the type DBD_IOMAP.
  573. X         * I.e. the effect is there won't occur a page fault to
  574. X         * read the swapped-out page tables in, as I expected. The
  575. X         * page fault will instead occur in the second level (i.e. in
  576. X         * the page tables) when attempting to read the non-present
  577. X         * pages from disk or elsewhere. The kernel will look in the
  578. X         * dbd table and find the type DBD_IOMAP, but which is invalid
  579. X         * for a non-present page. Hence it would panic then with:
  580. X         * "vfault - bad dbd_type".
  581. X         *
  582. X         * Also I have no idea how I could the swapped-out page tables
  583. X         * read in "by hand". The "pseudo page directory" of the re-
  584. X         * gion (addressed by Reg_p->r_list) contains obviously only
  585. X         * the base addresses and not the page state flags. Also
  586. X         * I don't know how to find the dbd's of the page table's
  587. X         * pages.
  588. X         * 
  589. X         * Probably I did something wrong here. If you've an idea
  590. X         * please let me know. Thanks.
  591. X         *
  592. X         * Anyway, until then I simply throw away the region if
  593. X         * the page tables of it are swapped out and then I reallocate
  594. X         * the same region.
  595. X         */
  596. X        if(Reg_p->r_flags & RG_SWAP) {
  597. X
  598. X            /* Freereg takes only effect if no users pointing
  599. X             * at it.
  600. X             */
  601. X            if(Reg_p->r_refcnt == 0) {
  602. X            Reg_p->r_flags &= ~RG_NOFREE;
  603. X            freereg(Reg_p);
  604. X
  605. X            /* Free the old slot and force allocating a
  606. X             * new region.
  607. X             */
  608. X            for(i = i; i < map_cnt; i++)
  609. X                mmapreg[i] = mmapreg[i+1];
  610. X            map_cnt--;
  611. X
  612. X            Reg_p = NULL;
  613. X
  614. X#ifdef DEBUG
  615. X            printf("MMAP: Info - reallocate region [a=0x%x, l=%dk]\n", memDesc.physaddr, memDesc.length/1024);
  616. X#endif
  617. X            }
  618. X            else {
  619. X            /* I hope this point here will never be reached!
  620. X             * Or - better - page tables are read in correctly
  621. X             * by the system. So we don't panic in the hope
  622. X             * it works.
  623. X             */
  624. X            printf("MMAP: Warning - region [a=%x, l=%dk] still used but page tables are swapped out!\n", memDesc.physaddr, memDesc.length/1024);
  625. X            printf("MMAP: Cannot reallocate this region!\n");
  626. X            printf("MMAP: Please email Thomas Wolfram <thomas@aeon.in-berlin.de> or\n      <wolf@prz.tu-berlin.de>. Thanks.\n");
  627. X
  628. X            /* panic("MMAP: PANIC\n");
  629. X             */
  630. X            }
  631. X        }
  632. X        }
  633. X
  634. X
  635. X        /* If necessary allocate a new region, type is shared memory.
  636. X         */
  637. X        if(Reg_p == NULL) {
  638. X
  639. X        /* Check whether we are at the limit of regions we can map.
  640. X         */
  641. X        if(map_cnt > nmmapreg) {
  642. X            u.u_error = EMFILE;
  643. X            break;
  644. X        }
  645. X
  646. X        /* Allocate new region which will be locked.
  647. X         */
  648. X            if((Reg_p = allocreg(NULL, RT_SHMEM, 0)) == NULL)
  649. X            break;
  650. X        }
  651. X
  652. X
  653. X        /* If the region is already initialized, check whether it is
  654. X         * allowed to grow the virtuell address space of the process by
  655. X         * btoc(memDesc.length) pages, before attaching it.
  656. X         */
  657. X
  658. X        if(Reg_p->r_pgsz > 0) {
  659. X
  660. X            if(chkpgrowth(btoc(memDesc.length)) < 0) {
  661. X            regrele(Reg_p);
  662. X            u.u_error = ENOMEM;
  663. X            break;
  664. X            }
  665. X        }
  666. X
  667. X        /* Attach region to process, R/O or R/W. Will fail if vaddr is
  668. X         * not a multiple of SHMLBA (= MMAPLBA, 4MB on a i386).
  669. X         */
  670. X        if(mode & FWRITE)
  671. X        accmode = SEG_RW;
  672. X        else
  673. X        accmode = SEG_RO;
  674. X
  675. X        if((PReg_p = attachreg(Reg_p, &u, memDesc.vaddr, PT_SHMEM, accmode))
  676. X               == NULL) {
  677. X        
  678. X        /* If attaching failed and region is already initialized,
  679. X         * release it. Otherwise free it again.
  680. X         */
  681. X        if(Reg_p->r_pgsz > 0)
  682. X            regrele(Reg_p);
  683. X        else
  684. X            freereg(Reg_p);
  685. X        break;
  686. X        }
  687. X    
  688. X
  689. X        /* If region is new allocated, grow region without allocating
  690. X         * swapable memory (DBD_NONE prevents decrementing of availsmem
  691. X         * and availrmem), i.e. allocate only page tables and dbd tables.
  692. X         * Then map the physical memory into it.
  693. X         * But check whether it is allowed to grow the virtuell address
  694. X         * space of the process by btoc(memDesc.length) pages before.
  695. X         */
  696. X        if(Reg_p->r_pgsz == 0) {       
  697. X
  698. X            if(chkpgrowth(btoc(memDesc.length)) < 0) {
  699. X            detachreg(PReg_p, &u);
  700. X            u.u_error = ENOMEM;
  701. X            break;
  702. X            }
  703. X
  704. X            if(growreg(PReg_p, btoc(memDesc.length), DBD_NONE) < 0) {
  705. X            detachreg(PReg_p, &u);
  706. X            u.u_error = ENOMEM;
  707. X            break;
  708. X            }
  709. X
  710. X        
  711. X            /* Map physical memory into virtuell address space of process,
  712. X         * i.e. modify page tables and dbd tables.
  713. X             * I could also use mappages() here, but so I don't have the
  714. X             * overhead of it and know what I do.
  715. X             *
  716. X             * Linear address:
  717. X             *          +----------+----------+------------+
  718. X             *          |   ptnum  |  pnum    | byte off.  |
  719. X             *          +----------+----------+------------+
  720. X             *               10        10           12
  721. X             */
  722. X            pmem = (paddr_t)memDesc.physaddr;
  723. X
  724. X            for(off = 0; off < memDesc.length; off += NBPP) {
  725. X
  726. X            pte = (pde_t *)((uint)Reg_p->r_list[ptnum(off)] & PG_ADDR)
  727. X                  + pnum(off);
  728. X            pte->pgi.pg_pde = (pmem & PG_ADDR) |
  729. X                               PG_LOCK | PTE_RW | PG_P;
  730. X        /*
  731. X         * SCO does page locking per-pfdat, not per-page table entry
  732. X         * according to SCO's <sys/immu.h>. Also pg_setlock(),
  733. X         * pg_clrlock(), and pg_islocked() are not macros, but
  734. X         * functions on SCO now. Assumed they changed not the
  735. X         * parameter of the original macro (I don't believe it,
  736. X         * would had a lot more changes in the kernel required...),
  737. X         * following would lock the page in core:
  738. X#ifdef SCO
  739. X            pg_setlock(pte);
  740. X#endif
  741. X         * It's uncommented because it's not tested yet.
  742. X         */
  743. X
  744. X            dbdte         = finddbd(Reg_p, pte);
  745. X            dbdte->dbd_type = DBD_IOMAP;
  746. X
  747. X            /* Move to next physical page. */
  748. X            pmem += NBPP;
  749. X            }
  750. X
  751. X            /* Region is initialized. Don't free region on last detach.
  752. X             */
  753. X            Reg_p->r_flags   |= RG_DONE | RG_NOFREE;
  754. X        Reg_p->r_dbdnone =  0;
  755. X
  756. X        mmapreg[map_cnt].physaddr = (paddr_t)memDesc.physaddr;
  757. X        mmapreg[map_cnt++].Reg_p  = Reg_p;
  758. X
  759. X        } /* Region size still zero */
  760. X
  761. X        /* Increase number of attached shared memory regions.
  762. X         */
  763. X        u.u_nshmseg++;
  764. X
  765. X         /* Only count up this to prevent swapping. Maybe it's not
  766. X         * necessary.
  767. X         */
  768. X            Reg_p->r_noswapcnt++;  
  769. X
  770. X        /* Release region and return.
  771. X         */
  772. X        regrele(Reg_p);
  773. X        u.u_rval1 = (int)memDesc.vaddr;
  774. X        break;
  775. X
  776. X
  777. X    /* Unmap region from physical address space and try to free
  778. X     * it.
  779. X         */
  780. X    case UNMAPRM:
  781. X         FreeReg = True;
  782. X
  783. X    /* Unmap region from physical address space.
  784. X     */
  785. X    case UNMAP:
  786. X
  787. X        /* Check whether the given vaddr is a valid virtuell address
  788. X         * of a shared memory region of this process, i.e. look for it
  789. X         * in the process table of pregions.
  790. X         */
  791. X        PReg_p = u.u_procp->p_region;
  792. X
  793. X        while(PReg_p->p_reg != NULL) {
  794. X
  795. X        if(PReg_p->p_type == PT_SHMEM  &&
  796. X                 PReg_p->p_regva == (caddr_t)arg)
  797. X             break;
  798. X        PReg_p++;
  799. X        }
  800. X
  801. X        if(PReg_p->p_reg == NULL) {
  802. X        u.u_error = EINVAL;
  803. X        break;
  804. X        }
  805. X
  806. X        /* Check whether the this is really one of our I/O regions,
  807. X         * i.e. region must be known to us.
  808. X         */
  809. X
  810. X        for(i = 0; i < map_cnt; i++) {
  811. X        if(PReg_p->p_reg == mmapreg[i].Reg_p)
  812. X             break;
  813. X        }
  814. X        if(i == map_cnt) {
  815. X        u.u_error = EINVAL;
  816. X        break;
  817. X        }
  818. X
  819. X        Reg_p = PReg_p->p_reg;
  820. X        reglock(Reg_p);
  821. X        detachreg(PReg_p, &u);
  822. X        u.u_nshmseg--;
  823. X
  824. X        /* If FREEREG is requested and no other user is pointing
  825. X         * at the region free it and remove it from the internal
  826. X         * list.
  827. X         */
  828. X        if(FreeReg && (Reg_p->r_refcnt == 0)) {
  829. X            reglock(Reg_p);
  830. X        Reg_p->r_flags  &= ~RG_NOFREE;
  831. X        freereg(Reg_p);
  832. X        for(i = i; i < map_cnt; i++)
  833. X            mmapreg[i] = mmapreg[i+1];
  834. X        map_cnt--;
  835. X        }
  836. X        break;
  837. X
  838. X
  839. X    /* Return number of currently memory mapped I/O regions.
  840. X     */
  841. X    case GETNMMREG:
  842. X        u.u_rval1 = map_cnt;
  843. X        break;
  844. X
  845. X    /* Return information block about currently memory mapped I/O
  846. X     * regions.
  847. X     */
  848. X    case GETMMREG:
  849. X
  850. X        for(i = 0; i < map_cnt; i++) {
  851. X        ibuf.physaddr = mmapreg[i].physaddr;
  852. X        ibuf.length   = ctob(mmapreg[i].Reg_p->r_pgsz);
  853. X        ibuf.refcnt   = mmapreg[i].Reg_p->r_refcnt;
  854. X        if(copyout(&ibuf, arg, sizeof(ibuf)) == -1) {
  855. X             u.u_error = EFAULT;
  856. X             return;
  857. X        }
  858. X        arg += sizeof(ibuf);
  859. X        }
  860. X        break;
  861. X
  862. X
  863. X    /* Return version number
  864. X     */
  865. X    case GETVERSION:
  866. X        u.u_rval1 = MMAPVERSION;
  867. X        break;
  868. X
  869. X
  870. X    default:
  871. X        u.u_error = EINVAL;
  872. X        break;
  873. X
  874. X    }
  875. X}
  876. X
  877. X
  878. X/* Find a virtual mapping address.
  879. X */
  880. Xstatic caddr_t FindVirtAddr(size)
  881. X    uint size;
  882. X{
  883. X    register caddr_t   vregaddr;
  884. X    register caddr_t   vmapaddr        = (caddr_t)UVMMAP;
  885. X    register preg_t   *preg_p       = u.u_procp->p_region;
  886. X
  887. X    /* Go through the process regions table...
  888. X     */
  889. X    while(preg_p->p_reg != NULL) {
  890. X
  891. X#ifdef DEBUG        
  892. X        printf("MMAP: Try vmapaddr %x\n", vmapaddr);
  893. X#endif
  894. X    /* If region grows down, use previous MMAPLBA boundary address as
  895. X     * starting address. Round up the 0x????3fffc aligned (ending) address
  896. X     * before.
  897. X     */
  898. X    if((preg_p->p_reg)->r_flags & RG_DOWN)
  899. X        vregaddr = prev_ba(next_ba(preg_p->p_regva) -
  900. X                ctob((preg_p->p_reg)->r_pgsz));
  901. X    else
  902. X        vregaddr = preg_p->p_regva;
  903. X#ifdef DEBUG
  904. X        printf("MMAP: vregaddr = %x\n", vregaddr);
  905. X#endif
  906. X
  907. X    /* Search for process region with address above the desired 
  908. X     * mapping address.
  909. X     */
  910. X        if(vmapaddr > vregaddr) {
  911. X        preg_p++;
  912. X        continue;
  913. X        }
  914. X
  915. X    /* If address is already in use try next address at MMAPLBA boundary
  916. X     * after end of this region.
  917. X     */
  918. X    if(vmapaddr == vregaddr) {
  919. X        vmapaddr = next_ba(vregaddr + ctob((preg_p->p_reg)->r_pgsz));
  920. X        preg_p++;
  921. X        continue;
  922. X    }
  923. X
  924. X    /* If desired start and end addresses are below this region
  925. X     * use this address for mapping, otherwise try next address at
  926. X     * MMAPLBA boundary after end of this region.
  927. X     */
  928. X    if((vmapaddr + size - 1) < vregaddr) {
  929. X#ifdef DEBUG
  930. X        printf("MMAP: Take %x\n", vmapaddr);
  931. X#endif
  932. X        return vmapaddr;
  933. X    }
  934. X    vmapaddr = next_ba(vregaddr + ctob((preg_p->p_reg)->r_pgsz));
  935. X    preg_p++;
  936. X    }    
  937. X
  938. X    /* If no hole between process regions found, but current vmapaddr
  939. X     * (end address) is still below the maximal possible user virtual
  940. X     * address, then use it.
  941. X     */
  942. X    if((vmapaddr + size - 1) < (caddr_t)MAXUVADR)
  943. X    return vmapaddr;
  944. X    
  945. X    /* Found no hole... */
  946. X    return NULL;
  947. X}
  948. X
  949. END_OF_FILE
  950. if test 15554 -ne `wc -c <'mmap-2.2.3/mmap.c'`; then
  951.     echo shar: \"'mmap-2.2.3/mmap.c'\" unpacked with wrong size!
  952. fi
  953. # end of 'mmap-2.2.3/mmap.c'
  954. fi
  955. if test -f 'mmap-2.2.3/mmap.man' -a "${1}" != "-c" ; then 
  956.   echo shar: Will not clobber existing file \"'mmap-2.2.3/mmap.man'\"
  957. else
  958. echo shar: Extracting \"'mmap-2.2.3/mmap.man'\" \(7901 characters\)
  959. sed "s/^X//" >'mmap-2.2.3/mmap.man' <<'END_OF_FILE'
  960. X.\" Copyright (c) 1993 by Thomas Wolfram
  961. X.TH mmap 7L "2.2.3, 22 November 1993" "Version 2.2.3"
  962. X.de BP
  963. X.sp
  964. X.ti -.2i
  965. X\(**
  966. X..
  967. X.SH NAME
  968. Xmmap \- \fBMMAP\fP ioctl commands (memory mapped I/O support)
  969. X.SH SYNOPSIS
  970. X.br
  971. X#include <sys/types.h>
  972. X.br
  973. X#ifndef SCO
  974. X.br
  975. X#include <sys/at_ansi.h>
  976. X.br
  977. X#include <sys/kd.h>
  978. X.br
  979. X#else
  980. X.br
  981. X#include <sys/vtkd.h>
  982. X.br
  983. X#endif
  984. X.br
  985. X#include <sys/sysmacros.h>
  986. X.br
  987. X#include <sys/immu.h>
  988. X.br
  989. X#include <sys/region.h>
  990. X.br
  991. X#include <sys/mmap.h>
  992. X.P
  993. Xint ioctl(fildes, command, arg);
  994. X.br
  995. Xint fildes, command;
  996. X.SH DESCRIPTION
  997. X.I MMAP
  998. Xis a pseudo device driver which provides memory mapped I/O for user processes,
  999. Xi.e. direct mapping of physical memory ranges into the user's virtual address
  1000. Xspace for fast access. It is especially useful for accessing the linear frame
  1001. Xbuffers of certain graphic hardware from the user level.
  1002. X.P
  1003. XTo execute the \fIMMAP ioctl\fR commands \fIfildes\fR must be an open file
  1004. Xdescriptor [see \fIopen(2)\fR] that refers to the special character device
  1005. X\fI/dev/mmap\fR. The effective user ID of the calling process must be
  1006. Xsuperuser.
  1007. X.br
  1008. XThe driver uses shared memory type regions for mapping. So the maximum
  1009. Xnumber of regions the driver can attach to a process is limited by
  1010. Xthe maximum number of shared memory regions which can be attached to
  1011. Xthe process [see \fIshmget(2), shmop(2), shmctl(2)\fR]. This number
  1012. Xis a tunable system parameter (\fISHMSEG\fR) [see \fIkconfig(1),
  1013. Xidtune(1M)\fR].
  1014. X.br
  1015. XThe number of regions which the driver is able to map system-wide (i.e. to
  1016. Xall running processes) is limited too. This number is also a tunable
  1017. Xsystem parameter (\fINMMAPREG\fR).
  1018. X.P
  1019. XNote, the \fIMMAP\fR driver grows the virtual address space of the calling
  1020. Xprocess by itself. Allocating address space before with \fImalloc(3)\fR
  1021. Xisn't necessary and will not work.
  1022. X.br
  1023. XThe mapping regions allocated by the driver will always be sharable, never
  1024. Xprivate to a process. Regions can be of type read/write or read/only.
  1025. XThis depends from the \fImode\fR \fI/dev/mmap\fR is opened [see \fIopen(2)\fR].
  1026. XOnce a region is allocated and mapped to a process it will normally remain
  1027. Xin the system (until reboot) even if the last process which pointed at it
  1028. Xdetaches it from its address space. (This is not much waste since
  1029. Xthe \fIMMAP\fR driver allocates no physical pages for the mapping region.)
  1030. XBut with the \fIUNMAPRM\fR ioctl removing after unmapping can be
  1031. Xrequested [see below and \fImmaprm(1L)\fR].
  1032. XIf a process wants to map in the same memory range like another one (e.g. if
  1033. Xit's the same program which is running again) it will be attached with the
  1034. Xalready existing region by the driver. Same applies if the processes which
  1035. Xrequests the same mapping are running simultaneously.
  1036. X.SS Ioctl Calls
  1037. XThe following ioctl commands can be used:
  1038. X.IP \fBMAP\fP 2
  1039. XThis call maps physical memory into the virtual address space of the
  1040. Xuser process. The following structure, defined in <sys/kd.h> [see
  1041. X\fIdisplay(7)\fR], is pointed to by the argument \fIarg\fR to the ioctl:
  1042. X.IP
  1043. Xstruct kd_memloc {
  1044. X.br
  1045. X    char  *vaddr;     /* virtual address to map to */
  1046. X.br
  1047. X    char  *physaddr;  /* physical address to map from */
  1048. X.br
  1049. X    long  length;     /* size in bytes to map */
  1050. X.br
  1051. X    long  ioflg;      /* not used by the \fIMMAP\fR driver */
  1052. X.br
  1053. X};
  1054. X.IP "" 2
  1055. XThe \fIvaddr\fR argument is the linear address in the process where the
  1056. Xphysical memory range will appear. This address must be on a boundary
  1057. Xspecified by the machine dependant constant \fIMMAPLBA\fR, defined in
  1058. X<sys/mmap.h>. If \fIvaddr\fR is equal to zero the address is selected by
  1059. Xthe driver itself.
  1060. X.br
  1061. XThe \fIphysaddr\fR argument is the physical address of the memory range
  1062. Xthat will be mapped in. It must be on a page boundary.
  1063. X.br
  1064. XThe \fIlength\fR argument is the size of the memory range that will be
  1065. Xmapped in. It will be rounded up to a multiple of the size of a page
  1066. Xby the driver.
  1067. X.br
  1068. XOn success the ioctl will return the virtual address where the memory
  1069. Xis mapped in. It will fail if one or more of the following is true:
  1070. X.RS 4
  1071. X.IP [EPERM] 15
  1072. XThe effective user ID of the calling process is not superuser.
  1073. X.IP [EFAULT] 15
  1074. XThe user address pointed to by \fIarg\fR is illegal.
  1075. X.IP [EINVAL] 15
  1076. XThe \fIvaddr\fR argument is not equal to zero, and the value is an illegal
  1077. Xaddress (not on a MMAPLBA boundary, already used in the process or not
  1078. Xbelow \fIMAXUVADR\fR, as defined in <sys/immu.h>).
  1079. X.IP [EINVAL] 15
  1080. XThe \fIphysaddr\fR argument is not on a page boundary.
  1081. X.IP [ENOMEM] 15
  1082. XThe \fIvaddr\fR argument is equal to zero and the driver is not able
  1083. Xto find a proper region in the user's address space where the memory
  1084. Xrange would fit in.
  1085. X.IP [ENOMEM] 15
  1086. XThe size of the user's virtual address space would exceed the system-imposed
  1087. Xlimit.
  1088. X.IP [ENOMEM] 15
  1089. XNot enough system internal space available to grow the user's virtual
  1090. Xaddress space.
  1091. X.IP [EMFILE] 15
  1092. XThe number of shared memory segments attached to the calling process would
  1093. Xexceed the system-imposed limit.
  1094. X.IP [EMFILE] 15
  1095. XThe number of all memory mapped regions in the system would exceed the
  1096. Xdriver-imposed limit.
  1097. X.RE 1
  1098. X.IP \fBUNMAP\fP 2
  1099. XThis call unmaps previously mapped physical memory from the calling process.
  1100. XThe argument \fIarg\fR to the ioctl must be the virtual address as
  1101. Xreturned by the previous \fIMAP\fR ioctl.
  1102. X.br
  1103. XIt will fail if one or more of the following is true:
  1104. X.RS 4
  1105. X.IP [EPERM] 15
  1106. XThe effective user ID of the calling process is not superuser.
  1107. X.IP [EINVAL] 15
  1108. XIf \fIarg\fR is not the start address of a region mapped by the driver to
  1109. Xthe calling process.
  1110. X.RE 1
  1111. X.IP \fBUNMAPRM\fP 2
  1112. XSame like \fIUNMAP\fR but removes the concerning region from the systems
  1113. Xinternal list, if no other process is still using it [see \fImmaprm(1L)\fR].
  1114. X.IP \fBGETNMMREG\fP 2
  1115. XThis call returns the number of the memory mapped I/O regions which
  1116. Xexists currently in the system [\fIsee mmapstat(1L)\fR]. It requires no
  1117. Xargument. It will fail if one or more of the following is true:
  1118. X.RS 4
  1119. X.IP [EPERM] 15
  1120. XThe effective user ID of the calling process is not superuser.
  1121. X.RE 1
  1122. X.IP \fBGETMMREG\fP 2
  1123. XThis call returns the current status of the \fIMMAP\fR driver. The
  1124. Xargument \fIarg\fR must be a pointer to an array of elements of
  1125. Xthe following type (defined in <sys/mmap.h>):
  1126. X.IP
  1127. Xtypedef struct mmapinfo {
  1128. X.br
  1129. X    paddr_t physaddr; /* physical address */
  1130. X.br
  1131. X    long  length;     /* size in bytes */
  1132. X.br
  1133. X    short refcnt;     /* number of users */
  1134. X.br
  1135. X    /* pointing currently at this region */
  1136. X.br
  1137. X} mmapinfo_t;
  1138. X.IP "" 2
  1139. Xwhich is filled by the driver for every region currently exists.
  1140. XThe array must have as much elements as the number returned by the
  1141. X\fIGETNMMREG\fR ioctl states [see \fImmapstat(1L)\fR].
  1142. XThe command will fail if one or more of the following is true:
  1143. X.RS 4
  1144. X.IP [EPERM] 15
  1145. XThe effective user ID of the calling process is not superuser.
  1146. X.IP [EFAULT] 15
  1147. XThe user address pointed to by \fIarg\fR is illegal.
  1148. X.IP "" 2
  1149. X.RE 1
  1150. X.IP \fBGETVERSION\fP 2
  1151. XReturns version number of driver, e.g. version 2.2.1 would be returned
  1152. Xas 0x0221.
  1153. X.SH FILES
  1154. X.IP \fI/dev/mmap\fR 2
  1155. XCharacter device interface to the driver.
  1156. X.SH "SEE ALSO"
  1157. Xopen(2), ioctl(2), display(7), shmget(2), shmop(2), shmctl(2), kconfig(1),
  1158. Xidtune(1M), intro(2), mmapstat(1L), mmaprm(1L).
  1159. X.SH DIAGNOSTICS
  1160. XUpon sucessful completion, the return value is as follows:
  1161. X.RS 5
  1162. X.P
  1163. XThe \fIMAP\fR ioctl returns the user's address where the physical memory
  1164. Xis mapped in.
  1165. X.P
  1166. XThe \fIUNMAP\fR and \fIUNMAPRM\fR ioctl's return a value of 0. 
  1167. X.P
  1168. XThe \fIGETNMMREG\fR ioctl returns the number of memory mapped I/O regions
  1169. Xwhich exists currently in the system.
  1170. X.P
  1171. XThe \fIGETMMREG\fR ioctl returns a value of 0. 
  1172. X.P
  1173. XThe \fIGETVERSION\fR ioctl returns the version number. 
  1174. X.RE 1
  1175. X.P
  1176. XOtherwise, a value of -1 is returned, and \fIerrno\fR [see \fIintro(2)\fR]
  1177. Xis set to indicate the error.
  1178. X.SH BUGS
  1179. XPlease report bugs to:
  1180. X.B wolf@prz.tu-berlin.de
  1181. Xor
  1182. X.BR thomas@aeon.in-berlin.de .
  1183. X.SH COPYING
  1184. XCopyright (c) 1993 Thomas Wolfram
  1185. X.SH AUTHOR
  1186. XThomas Wolfram
  1187. END_OF_FILE
  1188. if test 7901 -ne `wc -c <'mmap-2.2.3/mmap.man'`; then
  1189.     echo shar: \"'mmap-2.2.3/mmap.man'\" unpacked with wrong size!
  1190. fi
  1191. # end of 'mmap-2.2.3/mmap.man'
  1192. fi
  1193. echo shar: End of archive 2 \(of 2\).
  1194. cp /dev/null ark2isdone
  1195. MISSING=""
  1196. for I in 1 2 ; do
  1197.     if test ! -f ark${I}isdone ; then
  1198.     MISSING="${MISSING} ${I}"
  1199.     fi
  1200. done
  1201. if test "${MISSING}" = "" ; then
  1202.     echo You have unpacked both archives.
  1203.     echo "Sources of the mmap driver v2.2.3 unpacked."
  1204.     rm -f ark[1-9]isdone
  1205. else
  1206.     echo You still need to unpack the following archives:
  1207.     echo "        " ${MISSING}
  1208. fi
  1209. ##  End of shell archive.
  1210. exit 0
  1211.