home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v1.zip / DDKX86 / BOOK / SMBOOK.INF (.txt) < prev    next >
OS/2 Help File  |  1994-04-19  |  563KB  |  19,324 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Preface ΓòÉΓòÉΓòÉ
  3.  
  4.                       Writing OS/2 2.1 Device Drivers in C
  5.                                  Second Edition
  6.                               Steven J. Mastrianni
  7.  
  8. DISCLAIMER 
  9.  
  10. This book and software are provided 'as is'.  The implied warranties of 
  11. merchantability and fitness for a particular purpose are expressly disclaimed. 
  12. This book and software may contain programs that are furnished as examples. 
  13. These examples have not been thoroughly tested under all conditions. 
  14. Therefore, the reliability, serviceability, or function of any program or 
  15. program code herein is not guaranteed. 
  16.  
  17. The information presented in this book was valid at the time it was written and 
  18. was conveyed as accurately as possible by the author. However, some information 
  19. may be incorrect or may have changed prior to publication. The author makes no 
  20. claims that the material contained in this book is entirely correct, and 
  21. assumes no liability for use of the material contained herein. 
  22.  
  23. TRADEMARKS AND COPYRIGHTS 
  24.  
  25. IBM, AT, OS/2, Personal System/2, PS/2, and Micro Channel are registered 
  26. trademarks of the International Business Machines Corporation. 
  27.  
  28. C/2, XT, and Presentation Manager are trademarks of International Business 
  29. Machines Corporation. 
  30.  
  31. Intel is a registered trademark of the Intel Corporation. 
  32.  
  33. Lotus 1-2-3 is a registered trademark of Lotus Development Corporation. 
  34.  
  35. MS-DOS, CodeView and Microsoft are registered trademarks of Microsoft 
  36. Corporation. 
  37.  
  38. Microsoft and Microsoft Windows are registered trademarks of Microsoft 
  39. Corporation. 
  40.  
  41. UNIX is a registered trademark of AT&T Bell Laboratories. 
  42.  
  43. Copyright  1993 by Van Nostrand Reinhold 
  44.  
  45. Library of Congress Catalog Card Number 93-2264 ISBN 0-442-01729-4 
  46.  
  47. All rights reserved. No part of this work covered by the copyright hereon may 
  48. be reproduced or used in any form or by any means-graphic, electronic, or 
  49. mechanical, including photocopying, recording, taping, or information storage 
  50. and retrieval systems-without written permission of the publisher. 
  51.  
  52. Van Nostrand Reinhold is an International Thomson Publishing company. ITP logo 
  53. is a trademark under license. 
  54.  
  55. Printed in the United States of America 
  56.  
  57. Van Nostrand Reinhold               International Thomson Publishing GmbH
  58. 115 Fifth Avenue                    Kunigswinteror Str. 518
  59. New York, NY 10003                  5300 Bonn 3
  60.                                     Germany
  61.  
  62.  
  63. International Thomson Publishing    International Thomson Publishing Asia
  64. Berkshire House, 168-173            38 Kim Tian Road, #0105
  65. High Holborn, London WC1V 7AA       Kim Tian Plaza
  66. England                             Singapore 0316
  67.  
  68.  
  69. Thomas Nelson Australia             International Thomson Publishing Japan
  70. 102 Dodds Street                    Kyowa Building, 3F
  71. South Melbourne 3205                2-2-1 Hirakawacho
  72. Victoria, Australia                 Chiyada-Ku, Tokyo 102
  73.                                     Japan
  74.  
  75. Nelson Canada
  76. 1120 Birchmount Road
  77. Scarborough, Ontario
  78. M1K 5G4, Canada
  79.  
  80. 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
  81.  
  82.  
  83. Library of Congress Cataloging-in-Publication Data
  84.  
  85. Mastrianni, Steven J., 1951-
  86.  Writing OS/2 2.1 Device Drivers in C / Steven J. Mastrianni. - 2nd ed.
  87.  p.  cm. -- (VNR's OS/2 series)
  88.  ISBN 0-442-01229-4
  89.  1. OS/2 device drivers (Computer programs)  2. OS/2 (Computer file)  3.
  90.  C (Computer program language)   I. Title.  II.  Series. QA76.76.D49M37 1993
  91.   005.4'3--dc20                              93-2264 CIP
  92.  
  93. Project Management: Ray Campbell Art Director: Jo-Ann Radin-Campbell
  94. Production: mle design, Milford, CT 06460
  95.  
  96. DEDICATION 
  97.  
  98. This book is dedicated to my sons Steve and Jeffrey, my daughter Laura, and my 
  99. wife Debra, who put up with my absence while this book was being prepared. 
  100.  
  101. ACKNOWLEDGMENTS 
  102.  
  103. I would like to thank Dennis Rowe, Stacey Barnes, Mark Fiechtner, Frank 
  104. Schroeder, Dick Conklin, Carol Bray, and John Soyring of the IBM Corporation 
  105. for helping to make this book possible. I'd also like to thank Allen Wynn of 
  106. IBM for supplying the information on the IBM OEMHLP device driver. 
  107.  
  108. I would like to thank Marcello Lopez, Michael Kupka, Michael Glieneke, and 
  109. Rhonda Morrison for their contributions to this book. 
  110.  
  111. A special thanks to Dwight Vandenberghe of PentaSoft, Inc., Seattle, 
  112. Washington, for providing me with the training and inspiration to write my 
  113. first OS/2 device driver. 
  114.  
  115. VNR's OS/2 Series 
  116.  
  117. o O/S 2 Presentation Manager GPI Graphics by Graham C.E. Winn 
  118.  
  119. o Writing OS/2 2.0 Device Drivers In C by Steven Mastrianni 
  120.  
  121. o Now That I Have OS/2 2.0 On My Computer - What Do I Do Next? by Steven 
  122.   Levenson 
  123.  
  124. o The OS/2 2.0 Handbook by William H. Zack 
  125.  
  126. o The Cobol Presentation Manager Programming Guide by David M. Dill 
  127.  
  128. o Learning To Program OS/2 2.0 Presentation Manager By Example: Putting the 
  129.   Pieces Together by Stephen A. Knight 
  130.  
  131. o Comprehensive Database Performance For OS/2 2.0's Extended Services by Bruce 
  132.   Tate, Tim Malkemus, and Terry Gray 
  133.  
  134. o Client/Server Programming With OS/2 2.0 by Robert Orfali and Daniel Harkey 
  135.  
  136. o OS/2 2.X Notebook:  Best of IBM OS/2 Developer edited by Dick Conklin, Editor 
  137.  
  138. o The Shell Collection: OS/2 2.X Utilities by Steven Levenson 
  139.  
  140. o Using Workplace OS/2: The Power User's Guide to IBM's OS/2 Version 2.1 by 
  141.   Lori Brown and Jeff Howard 
  142.  
  143. o Writing OS/2 2.1 Device Drivers in C, 2nd Edition by Steven Mastrianni 
  144.  
  145. o The OS/2 2.1 Corporate Programmer's Handbook by Nora Scholin, Mark Sullivan, 
  146.   and Robin Scragg 
  147.  
  148. o OS/2 2.1 REXX HANDBOOK:  Basics, Applications and Tips by Hallett German 
  149.  
  150.  
  151. ΓòÉΓòÉΓòÉ 1.1. Tables ΓòÉΓòÉΓòÉ
  152.  
  153. Tables 
  154.  
  155. Table 4-1. OS/2 Priority Structure
  156. Table 5-1. Device Attribute Word
  157. Table 5-2. Capabilities Bit Strip
  158. Table 5-3. Device Driver Strategy Calls
  159. Table 6-1  Device Driver Strategy Commands
  160. Table 6-2. API Routines Available During Init
  161. Table 6-3. Media Descriptor Byte
  162. Table 6-4. Boot Sector Format
  163. Table 9-1. DOS Settings
  164. Table 9-2. DOS Settings Information
  165. Table 9-3. Virtualized 8250/16450 Registers
  166. Table 9-4. Virtualized Timer Registers
  167. Table 9-5. Supported Virtualized Timer Registers
  168. Table 9-6. Virtualized INT 13 Functions
  169. Table 9-7. Virtualized Floppy Disk Ports
  170. Table 9-8. Virtualized DOS Interrupts
  171. Table 9-9. Virtualized BIOS Interrupts
  172. Table 9-10. Virtualized DOS Software Interrupts
  173. Table 11-1. DMA Channel Assignments
  174. Table 11-2. DMA Controller Port Assignments
  175. Table 11-3A. DMA Channel Addressing for Channels 0-3
  176. Table 11-3B. DMA Channel Addressing for Channels 5-7
  177. Table 11-4. DMA Mask Register
  178. Table 11-5. DMA Mode Register
  179. Table 11-6. DMA Command Register
  180. Table 12-1. Capabilities Bits
  181. Table 12-2. Volume Descriptor Word
  182. Table 12-3. LstRequestControl Word Bits
  183. Table 12-4. LstStatus Byte, Lower Nibble
  184. Table 12-5. LstStatus Byte, Upper Nibble
  185. Table 12-6. RequestCtl Byte
  186. Table 12-7. Request Priority
  187. Table 12-8. Request Status, Lower Nibble (Completion Status)
  188. Table 12-9. Request Status, Upper Nibble (Error Status)
  189. Table 12-10. Request Unrecoverable Error Codes
  190. Table 12-11. Request Recoverable Error Codes
  191. Table 12-12. Request Control Functions
  192. Table 13-1. KDB Keywords
  193. Table 13-2. KDB Binary Operators
  194. Table 13-3. KDB Unary Operators
  195. Table 13-4. KDB Parameter Definitions
  196. Table 13-5. Page Bit Definitions (bit set/clear)
  197. Table 13-6. KDB Register Definitions
  198. Table 13-7. KDB Flag Register Definitions
  199. Table 13-8. KDB Machine Status Word
  200. Table 13-9. KDB Recognized Structures
  201. Table 14-1. Presentation driver flag bits
  202. Table 14-2. Device Context Types
  203. Table 14-3. Data Types for Queued Date
  204. Table 14-4. Graphics Engine Exports
  205. Table 14-5. Presentation Driver Errors
  206. Table 14-6. Presentation Driver Error Codes
  207. Table 14-7. Job Error Returns
  208. Table 16-1. OS/2 PCMCIA Card Services
  209. Table 16-2. Card Services Register Interface (input)
  210. Table 16-3. Card Services Register Interface (output)
  211. Table 16-4. OS/2 2.2 Callbacks
  212. Table 16-5. Callback Register Interface (input)
  213. Table 16-6. Callback Register Interface (output)
  214. Table A-1. Device Helper Functions
  215. Table A-2. Device Helper Contexts
  216. Table A-4. Read Only System Variables
  217. Table A-5. Device Driver Events
  218. Table D-1. OEMHLP$ Supported IOCtl Calls
  219. Table D-2. Video Chip Set Information
  220. Table D-3. TESTCFG IOCtls, Category 0x80
  221.  
  222.  
  223. ΓòÉΓòÉΓòÉ 1.2. Figures and Examples. ΓòÉΓòÉΓòÉ
  224.  
  225. Figures and Examples 
  226.  
  227. Figure 1-1. Role of the BIOS.
  228. Figure 2-1. Polled printer output.
  229. Figure 2-2. Interrupt printer output.
  230. Figure 2-3. The role of the device driver.
  231. Figure 3-1. Real mode address calculation.
  232. Figure 3-2. 80286 protect mode addressing.
  233. Figure 3-3. 80386-486 flat mode addressing.
  234. Figure 3-4. The 80x86 ring architecture.
  235. Figure 4-1. Process and threads.
  236. Figure 5-1. Application-to-device driver interface.
  237. Example 5-1. Request Packet header.
  238. Example 5-2. OS/2 device driver header.
  239. Example 5-3. Device driver header, multiple devices.
  240. Example 5-4. Start-up routine, one device.
  241. Example 5-5. Start-up routine, four devices.
  242. Example 5-6. Start-up routine with timer and interrupt handler.
  243. Example 5-7. Skeleton strategy section.
  244. Example 5-8. Interrupt handler.
  245. Example 5-9. Timer handler.
  246. Example 5-10. TickCount timer handler.
  247. Example 6-1. Request Packet definition.
  248. Example 6-2. Standard OS/2 device driver errors.
  249. Example 6-3. MachineConfigurationInfo structure.
  250. Example 7-1. Application call to open the driver.
  251. Example 7-2. INIT section.
  252. Example 7-3. OPEN section.
  253. Example 7-4. CLOSE section.
  254. Example 7-5. IOCtl 0x01, write port.
  255. Example 7-6. IOCtl 0x02.
  256. Example 7-7. IOCtl 0x03.
  257. Example 7-8. READ and WRITE section.
  258. Example 7-9. Timer handler.
  259. Example 8-1. ISA and Micro Channel INIT section.
  260. Figure 8-1. Micro Channel vs. ISA bus interrupt handler.
  261. Example 9-1. VDD initialization section.
  262. Example 9-2. VDD data segment.
  263. Example 9-3. VDD input handler.
  264. Example 9-4. VDD data port output handler.
  265. Example 9-5. VDD user routines.
  266. Example 9-6. VDD include file.
  267. Example 9-7. VDD Make And DEF Files.
  268. Example 9-8. Registering PDD for VDD-PDD communications.
  269. Example 9-9. VDD-PDD communications structure.
  270. Example 10-1. PhysToVirt call.
  271. Example 10-2. Mapping a GDT selector during INIT.
  272. Example 10-3. IOPL Segment.
  273. Example 10-4. IOPL DEF file.
  274. Example 11-1. DMA setup routine.
  275. Example 12-1. Driver Capabilities structure.
  276. Example 12-2. Volume Characteristics Structure.
  277. Example 12-3. Request List Header structure.
  278. Example 12-4. Request Header structure.
  279. Example 12-5. Scatter Gather Descriptor structure.
  280. Example 12-6. Read/Write Request structure.
  281. Example 12-7. Read Prefetch Request structure.
  282. Example 12-8. SetFSDInfo structure.
  283. Example 15-1. VMGlobalToProcess and VMProcessToGlobal
  284. Example 15-2. Using VMAlloc
  285. Example 15-3. Calling VMLock
  286. Example 16-1. PCMCIA software architecture.
  287. Example 16-2. ClientData structure.
  288. Example A-1. ADD Device Class Table.
  289. Example A-2. Retreiving an ADD's entry point using GetDOSVar.
  290. Example D-1. Locating An EISA Bus Adapter Using OEMHLP.
  291.  
  292.  
  293. ΓòÉΓòÉΓòÉ 2. Foreword ΓòÉΓòÉΓòÉ
  294.  
  295. FOREWORD 
  296.  
  297. Building upon the success of OS/2 Version 2.0 with well over 2 million copies 
  298. shipped, IBM has now released an exciting new upgrade of this increasingly 
  299. popular PC operating system. OS/2 Version 2.1 includes many new functional 
  300. enhancements such as 32-bit graphics processing, integrated multimedia support, 
  301. the ability to run applications originally designed for Windows 3.1 and much 
  302. more. 
  303.  
  304. OS/2 2.1 not only has superior abilities for running DOS applications, Windows 
  305. applications and new 32-bit OS/2 applications, but it allows users to exploit 
  306. the untapped power of their 32-bit PC's and advanced I/O devices. However, the 
  307. PC hardware industry is not standing still. In addition to the introduction of 
  308. the Pentium processor, the PC industry has seen an explosive growth in faster, 
  309. more intelligent peripheral devices, including Fax/Modems, CD-ROM's, high 
  310. resolution printers and display devices, mass storage, and new technology such 
  311. as PCMCIA. Support for these new devices requires device drivers. In the case 
  312. of high resolution video devices, several drivers may be required. Keep ing up 
  313. with the demand of users for state-of-the-art support of these devices can be a 
  314. daunting task. 
  315.  
  316. Writing OS/2 2.1 Device Drivers in C is the second edition of the very popular 
  317. Writing OS/2 2.0 Device Drivers in C, which has sold more than 15,000 copies in 
  318. over 30 countries. I think you will find this second edition even more helpful 
  319. and informative than the first. More sample source code has been added, and all 
  320. of the source code for the examples in the book is included on a disk attached 
  321. to the back cover. Several more chapters were added with even more information 
  322. covering device driver development - including a question-and- answer section 
  323. covering commonly asked driver development questions. 
  324.  
  325. Steve's writing style is clear and concise. He tells you what you need to know 
  326. - without extraneous information, excessive use of buzz words, and acronyms. 
  327. Developers of device drivers who read Steve's first edition have consistently 
  328. told me they found his book to be a valuable addition to their libraries. I 
  329. think you will find this second edition even more worthwhile. 
  330.  
  331. OS/2 2.1 is going to make a difference in the way PC's are used. It will both 
  332. preserve user's current 16-bit investments, and enable them to exploit 32-bit 
  333. hardware and I/O devices. Authors like Steve help provide the technical support 
  334. you will need to join this new PC revolution and move into the 21st century of 
  335. computing. 
  336.  
  337. John Soyring
  338. Director of Software Development Programs
  339. IBM Corporation
  340.  
  341.  
  342. ΓòÉΓòÉΓòÉ 3. Introduction ΓòÉΓòÉΓòÉ
  343.  
  344. INTRODUCTION 
  345.  
  346. This is the second edition to Writing OS/2 2.1 Device Drivers in C. The first 
  347. edition of this book has already sold 15,000 copies in over 30 countries. This 
  348. is not a testament of the book's popularity; rather, it is a statement of the 
  349. tremendous popularity of OS/2. The book began as a collection of my notes taken 
  350. while developing device drivers for OS/2 1.0. The collection of notes kept 
  351. getting larger and larger, so I decided to put them together into a more 
  352. organized form. I finished the first edition of the book in January of 1992 and 
  353. it was first published in April of that year. 
  354.  
  355. Since that time, OS/2 has undergone enormous changes. The latest release, 2.1, 
  356. is rock solid, and contains some of the things we've been waiting for, such as 
  357. support for CD-ROM drives, super VGA video, and multimedia devices such as the 
  358. Sound Blaster. The addition of the Windows 3.1 support has enhanced OS/2's 
  359. popularity, allowing the latest Windows 3.1 applications to run seamlessly on 
  360. the OS/2 desktop. This is the OS/2 we've all envisioned, and IBM has made our 
  361. vision real. 
  362.  
  363. However, OS/2 device drivers continue to be a limiting factor in the acceptance 
  364. and use of OS/2. This is somewhat discouraging, since OS/2 device drivers are 
  365. not difficult to write. Using the examples I give you in this book, you should 
  366. be able to have a simple OS/2 physical device driver up and running in less 
  367. than one hour. Of course, some types of device drivers are more difficult. If 
  368. you follow the guidelines I give you, however, you'll find that writing an OS/2 
  369. device driver can be an easy and rewarding experience. 
  370.  
  371. As an independent software developer and consultant, I don't have time to read 
  372. volumes of reference materials to get up to speed quickly at a new assignment. 
  373. Reference materials have never been good about telling you how to do something 
  374. anyway, since they're only references. Sometimes, a few source code examples 
  375. are all that I really need to get started, and I've kept that in mind when 
  376. writing this book. To help you get going quickly, I've included enough code so 
  377. that you can begin writing OS/2 2.1 device drivers immediately. By the time you 
  378. finish this book, you will have enough background and sample source code to 
  379. easily develop your own OS/2 device drivers. You are free to use the code 
  380. described in the listings section or on the companion disk for your device 
  381. drivers. The code in this book relies upon a library of C-callable functions 
  382. for the Device Helper, or DevHlp routines. The DevHlp routines are the driver 
  383. writer's API, and perform such functions as hooking interrupts, timers and 
  384. converting addresses. At the back of the book, you'll find an order form for 
  385. the C-callable library, or you can write your own providing you have a good 
  386. knowledge of assembler programming and the parameter passing mechanisms via the 
  387. stack. The cost of the library is $79 without the library source, and $149 with 
  388. the library source. This is not inexpensive, but its cheaper than writing more 
  389. than 100 assembly language routines from scratch. If your time is worth more, 
  390. or you need to get going immediately, I recommend you buy the library. I 
  391. provide free support via Compuserve, and offer free updates to the library for 
  392. one year. 
  393.  
  394. This text does not contain a complete discussion or reference for OS/2 2.1, nor 
  395. is it a complete reference for device driver function calls or prototypes; 
  396. readers should have a general understanding of OS/2 2.1 and the OS/2 religion, 
  397. along with some OS/2 2.1 programming experience. See the Reference Section for 
  398. a list of recommended reading. A complete reference for OS/2 1.3 device drivers 
  399. can be found in I/O Subsystems and Device Support, Volume 1 and Volume 2 from 
  400. IBM, which is part of the OS/2 1.3 Programming Tools and Information package. 
  401. Complete documentation for OS/2 2.1 Physical Device Drivers and Virtual Device 
  402. Drivers can be found in the IBM Operating System/2 Version 2.1 Physical Device 
  403. Driver Reference, the IBM Operating System/2 Version 2.1 Virtual Device Driver 
  404. Reference and the IBM Operating System/2 Version 2.1 Presentation Driver 
  405. Reference which are part of the IBM OS/2 2.1 Technical Library. In this book, I 
  406. will discuss the issues, both hardware and software, that will directly affect 
  407. your OS/2 device driver development. Some type of hardware background is 
  408. helpful, but not necessary. 
  409.  
  410. Generally, you can write all of your OS/2 device drivers, including interrupt 
  411. handlers, in C. A device driver written in C can be completed in approximately 
  412. half the time it would take to write the same device driver in assembly 
  413. language. Most device drivers will work fine when written in C. Programmers who 
  414. have written device drivers for other multitasking operating systems, such as 
  415. UNIX or VMS, should find OS/2 device driver design concepts similar. 
  416. Programmers not familiar with multitasking device driver design will find OS/2 
  417. device driver development somewhat more difficult. Your first OS/2 device 
  418. driver could take about two months to complete, and subsequent device drivers 
  419. should take slightly less time. Block and Presentation Manager device drivers 
  420. are significantly more complex, and may take upwards of six to nine months or 
  421. more to complete. I have included a short chapter on Presentation Device 
  422. Drivers, but the topic of PM drivers could easily span an entire book in 
  423. itself. I didn't feel that I could do the topic justice in the limited space of 
  424. this book. Please refer to the IBM OS/2 2.1 Presentation Driver Reference for 
  425. more complete information on writing presentation drivers. 
  426.  
  427. To use the examples in the text or on the companion disk, you will need a 
  428. compiler, assembler, and compatible linker. For OS/2 character mode and block 
  429. device drivers, the Microsoft C 5.1 or 6.0 compiler, the Microsoft 5.1 or 6.0 
  430. Assembler, and the Microsoft 5.13 or later linker will be sufficient. For OS/2 
  431. Virtual Device Drivers, you will need a 32-bit C compiler, such as the IBM C 
  432. Set/2 compiler version 1.1 or greater, along with the corresponding 32-bit 
  433. linker and symbol file generator. 
  434.  
  435. Debugging OS/2 device drivers requires the use of a kernel-level debugger. I 
  436. recommend the kernel debugger supplied with the IBM OS/2 2.1 Toolkit. Other 
  437. third-party debuggers are available, but the IBM kernel debugger is the only 
  438. debugger which has knowledge of the internal kernel symbols. You may also wish 
  439. to look at ASDT32, a 32-bit kernel debugger supplied with the IBM DDK. ASDT32 
  440. provides debugging output on the main display, eliminating the need for a 
  441. debugging terminal. ASDT32 is also available to members of the IBM Developer 
  442. Assistance Program via DAPTOOLS on IBMLINK. 
  443.  
  444. If you are developing or plan to develop an OS/2 product, I recommend that you 
  445. join the IBM Developer Assistance Program. This program, offered to qualified 
  446. software developers, provides up-to-date information on OS/2 2.1, updates to 
  447. the operating system and tools, and substantial discounts on IBM hardware and 
  448. software. Call the IBM Developer Assistance Program at area code (407) 982-6408 
  449. and ask how to become a member. You may also join the IBM Worldwide DAP program 
  450. by entering GO OS2DAP from your Compuserve account. 
  451.  
  452. Unfortunately, two chapters planned for this book did not make it in time for 
  453. this publishing. The two chapters are titled -IFS Drivers' and -SCSI/ADD Device 
  454. Drivers'. These two chapters will appear in the next printing. I apologize for 
  455. this omission, since both are important topics. 
  456.  
  457. In Chapter 1, I describe how device drivers for personal computers evolved from 
  458. simple polling loops to the complex interrupt-driven device drivers found in 
  459. today's real-time PC operating systems. In Chapter 2, I describe what device 
  460. drivers are and how they fit into the total system picture. In Chapter 3, I 
  461. describe the relevant parts of the PC hardware architecture necessary for 
  462. device driver writers to be aware of. If you are already an experienced device 
  463. driver writer, you may wish to skip these three chapters and proceed directly 
  464. to Chapter 4. Chapter 4 begins with a historical look at OS/2 and provides a 
  465. brief outline of the OS/2 operating system. Programmers already familiar with O 
  466. S/2 will probably wish to skip this chapter and proceed directly to Chapter 5. 
  467. In Chapter 5, I discuss the anatomy of the OS/2 device driver by presenting 
  468. sample code fragments, listings, and various tables. Topics include the 
  469. strategy section, interrupt handlers, timer handlers, request packets and 
  470. device headers. Chapter 6 continues the architecture topic by describing, in 
  471. detail, the strategy commands that the device driver receives from OS/2 and how 
  472. the device driver should respond to them. In Chapter 7, I use actual code to 
  473. show you how to build an OS/2 8-bit parallel port device driver. I also 
  474. describe, in detail, the operation of the device driver for each request it 
  475. receives from the OS/2 kernel. Chapter 8 describes the special considerations 
  476. necessary for writing OS/2 device drivers for Micro Channel bus machines, such 
  477. as the IBM PS/2. Chapter 9 describes Virtual Device Drivers, or VDDs, and 
  478. contains code for an actual VDD. In Chapter 10, I show you how to handle 
  479. memory-mapped adapters, and how to perform direct port I/O without a device 
  480. driver. Chapter 11 explains how to use Direct Memory Access, or DMA, and 
  481. includes several code listings to illustrate how DMA is handled under OS/2. In 
  482. Chapter 12, I describe the Extended Disk Driver Interface, also known as the 
  483. Strategy 2 or scatter/gather entry point. Chapter 13 provides a handy reference 
  484. for the OS/2 2.1 Kernel Debugger commands. Chapter 14 contains an introduction 
  485. to Presentation device drivers. In Chapter 15, I describe various types of 
  486. pointers and addressing modes you will need to understand when writing your 
  487. device drivers. Chapter 16 introduces the PCMCIA architecture and how OS/2 2.1 
  488. supports PCMCIA device drivers. Finally, Chapter 17 contains some helpful hints 
  489. and suggestions, as well as a compendium of tips and techniques I've used when 
  490. writing my OS/2 device drivers. 
  491.  
  492. In Appendix A, you'll find a detailed description of the OS/2 Device Helper 
  493. routines with their C calling sequence as provided by the C Callable DevHlp 
  494. library described in the diskette order form in this book. Appendix B includes 
  495. a recommended list of further reading. Appendix C contains source code listings 
  496. for the device drivers and support routines discussed in the book. All of this 
  497. code, without the library, is included on the free companion disk attached to 
  498. the back cover of this book. You are free to use the code for your own use but 
  499. you may not sell it or distribute it for profit without written permission of 
  500. the publisher. Finally, Appendix D contains documentation for the IBM OEMHLP 
  501. and TESTCFG Device Drivers 
  502.  
  503.  
  504. ΓòÉΓòÉΓòÉ 4. Chapter 1 - The Evolution of PC Device Drivers ΓòÉΓòÉΓòÉ
  505.  
  506. In 1976, a small company in Albuquerque, New Mexico, called MITS, founded by Ed 
  507. Roberts, introduced a computer in kit form that could be assembled by a novice 
  508. electronic tinkerer. The computer, called the Altair 8800, delivered technology 
  509. into the home which had previously been confined to laboratories of large 
  510. companies and universities. Based on the Intel 8080 microprocessor, the Altair 
  511. provided much of the functionality of larger machines, but at a much lower 
  512. price. The user could enter a program through the front panel switches and 
  513. execute it. Later, a high-level language program called Beginner's All- purpose 
  514. Symbolic Instruction Code, or BASIC as it's more widely known, was introduced 
  515. for the Altair to make writing programs easier. BASIC was written for MITS by 
  516. Bill Gates and Paul Allen. 
  517.  
  518. The first personal computers were quite expensive by today's standards. A kit 
  519. containing the computer, case and power supply, less any memory or storage, 
  520. sold for $2000.00, not a trivial sum in 1976. Four thousand characters of 
  521. memory was priced at over $1000.00. In addition, many circuits were based on an 
  522. electronic technology that was prone to interference from certain types of 
  523. radio frequencies and small variations in the AC input voltage. The collection 
  524. of electronic circuits and other equipment that comprise a computer system are 
  525. referred to as the computer hardware. The programs that run on the computer are 
  526. referred to as software. 
  527.  
  528. A short time after the Altair was introduced, MITS introduced an audio cassette 
  529. interface, which allowed the use of a standard audio cassette player/recorder 
  530. for the storage of information. Using the audio cassette proved cumbersome. 
  531. Since the computer had no direct control over the cassette player, it could not 
  532. determine, for example, that the play and record buttons were pressed while 
  533. recording, or if the player was even attached to the computer. Recording 
  534. information on audio tape was also unreliable. In order to store a program or 
  535. data onto the tape, the data had to be converted into audio signals before 
  536. writing it to the tape. In order to read the data from the tape, the audio 
  537. signals from the tape had to be converted back into machine code. Since the 
  538. computer had to be programmed to read and write using the cassette tape unit, 
  539. the user had to manually enter a program to perform those operations using the 
  540. front panel switches. 
  541.  
  542. A special integrated circuit, called an Erasable Programmable Read Only Memory, 
  543. or EPROM, was added to solve the problem of having to manually enter the 
  544. initial boot program. The EPROM was programmed to contain the cassette loader, 
  545. and retained its contents even if power was lost. The EPROM contained only 256 
  546. characters or bytes of storage, so the loader program could not be very 
  547. complex. The user could select this EPROM using the computer's front panel 
  548. switches and start the tape program by executing the code located in the EPROM. 
  549.  
  550.  
  551. ΓòÉΓòÉΓòÉ 4.1. Storage Devices ΓòÉΓòÉΓòÉ
  552.  
  553. Shortly thereafter, a floppy disk drive storage system was introduced, which 
  554. provided for the storage of 250,000 bytes on an 8 inch floppy disk, using the 
  555. same format that had been used by IBM on their larger computer systems Again, 
  556. the boot program, this time for floppy disk, was programmed into an EPROM, so 
  557. the user did not have to enter it manually.  The disk boot program turned out 
  558. to be much more complicated, and would not fit into the 256-character storage 
  559. of the EPROM.  This problem was solved by placing a more complex loader onto 
  560. the floppy disk.  The small boot program in the EPROM loaded the more complex 
  561. disk loader, which in turn loaded the selected program or data from the disk. 
  562.  
  563. Software for this new computer was poor to nonexistent. Programs had to be 
  564. written by hand on paper and entered manually. The person writing the program 
  565. had to be somewhat of a computer expert since the programs had to be entered in 
  566. a language of numbers called machine code. Machine code is the only type of 
  567. instruction that a Central Processing Unit, or CPU, can understand. Machine 
  568. code is a representation in the computer's memory of an instruction or piece of 
  569. data, and is expressed in a pattern of ones and zeroes, called binary notation. 
  570. The CPU is capable of recognizing certain patterns of these ones and zeroes, 
  571. which are called bits, as instructions. Programming in machine code proved to 
  572. be time consuming and prone to error, and the slightest programming error could 
  573. be disastrous. 
  574.  
  575.  
  576. ΓòÉΓòÉΓòÉ 4.2. Interface Adapter Cards ΓòÉΓòÉΓòÉ
  577.  
  578. Each device was connected to the CPU through an electronic circuit board called 
  579. an electrical interface card, commonly known today as an adapter. The interface 
  580. card plugged into the computer bus, which was connected to the CPU. A program 
  581. that had to access a device would instruct the CPU to read from or write to the 
  582. interface card, which would in turn issue the correct electrical signals to the 
  583. device to perform the requested operation. The interface acted as a converter 
  584. of sorts, converting CPU instructions into electrical signals to control the 
  585. particular device. A motor, for instance, could be turned on and off using a 
  586. program that commanded an interface to turn the motor on and off. The motor was 
  587. not aware of the computer's presence or programming, but merely acted upon the 
  588. electrical signals generated by the interface card. 
  589.  
  590. Because a very limited number of these adapters were available, programs would 
  591. control them by directing the CPU to directly access the adapter hardware. 
  592. Programs that used particular adapters were written specifically to access 
  593. those adapters. If the adapter was changed, the program would have to be 
  594. rewritten to accommodate the new adapter's requirements. This was unacceptable, 
  595. since a software supplier could not afford to support multiple versions of a 
  596. program for each different type of adapter configuration. 
  597.  
  598.  
  599. ΓòÉΓòÉΓòÉ 4.3. The First Operating System For Personal Computers ΓòÉΓòÉΓòÉ
  600.  
  601. With the introduction of the floppy disk for microcomputers, the first disk- 
  602. based personal computer operating system was born. Called the Control Program 
  603. for Microcomputers, or CP/M, it resided on a floppy disk. When directed to, it 
  604. would load itself into the computer's memory to manage the attached devices, 
  605. including storage devices, keyboards, and terminals. Once loaded into the 
  606. computer's memory, CP/M took responsibility for reading and writing to floppy 
  607. disks, tape drives, printers, terminals, and any other devices attached to the 
  608. computer. The CP/M operating system was a generic piece of software, i.e., it 
  609. could be used on any configuration of computer with the same type of 
  610. microprocessor. To allow this generic operating system to manage different 
  611. configurations of devices, CP/M accessed all devices through a 
  612. hardware-specific set of programs called the Basic Input/Output System, or 
  613. BIOS. By changing a small section of the BIOS program, users could add 
  614. different types of devices while the operating system program remained 
  615. unchanged (see Figure 1-1, below). Figure 1-1. Role of the BIOS 
  616.  
  617. The CP/M BIOS code was an example of an early personal computer device driver. 
  618. The BIOS code isolated the CP/M operating system from the device electronics 
  619. and provided a consistent interface to the devices. Programs that wished to 
  620. read from or write to a particular device did so by calling CP/M routines, 
  621. which in turn called the BIOS. When reading a file from the disk, the 
  622. programmer did not have to keep track of where the file resided on the disk, or 
  623. command the disk unit to position itself where the file was located on the 
  624. disk. The disk geometry parameters, which defined the size of the disk, number 
  625. of tracks, number of heads, and the number of sectors per track, were handled 
  626. by the BIOS code. The developers of the CP/M operating system were free to 
  627. change the operating system without worrying about the many types of hardware 
  628. configurations that existed. Today, the BIOS code is still responsible for 
  629. defining the disk geometry. 
  630.  
  631. Since that time, computer speed and storage have increased exponentially. The 
  632. amount of computer processing power previously requiring the space of a normal 
  633. living room can now fit on a small notebook-size computer. This increased 
  634. performance has allowed the computer to perform more and more tasks for the 
  635. user. In addition, the user's needs have become more sophisticated, and with 
  636. them the software needed to provide a comparable level of functionality has 
  637. become increasingly complex. 
  638.  
  639. The functionality of the operating system and its environment have changed 
  640. dramatically, yet the necessity for the device driver has only increased. The 
  641. basic job of the device driver remains the same. That is, the device driver 
  642. isolates an application program from having to deal with the specific hardware 
  643. constraints of a particular device, and removes such responsibility from the 
  644. programmer. Device drivers allow for the expansion and addition of hardware 
  645. adapters, while allowing the operating system to remain intact. Thus device 
  646. drivers remain the vital link between the computer system's electronics and the 
  647. programs that execute on it. 
  648.  
  649. For CP/M, the BIOS software solved the device independence issues, but did not 
  650. solve all of the problems. The BIOS code resided on a floppy disk and was 
  651. loaded along with the operating system at boot time. Users could change the 
  652. BIOS code to reflect a new device configuration, but the BIOS code was in 
  653. assembly language which was difficult for novice programmers to learn. If the 
  654. BIOS code contained an error, the operating system might not load, or if it did 
  655. load, it would sometimes not work or work erratically. The BIOS was difficult 
  656. to debug, because the debugger used the BIOS code to perform its input and 
  657. output! A few years later, the BIOS code was relocated into Read Only Memory, 
  658. or ROM, and subsequently to Electrically Erasable Programmable Read Only 
  659. Memory, or EEPROM. 
  660.  
  661. Using a special technique, the contents of EEPROM can be modified by a special 
  662. setup program. The contents of memory in EEPROM is retained even if power is 
  663. lost, so the device-specific contents of the BIOS is always retained. 
  664.  
  665.  
  666. ΓòÉΓòÉΓòÉ 4.4. The First Bus ΓòÉΓòÉΓòÉ
  667.  
  668. The Altair introduced the idea of a common set of circuits that allowed all of 
  669. the devices in the system to communicate with the CPU. This common set of 
  670. circuits was called the bus, and the Altair computer introduced the first open- 
  671. architecture bus, called the S-100 bus. It was called the S-100 bus because it 
  672. contained 100 different electronic paths. Connectors were attached to the bus, 
  673. which allowed adapter cards to be plugged into them and connect to the bus. The 
  674. S-100 bus was the forerunner of today's bus architectures. 
  675.  
  676. Although prone to radio-frequency interference, the S-100 bus established 
  677. itself as the standard bus configuration for 8080 and Z-80-based personal 
  678. computers, and was the first attempt at standardizing personal computer 
  679. hardware. The IEEE actually drafted and published a standard for the S-100 bus, 
  680. called IEEE- 696. Some S-100-bus computers are still in operation today. 
  681.  
  682.  
  683. ΓòÉΓòÉΓòÉ 5. Chapter 2 - Understanding Device Drivers ΓòÉΓòÉΓòÉ
  684.  
  685. The use of the BIOS code in CP/M to isolate the operating system from the 
  686. specifics of devices was not a new idea. Large computer systems and mid-range 
  687. computers, called minicomputers, had been using this technique for some time. 
  688. But, this was the first time they were applied to personal computers. 
  689.  
  690. The first operating systems were single tasking, i.e., they were capable of 
  691. executing only one program at a time. Even though these early computers were 
  692. comparatively slow in their operation, they were faster than the devices they 
  693. needed to access. Most output information was printed on a line printer or 
  694. written to a magnetic tape, and most input information was read from a punched 
  695. card reader or keyboard. This meant that if a program was waiting for input 
  696. data, the computer system would be idle while waiting for the data to be 
  697. entered. This operation, called polling, was very inefficient. The computer was 
  698. capable of executing thousands of instructions in between each keystroke. Even 
  699. the fastest typist could not keep up with the computer's input ability to 
  700. process each key. Figure 2-1. Polled printer output 
  701.  
  702. If a program needed to print something on a printer, it would do so one 
  703. character at a time, waiting for the device to acknowledge that the character 
  704. was printed before sending the next character (see Figure 2-1). Since the 
  705. computer processed the data faster than it could be printed, it would sit idle 
  706. for much of the time waiting for the electromechanical printing device to do 
  707. its job.  As technology progressed, faster input and output devices became 
  708. available, all well as faster computers.  Still, the computer was at the mercy 
  709. of the input and output devices it needed.  The configuration of these input 
  710. and output (I/O) devices was also different.  Some line printers printed on 8 
  711. 1/2 by 11-inch paper and some on 8 1/2 by 14-inch paper.  Magnetic tape storage 
  712. devices used different size tapes and formats, and disk storage devices 
  713. differed in the amount and method of storage. 
  714.  
  715. The device driver solved the problems associated with the different types of 
  716. devices and with the computer remaining idle while performing input and output 
  717. operations. The device driver program was inserted between the program doing 
  718. the I/O and the actual hardware device, such as a printer or magnetic tape 
  719. drive. The device driver was programmed with the physical characteristics of 
  720. the device. In the case of a line printer, the device driver was programmed 
  721. with the number of characters per line it accepted or the size of the paper 
  722. that the device could handle. For a magnetic tape device driver, the device 
  723. driver was programmed with the physical characteristics of the tape mechanism, 
  724. such as the format used to read from and write to the drive, and its storage 
  725. capacity. The program performing the I/O did not require detailed knowledge of 
  726. the hardware device. The device driver also allowed the programmer to direct a 
  727. print operation with no knowledge of the type of printer that was attached. 
  728. Thus, a new printer could be added, with its corresponding device driver, and 
  729. the application program could run unmodified with the new printer. 
  730.  
  731. The polling issue was also addressed. Since the device driver had intimate 
  732. knowledge of how to talk to the I/O device, there was no reason why the 
  733. application program had to wait around for each character to be printed (see 
  734. Figure 2-2). It could send the device driver a block of, say, 256 characters 
  735. and return to processing the application program.  The device driver would take 
  736. the characters one at a time and send them out to the printer.  When the device 
  737. driver had exhausted all of its work, it would notify the application program 
  738. of that fact. The application program would then send the device driver more 
  739. data to print, if necessary.  The application program was now free to utilize 
  740. the CPU to perform tasks that demanded more processing, thus reducing the idle 
  741. time of the computer. 
  742.  
  743. The device driver became even more important when operating systems appeared 
  744. that could run more than one program at a time. It was now possible for more 
  745. than one program to use the same I/O device, and often at the same time. The 
  746. device driver was used to serialize access to the device, and protect the 
  747. device from errant programs that might try to perform an incorrect operation or 
  748. even cause a device failure. Figure 2-2. Interrupt printer output 
  749.  
  750.  
  751. ΓòÉΓòÉΓòÉ 5.1. Device Drivers Today ΓòÉΓòÉΓòÉ
  752.  
  753. Today, device drivers remain an irreplaceable and critical link between the 
  754. operating system and the I/O device (see Figure 2-3). Many new I/O devices have 
  755. appeared, including color graphics printers, cameras, plotters, scanners, music 
  756. interfaces, and CD-ROM drives.  The device driver remains a necessary component 
  757. to complete the interface from the operating system to the physical device. 
  758. Today's computers can run dozens and even hundreds of programs at one time.  It 
  759. is more important than ever for the device driver to free up the CPU to do more 
  760. important work, while handling the relatively mundane tasks of reading and 
  761. writing to the device. 
  762.  
  763. Today, device drivers are more complex, as are the operating systems and 
  764. devices they interface with. Device drivers can interact more with the CPU and 
  765. operating system, and in some cases they can allow or block the execution of 
  766. programs. They can usually turn the interrupt system on and off, which is an 
  767. integral part of the performance of the system. Device drivers usually operate 
  768. at the most trusted level of system integrity, so the device driver writer must 
  769. test them thoroughly to assure bug-free operation. Failures at a device driver 
  770. level can be fatal, and cause the system to crash or experience a complete loss 
  771. of data. Figure 2-3. The role of the device driver 
  772.  
  773. The use of computers for graphics processing has become widespread.  It would 
  774. be impossible to support the many types of graphics devices without device 
  775. drivers. Today's hardware offers dozens of different resolutions and sizes. For 
  776. instance, color graphics terminals can be had in CGA, EGA, VGA, MCGA, SVGA, and 
  777. XGA formats, each offering a different resolution and number of supported 
  778. simultaneous displayable colors. Printers vary in dots per inch (DPI), Font 
  779. selection, and interface type. Since all of these formats and configurations 
  780. are still in use, the supplier of a graphics design package needs to support 
  781. all of them to offer a marketable software package. The solution is for the 
  782. graphical design program to read and write to these graphics devices using a 
  783. standard set of programs, called APIs (Application Programming Interfaces), 
  784. which in turn call the device driver specific to the hardware installed. 
  785.  
  786. The device driver has an in-depth knowledge of the device, such as the physical 
  787. size of the output area, the resolution (number of dots or pixels per screen), 
  788. and the special control characters necessary for formatting. For instance, a 
  789. graphics application program might direct the output device to print a line of 
  790. text in Helvetica bold italic beginning at column 3, line 2. Each graphics 
  791. output device, however, might use a different command to print the line at 
  792. column 3, line 2. The device driver resolves these types of differences. 
  793.  
  794. A user might wish to print a 256-color picture on a black and white printer in 
  795. a lower or higher resolution. The device driver would resolve the differences 
  796. and perform the proper translation, clipping and color-to-gray-scale mapping as 
  797. required. While this method allows the graphics program to remain generic for 
  798. any hardware configuration, it does require the software vendor to supply 
  799. device drivers for the many types of input and output devices. Some word 
  800. processors, for example, come with over 200 printer device drivers to support 
  801. all makes and models of printers, from daisy wheel to high-speed laser and 
  802. color printers. 
  803.  
  804.  
  805. ΓòÉΓòÉΓòÉ 5.2. Device Drivers - A Summary ΓòÉΓòÉΓòÉ
  806.  
  807. In summary, the device driver:
  808.  
  809.  o Contains the specific device characteristics and removes any
  810.   responsibility of the application program for having knowledge of the
  811.   particular device.
  812.  
  813.   In the case of a disk device driver, the device driver might contain the
  814.   specific disk geometry, which is transparent to the program that calls
  815.   the device driver. The device driver maps logical disk sectors to their
  816.   physical equivalents. The application program need not be aware of the
  817.   size of the disk, the number of cylinders, the number of heads, or the
  818.   number of sectors per track. The device driver also controls the disk
  819.   seek, which is the motion necessary to position the read/write head over
  820.   the proper area of the disk. This simplifies the application code, by
  821.   allowing it to issue only reads and writes, and leaving the details of how
  822.   it is done to the device driver.
  823.  
  824.   In the case of a video device driver, the driver might contain the size of
  825.   the screen, the number of pixels per screen, and the number of
  826.   simultaneous colors that can be displayed. Programs that need access to
  827.   the display call the display device driver, which performs several
  828.   functions. First, it maps the number of colors in the picture to those
  829.   supported by the video adapter. This is especially true if a color picture
  830.   is displayed on a black and white (monochrome) display. Second, if the
  831.   resolution of the target display is smaller than the original, the device
  832.   driver must adjust the size proportionally. Third, it might adjust the
  833.   aspect ratio, the ratio of vertical pixels to horizontal pixels. A circle, for
  834.   example, would appear egg-shaped without the correct aspect ratio.
  835.  
  836.   In the case of a serial device, such as a modem, the device driver
  837.   handles the specifics of the electronics that perform the actual sending
  838.   and receiving of data, such as the transfer speed and data type.
  839.  
  840.  o Allows for device independence by providing for a common program
  841.   interface, allowing the application program to read from or write to
  842.   generic devices. It also handles the necessary translation or conversion
  843.   which may be required by the specific device.
  844.  
  845.  o  Serializes access to the device, preventing other programs from
  846.   corrupting input or output data by attempting to access the device at
  847.   the same time.
  848.  
  849.  o  Protects the operating system and the devices owned by the operating
  850.   system from errant programs which may try to write to them, causing
  851.   the system to crash.
  852.  
  853.  
  854. ΓòÉΓòÉΓòÉ 6. Chapter 3 - The PC Hardware Architecture ΓòÉΓòÉΓòÉ
  855.  
  856. Writing device drivers requires you to have at least a limited understanding of 
  857. the personal computer hardware architecture. Device drivers are special pieces 
  858. of software because they "talk" directly to electronic circuits. Application 
  859. programs, or those programs that use device drivers to access devices, can be 
  860. written without a knowledge of the electronics. While you don't have to be an 
  861. electrical engineer, you will need at least a basic knowledge of the hardware 
  862. you will be interacting with. 
  863.  
  864.  
  865. ΓòÉΓòÉΓòÉ 6.1. The System Bus ΓòÉΓòÉΓòÉ
  866.  
  867. The CPU is connected to the rest of the computer through electrical circuits 
  868. called the bus. The bus contains the electrical paths common to different 
  869. devices, allowing them to access each other using a very specialized protocol. 
  870. The CPU is allowed read and write access to the computer's memory (and some 
  871. devices) by means of the address bus. Data is moved to and from devices (and 
  872. memory) via the data bus. The computer bus is the center of communications in 
  873. the computer. To allow hardware interfaces or adapters to gain access to the 
  874. CPU, the computer system is fitted with connectors to allow adapters to be 
  875. plugged into the bus. The adapters must adhere to the electrical standards of 
  876. the bus. Certain restrictions, such as bus timing and switching must be adhered 
  877. to by the adapter manufacturers, or the entire system may experience erratic 
  878. behavior or possibly not function at all. 
  879.  
  880. The width of the bus, or the number of bits that can be transferred to or from 
  881. memory or devices in parallel, directly affects system performance. Systems 
  882. with "wider" busses will, in general, offer greater performance because of 
  883. their ability to move more data in less time. 
  884.  
  885. Today there are three primary bus architectures in the IBM-compatible 
  886. marketplace. They are called Industry Standard Architecture (ISA), Enhanced 
  887. Industry Standard Architecture (EISA) and Micro Channel Architecture (MCA). Of 
  888. course, there are other types of busses used for non-IBM compatible computers, 
  889. but they will not be covered in this book. 
  890.  
  891.  
  892. ΓòÉΓòÉΓòÉ 6.2. The IBM PC - Beginnings ΓòÉΓòÉΓòÉ
  893.  
  894. In 1981, IBM released the IBM PC, a personal computer based on the Intel 8088 
  895. microprocessor.  The 8088 was a 16-bit microprocessor, and was IBM's first 
  896. entry into the personal computer market.  IBM was known worldwide as a supplier 
  897. of large data processing systems, but this was their first product for personal 
  898. use.  The IBM PC contained a new bus design called the PC bus.  The PC bus was 
  899. fitted with adapter card slots for expansion, and to make the bus popular, IBM 
  900. released the specifications of the PC bus.  This encouraged third-party 
  901. suppliers to release many different types of adapters to be used in the IBM PC. 
  902. This was a strategic move by IBM which led to the standardization of the PC bus 
  903. architecture for all personal computers. 
  904.  
  905. Storage was limited to a single floppy disk, capable of storing approximately 
  906. 180,000 bytes of information. 
  907.  
  908. The IBM PC was not a relatively fast machine, but users could, for the first 
  909. time, have an IBM computer on their desks. Original sales projections for the 
  910. IBM PC were a few hundred thousand units, but demand quickly exceeded 
  911. availability. The personal computer revolution had begun. 
  912.  
  913.  
  914. ΓòÉΓòÉΓòÉ 6.3. IBM PC XT ΓòÉΓòÉΓòÉ
  915.  
  916. In 1982, IBM introduced the IBM XT computer. The IBM XT contained a built-in 
  917. ten million byte (10MB) hard disk storage device, and the floppy disk storage 
  918. was doubled to 360,000 bytes (360KB). The IBM XT was based on the IBM PC and 
  919. retained the same basic design, except that users could now store ten million 
  920. characters of data on the hard disk. 
  921.  
  922. Computer hardware can process instructions relatively fast. The execution of a 
  923. simple instruction may take less than one microsecond (.000001 seconds). The 
  924. computer input and output devices, however, are relatively slow. For example, 
  925. if the computer was receiving bytes of data from another computer over a phone 
  926. line, the time to receive just one byte of data would be approximately 4 
  927. milliseconds (.004 seconds). If the  computer was just waiting for more bytes 
  928. to appear, it would be spending most of its time doing nothing but waiting. 
  929. This would be extremely inefficient, as the computer could have executed 
  930. thousands of instructions while waiting for another byte. This problem is 
  931. solved by a hardware mechanism called the interrupt system. The interrupt 
  932. system allows an external event, such as the reception of a character, to 
  933. interrupt the program currently being executed. A special program, called an 
  934. interrupt handler, interrupts the currently executing program, receives the 
  935. character, processes it, and returns to the program that was executing when the 
  936. interrupt was received. The program that was executing at the time of the 
  937. interrupt resumes processing at the exact point at which it was interrupted. 
  938.  
  939. The IBM PC and PC XT had an eight-level Programmable Interrupt Controller 
  940. (PIC), which permitted up to eight interrupts on the PC bus. This represented 
  941. somewhat of a problem, as several interrupt levels were already dedicated to 
  942. the system. The system timer reserved an interrupt, as well as the hard disk, 
  943. floppy drive, printer port and serial port. This left only two unused 
  944. interrupts, which were reserved for a second printer and second serial 
  945. communications port. If you happened to have these devices installed, you could 
  946. not install any other adapter cards that utilized interrupts. 
  947.  
  948.  
  949. ΓòÉΓòÉΓòÉ 6.4. IBM PC AT ΓòÉΓòÉΓòÉ
  950.  
  951. In 1984, IBM introduced the IBM PC AT personal computer. The IBM PC AT computer 
  952. utilized the Intel 80286, a more powerful 16-bit microprocessor. The IBM PC AT 
  953. utilized a newly designed bus, called the AT bus. The AT bus added eight 
  954. additional address and data lines, to enable the CPU to transfer twice as much 
  955. data in the same amount of time as the IBM PC. In another brilliant engineering 
  956. innovation, IBM made the AT bus downward compatible with existing IBM PC 
  957. adapter cards. The user did not have to give up a large investment in adapter 
  958. hardware to upgrade to the IBM PC AT. The AT could use newly introduced 16-bit 
  959. adapters as well as the existing eight bit adapters. The newer bus could still 
  960. accommodate the older PC and XT bus adapter cards. Today, the AT bus remains 
  961. the most popular IBM PC-compatible bus in existence, with over 100 million 
  962. installed, and is commonly called the ISA bus. 
  963.  
  964. The processor speed of the PC AT was increased 25 percent, and the combination 
  965. of processor speed and greater bus width led to dramatic performance increases 
  966. over PC XT. The PC AT was equipped with a 20MB hard disk, a 1.2MB floppy disk, 
  967. and was fitted with a larger power supply to handle the increased speed and 
  968. capacity. The color display was becoming more popular, but was limited in 
  969. colors and resolution.  IBM quickly introduced an upgraded model of the IBM PC 
  970. AT, called the model 339. The newer version came with a 30MB hard disk and a 
  971. 1.2MB floppy disk. To retain compatibility, the AT's floppy disk could also 
  972. read and write to the smaller capacity 360K byte floppies for the IBM PC XT. 
  973. Processor speed was again bumped up 33 percent. 
  974.  
  975. The AT bus, however, had limitations. The electrical design of the bus was 
  976. limited by the speed that data could be transferred on the bus. This was not a 
  977. problem for the IBM PC AT, but as processors became faster and users demanded 
  978. more power, the performance of the AT bus became a limiting factor. 
  979.  
  980.  
  981. ΓòÉΓòÉΓòÉ 6.5. The AT Bus ΓòÉΓòÉΓòÉ
  982.  
  983. When the IBM PC AT was introduced in 1984, the bus requirements changed 
  984. significantly. The IBM PC AT used the Intel 80286, which was also a 16-bit 
  985. processor. The processor speed was increased by thirty percent. Since the 
  986. memory address could be 16 bits wide, the processor could now issue only one 
  987. address command to the memory circuits, cutting the time necessary to address 
  988. memory in half. The data bus width was also increased to 16 bits, and 8 more 
  989. interrupts were added. 
  990.  
  991. The AT bus has 24 address lines, which limits the amount of directly 
  992. addressable memory to 16MB, but recent IBM-compatibles have provided a separate 
  993. CPU-to-memory bus, which is 32 bits wide. The peripheral address bus that the 
  994. adapter cards plug into remains a 24 bit address bus. 
  995.  
  996. The IBM PC AT was upgraded to run another thirty percent faster by raising the 
  997. processor clock speed to 8 megahertz (Mhz). Performance increased dramatically, 
  998. but a problem for future expansion now became apparent. The electrical design 
  999. characteristics of the AT bus prohibited it from reliably running at speeds 
  1000. faster than 8 Mhz, with a maximum bus throughput of about 8MB per second. Users 
  1001. were demanding more power, and CPU makers such as Intel were producing faster 
  1002. and more powerful processors. 
  1003.  
  1004. Adapter cards for the AT bus required the manual installation and/or removal of 
  1005. small electrical jumpers to define the characteristics of the card. There were 
  1006. jumper settings for the card address, interrupt level, adapter card port 
  1007. address, timing, and a host of other options. This sometimes made installation 
  1008. troublesome. An incorrectly placed jumper could cause the adapter not to work 
  1009. or the system to hang. Novice computer users had a tough time understanding all 
  1010. of the options and how to set them for various configurations. Boards were 
  1011. often returned to manufacturers for repair when all that was wrong was an 
  1012. incorrectly installed jumper. 
  1013.  
  1014. The AT bus design allows for 15 interrupts, but adapters cannot share the same 
  1015. interrupt, or IRQ level. Once a device driver claims an interrupt level, the 
  1016. interrupt level cannot be used for another adapter. 
  1017.  
  1018.  
  1019. ΓòÉΓòÉΓòÉ 6.6. The IBM PS/2 and Micro Channel ΓòÉΓòÉΓòÉ
  1020.  
  1021. IBM's answer to the limitations of the AT bus was to create, from scratch, an 
  1022. entirely new bus architecture. This new architecture, called Micro Channel, was 
  1023. (and is) vastly superior to the AT bus architecture. Since IBM decided that the 
  1024. bus did not have to support existing adapter cards and memory, they were free 
  1025. to design the new bus without restrictions. The Micro Channel bus was a 
  1026. proprietary bus (which has since been made public) that was designed to solve 
  1027. all of the existing problems with the AT bus, and to provide for an 
  1028. architecture that would support multiple processors and bus-masters on the same 
  1029. bus using a bus arbitration scheme. In addition, the Micro Channel bus provided 
  1030. greater noise immunity from Radio Frequency Interference (RFI), 32 address 
  1031. lines, 24 DMA address lines, and 16 data lines with increased speed 
  1032. (bandwidth). The first Micro Channel bus computer was twice as fast as the IBM 
  1033. PC AT, and had a maximum  bus transfer rate of 20MB per second. Some Micro 
  1034. Channel adapters can manage as much as 160MB per second. 
  1035.  
  1036. The Micro Channel bus supports multiple bus masters. Bus mastering allows an 
  1037. adapter to obtain control of the system bus to perform I/O at higher rates than 
  1038. if the CPU was used. The Micro Channel design supports up to 15 bus masters. 
  1039. The Micro Channel bus also has better grounding and more interrupt capability. 
  1040.  
  1041. IBM introduced a brand new line of computers, called the Personal System/2, or 
  1042. PS/2, which utilized the Micro Channel technology.  The new computers offered 
  1043. several new features, such as built-in support for VGA color and 
  1044. larger-capacity Enhanced Small Disk Interface, or ESDI, hard disk drives.  In 
  1045. the area of hardware, IBM made three major design changes.  First, they 
  1046. designed the Micro Channel bus to be slot dependent.  That is, each slot was 
  1047. addressable by the CPU.  This differed from the IBM PC and PC AT bus machines, 
  1048. where adapter boards could be placed in any slot. 
  1049.  
  1050. Second, they specified that each adapter  that was plugged into the Micro 
  1051. Channel bus would need its own unique identifier assigned by IBM.  The ID was 
  1052. stored in EEPROMs located on each adapter card.  In addition, the EEPROMs would 
  1053. hold card configuration data, such as the memory-mapped address, interrupt 
  1054. level, and port address of the adapter. These special registers were called 
  1055. Programmable Option Select registers, or POS registers.  These registers, 
  1056. addressable only in a special mode, eliminated the need for configuration 
  1057. jumpers required for AT bus adapters.  The user would load a special 
  1058. configuration program, which would set the adapter configuration and program 
  1059. the EEPROMs and each adapter. 
  1060.  
  1061. Third, they included 64 bytes of Non-volatile Random Access Memory, or NVRAM, 
  1062. which would hold the current configuration information for each slot. The 
  1063. contents of the NVRAM is retained by a low-voltage battery. When the computer 
  1064. was powered on, a Read Only Memory, or ROM, resident program would compare, 
  1065. slot by slot, the configuration of each adapter to the current configuration 
  1066. stored in NVRAM. If it found a difference, it would stop and force the user to 
  1067. run the setup program to reconfigure the system. This Power On Self Test or 
  1068. POST, also checks the size of memory and compares it to the amount configured 
  1069. in NVRAM. 
  1070.  
  1071.  
  1072. ΓòÉΓòÉΓòÉ 6.7. Enhanced Industry Standard Architecture (EISA) ΓòÉΓòÉΓòÉ
  1073.  
  1074. The third major innovation in bus technology was the introduction of the 
  1075. Enhanced Industry Standard Architecture bus, or EISA bus. The EISA bus was 
  1076. introduced in September of 1988 in response to IBM's introduction of the Micro 
  1077. Channel bus. Some of the motivation for the EISA bus was the same as for the 
  1078. Micro Channel. EISA was designed for high throughput and bus mastering, and is 
  1079. capable of 33MB per second throughput. The developers of the EISA bus 
  1080. maintained compatibility with existing ISA bus adapters by designing a 
  1081. connector that would accept either type of adapter card. It should be noted, 
  1082. however, that using an ISA bus adapter in an EISA bus system provides no 
  1083. increased performance. 
  1084.  
  1085. The EISA bus, like the Micro Channel bus, supports multiple bus masters, but 
  1086. only six compared to Micro Channel's 15. This is still better than the ISA bus, 
  1087. which supports only one bus master. Throughput of the ISA bus machine is 
  1088. limited by the processor speed, as more work has to be done by the CPU. In a 
  1089. multiple bus master architecture like EISA or Micro Channel, the adapter card 
  1090. relieves the CPU of the responsibility of handling the high-speed data 
  1091. transfers, and thus is more efficient. 
  1092.  
  1093.  
  1094. ΓòÉΓòÉΓòÉ 6.8. Bus Wars ΓòÉΓòÉΓòÉ
  1095.  
  1096. Many benchmarks have been performed pitting the three buses against each other. 
  1097. With a few exceptions, the casual user will not notice much difference between 
  1098. them. However, increasing demands for higher transfer rates and increased CPU 
  1099. performance will soon make the traditional AT bus obsolete. The AT bus is 
  1100. handicapped by its 24-bit address bus and 16-bit data bus, which limits 
  1101. performance by permitting the system to transfer data only half as fast as EISA 
  1102. and Micro Channel bus systems. It is also limited by its interrupt support and 
  1103. bus-mastering capabilities. Without another alternative, this leaves EISA and 
  1104. Micro Channel as the natural successors to the ISA bus. IBM is gearing up for 
  1105. the challenge, and has recently specified a new mode of Micro Channel operation 
  1106. that will run on all IBM Micro Channel machines. The new specification, called 
  1107. Micro Channel II, allows for transfer rates of 40, 80, and 160MB per second, 
  1108. leaving the EISA machines in the dust. IBM is also beginning to price their 
  1109. Micro Channel systems at equal to or less than their ISA equivalents in an 
  1110. attempt to make the Micro Channel bus more popular. The EISA bus, however, 
  1111. maintains compatibility with the wide variety of inexpensive ISA adapters, and 
  1112. is not likely to be upstaged in the near future by the Micro Channel bus. 
  1113.  
  1114. EISA promises to remain popular because of the large investment in ISA bus 
  1115. adapters and the reluctance of many users to embrace the Micro Channel bus. 
  1116.  
  1117.  
  1118. ΓòÉΓòÉΓòÉ 6.9. Real Mode ΓòÉΓòÉΓòÉ
  1119.  
  1120. The Intel processors are capable of operating in one of two modes. These are 
  1121. called real mode and protect mode. The most popular computer operating system, 
  1122. DOS, runs in real mode. In real mode, the processor is capable of addressing up 
  1123. to one megabyte of physical memory. This is due to the addressing structure, 
  1124. which allows for a 20-bit address in the form of a segment and offset (see 
  1125. Figure 3-1). Figure 3-1. Real mode address calculation 
  1126.  
  1127. Real mode allows a program to access any location within the one megabyte 
  1128. address space. There are no protection mechanisms to prevent programs from 
  1129. accidentally (or purposely) writing into another program's memory area. There 
  1130. is also no protection from a program writing directly to a device, say the 
  1131. disk, and causing data loss or corruption. DOS applications that fail generally 
  1132. hang the system and call for a <ctrl-alt-del> reboot, or in some cases, a 
  1133. power-off and a power-on reboot (POR). The real mode environment is also ripe 
  1134. for viruses or other types of sabotage programs to run freely. Since no 
  1135. protection mechanisms are in place, these types of "Trojan horses" are free to 
  1136. infect programs and data with ease. 
  1137.  
  1138.  
  1139. ΓòÉΓòÉΓòÉ 6.10. Protect Mode ΓòÉΓòÉΓòÉ
  1140.  
  1141. The protect mode of the Intel 80286 processor permits direct addressing of 
  1142. memory up to 16MB, while the Intel 80386 and 80486 processors support the 
  1143. direct addressing of up to four gigabytes (4,000,000,000 bytes).  The 80286 
  1144. processor uses a 16-bit selector and 16-bit offset to address memory (see 
  1145. Figure 3-2). A selector is an index into a table that holds the actual address 
  1146. of the memory location.  The offset portion is the same as the offset in real 
  1147. mode addressing. This mode of addressing is commonly referred to as the 16:16 
  1148. addressing. Under OS/2 2.1, the 80386 and 80486 processors address memory using 
  1149. a selector:offset, but the value of the selector is always 0, and the offset is 
  1150. always 32 bits long (see Figure 3-3). This mode of addressing is referred to as 
  1151. the 0:32 or flat addressing. The protect mode provides hardware memory 
  1152. protection, prohibiting a program from accessing memory owned by another 
  1153. program.  While a defective program in real mode can bring down the entire 
  1154. system (a problem frequently encountered by systems running DOS).  A protect 
  1155. mode program that fails in a multitasking operating system merely reports the 
  1156. error and is terminated.  Other programs running at the time continue to run 
  1157. uninterrupted. Figure 3-2. 80286 protect mode addressing 
  1158.  
  1159. To accomplish this memory protection, the processor keeps a list of memory 
  1160. belonging to a program in the program's Local Descriptor Table, or LDT. When a 
  1161. program attempts to access a memory address, the processor hardware verifies 
  1162. that the address of the memory is within the memory bounds defined by the 
  1163. program's LDT. If it is not, the processor generates an exception and the 
  1164. program is terminated. Figure 3-3. 80386-486 flat mode addressing 
  1165.  
  1166. The processor also keeps a second list of memory called the Global Descriptor 
  1167. Table, or GDT. The GDT usually contains a list of the memory owned by the 
  1168. operating system, and is only accessible by the operating system and device 
  1169. drivers. Application programs have no direct access to the GDT except through a 
  1170. device driver. 
  1171.  
  1172. OS/2 1.x uses the protect mode of the Intel processor to run native OS/2 
  1173. programs, and provides a single DOS "compatibility box" for running DOS 
  1174. applications. If a DOS session is selected while the system is running an OS/2 
  1175. application, the processor stops running in protect mode and switches to the 
  1176. real mode to accommodate the DOS application. A poorly programmed DOS 
  1177. application can bring down the entire system. 
  1178.  
  1179. OS/2 2.1 runs DOS programs in the protect mode, using the virtual 8086 mode of 
  1180. the 80386 and 80486 processors. This special mode allows each DOS application 
  1181. to run in its own protected one megabyte of memory space, without being aware 
  1182. of any other applications running on the system. Each virtual DOS partition, or 
  1183. VDM, thinks that it's the only application running. Errant DOS programs are 
  1184. free to destroy their own one megabyte environment, but cannot crash the rest 
  1185. of the system. If a DOS application fails in a VDM, a new copy of DOS can be 
  1186. booted into the VDM and restarted. For a more complete description of the Intel 
  1187. processors and their architecture, please refer to Appendix B for a list of 
  1188. recommended reading. 
  1189.  
  1190.  
  1191. ΓòÉΓòÉΓòÉ 6.11. Using Addresses and Pointers ΓòÉΓòÉΓòÉ
  1192.  
  1193. Writing an OS/2 2.1 device driver requires a thorough understanding of 
  1194. addresses, pointers, and the OS/2 2.1 memory management DevHlp routines. Since 
  1195. OS/2 2.1 is a hybrid operating system composed of 16-bit and 32-bit code, many 
  1196. of your device driver functions will involve pointer conversion and 
  1197. manipulation. Specifically, pointers might have to be converted from 16-bit to 
  1198. 32-bit, and from 32-bit back to 16-bit. Addresses might be expressed as 
  1199. virtual, physical or linear address. Several DevHlp functions require flat 
  1200. pointers to items in the driver's data segment, which is normally a 16:16 
  1201. pointer. If you don't have a good understanding of 16-bit and 32-bit addresses 
  1202. or pointers, please go back and reread the previous sections. Refer to Chapter 
  1203. 15 for more information. 
  1204.  
  1205.  
  1206. ΓòÉΓòÉΓòÉ 6.12. The Ring Architecture ΓòÉΓòÉΓòÉ
  1207.  
  1208. In the protect mode, the processor operates in a Ring architecture. The ring 
  1209. architecture protects the operating system by allowing minimum access to the 
  1210. system and hardware. 
  1211.  
  1212. Normal application programs run at Ring 3, which is the least trusted ring (see 
  1213. Figure 3-4). Programs that run in Ring 3 have no direct access to the operating 
  1214. system or hardware, and must adhere to very strict guidelines for accessing 
  1215. OS/2 or its supported devices. 
  1216.  
  1217. Ring 2 is reserved for Input/Output Privilege Level (IOPL) programs (see 
  1218. Chapter 10) and 16-bit Dynamic Link Libraries, or DLLs. With OS/2 2.1, 32-bit 
  1219. DLLs run in Ring 3. Refer to Chapter 4 for a more detailed discussion of DLLs. 
  1220.  
  1221. Ring 1 is currently reserved. 
  1222.  
  1223. Ring 0 is the most trusted level of the processor, and is where physical and 
  1224. virtual device drivers run. Device drivers need, and are granted, full access 
  1225. to the processor and system hardware as well as the interrupt system and OS/2 
  1226. internals. 
  1227.  
  1228. Most application programs will run in Ring 3. Occasionally, for performance 
  1229. reasons, an application may need to write directly to adapter hardware and will 
  1230. do so through an IOPL routine at Ring 2, but will quickly return to Ring 3 to 
  1231. continue running. An example of such a program is the CodeView debugger. As an 
  1232. additional protection method, OS/2 can refuse input and output by a Ring 2 
  1233. program if the user modifies the CONFIG.SYS file to contain the line IOPL=NO. 
  1234. Programs attempting to perform Ring 2 I/O will generate a General Protection, 
  1235. or GP fault if IOPL=NO appears in the CONFIG.SYS file. Users may also permit 
  1236. only selected programs to perform IOPL by entering the program names in 
  1237. CONFIG.SYS. See Chapter 10 for a discussion of IOPL. Figure 3-4. The 80X86 ring 
  1238. architecture 
  1239.  
  1240.  
  1241. ΓòÉΓòÉΓòÉ 7. Chapter 4 - An Overview of the OS/2 Operating System ΓòÉΓòÉΓòÉ
  1242.  
  1243. OS/2, introduced in late 1987, was billed as the successor to DOS. In fact, it 
  1244. was going to be called DOS before IBM got into the act. Over 500 programmers at 
  1245. IBM and Microsoft worked night and day to get OS/2 out the door on schedule. 
  1246. Both IBM and Microsoft trumpeted OS/2 as the replacement for DOS, and Bill 
  1247. Gates himself predicted that OS/2 would replace DOS on the desktop by 1989. 
  1248. This, of course, never happened. The reasons why OS/2 never caught on can be 
  1249. debated forever, but probably can be summarized in a few key statements. 
  1250.  
  1251. First, when IBM announced OS/2, there were only a handful of applications ready 
  1252. to run on it. The few that were ready were just warmed-over DOS versions, which 
  1253. were recompiled and relinked under OS/2. They also ran considerably slower than 
  1254. their DOS counterparts. 
  1255.  
  1256. Second, the graphical user interface for OS/2, called Presentation Manager, was 
  1257. missing. As a result, most application programs were written with dull, 
  1258. character-based user interfaces. 
  1259.  
  1260. Third, the DOS compatibility box, or penalty box as it was sometimes referred 
  1261. to as, crashed frequently when DOS applications were run under it. It simply 
  1262. wasn't compatible with DOS. Some DOS applications would run, but most wouldn't. 
  1263. This was largely a result of the small amount of memory available to a DOS 
  1264. application, which was only approximately 500MB. Users were reluctant to 
  1265. replace DOS with an operating system that wouldn't run all of their favorite 
  1266. DOS applications. 
  1267.  
  1268. Fourth, IBM made a big mistake by attempting to tie the OS/2 name to their 
  1269. recently introduced family of PS/2 computers. Users believed that OS/2 would 
  1270. run only on PS/2 machines. IBM also bungled the marketing of OS/2. IBM 
  1271. authorized dealers didn't know what OS/2 was, how to sell it or how to order 
  1272. it. No advertisements appeared for OS/2, and it wasn't actively shown at trade 
  1273. shows or in technical publications. OS/2 was virtually ignored until sometime 
  1274. in 1990, just following the introduction and huge success of Microsoft Windows 
  1275. 3.0. 
  1276.  
  1277. Lastly, the timing was bad. OS/2 needed four megabytes or more of memory, and 
  1278. memory was selling for approximately $400 per megabyte. The high memory prices 
  1279. were due in part to high tariffs placed on the Japanese for dumping memory 
  1280. chips and to increased demand. Most systems had one megabyte of memory or less, 
  1281. so upgrading was very expensive. OS/2 was not cheap, about $350 for the 
  1282. Standard Edition, which, combined with the cost of extra memory, represented a 
  1283. substantial upgrade cost. 
  1284.  
  1285. Spurred on by the huge success of Windows 3.0, Microsoft decided that it would 
  1286. abandon OS/2 and concentrate on the Windows platform, which is based on DOS. 
  1287. IBM, left without a multitasking solution for its PC-to- mainframe connection, 
  1288. had been counting on OS/2 to replace DOS. IBM finally woke up and realized that 
  1289. without some major changes in the way OS/2 was designed and marketed, that OS/2 
  1290. would die an untimely death. The result of IBM's rude awakening was the 
  1291. introduction of OS/2 2.1 early in 1992. 
  1292.  
  1293.  
  1294. ΓòÉΓòÉΓòÉ 7.1. Roots ΓòÉΓòÉΓòÉ
  1295.  
  1296. OS/2 was originally called MS-DOS version 4.0. MS-DOS 4.0 was designed for 
  1297. preemptive multitasking, but was still crippled by the 640KB memory space 
  1298. restriction of real mode operation. A new product, called MS-DOS 5.0 was 
  1299. conceived, and IBM and Microsoft signed a Joint Development Agreement to 
  1300. develop it. MS-DOS 5.0 was later renamed OS/2. OS/2 was designed to break the 
  1301. 640KB memory barrier by utilizing the protect mode of the 80286 processor. The 
  1302. protect mode provided direct addressing of up to 16 megabytes of memory and a 
  1303. protected environment where badly written programs could not affect the 
  1304. integrity of other programs or the operating system. 
  1305.  
  1306. When Gordon Letwin, Ed Iaccobuci, and the developers at IBM and Microsoft first 
  1307. designed OS/2 1.0, they had several goals in mind. First, OS/2 had to provide a 
  1308. graphical device interface that was hardware independent. The concept was that 
  1309. each device would be supplied with a device driver containing the specific 
  1310. characteristics of the device. Graphics applications could be written without 
  1311. regard to the type of graphics input or output device. This concept is referred 
  1312. to as virtualization. However, virtualization comes at a cost. When an 
  1313. application sends a request to the OS/2 kernel for access to a device, the 
  1314. kernel has to build a request and send it to the device driver. The device 
  1315. driver has to break it down, perform the operation, format the data, and 
  1316. transfer it back to the application. 
  1317.  
  1318. Second, OS/2 had to allow direct hardware access to some peripherals for 
  1319. performance reasons. Peripherals such as video adapters require high-speed 
  1320. access to devices, and the normal device driver mechanism was just not fast 
  1321. enough. To solve this problem, OS/2 allows applications or Dynamic Link 
  1322. Libraries (DLLs) to perform direct I/O to adapter hardware. The video device 
  1323. driver, which resides in a Dynamic Link Library (DLL), can access the device 
  1324. directly without calling a device driver to perform the I/O. Dynamic Linking 
  1325. also allows programs to be linked with undefined external references, which are 
  1326. resolved at run time by the OS/2 system loader. The unresolved entry points 
  1327. exist in DLLs on the OS/2 system disk, and are loaded into memory and linked 
  1328. with the executable program at run time. The use of DLLs allows system services 
  1329. that exist in the DLLs to be modified by changing a DLL and not the entire 
  1330. system. A display adapter, for example, could be added simply by a adding a new 
  1331. DLL. Additional system functions and processes can be implemented as DLLs. 
  1332.  
  1333. Third, OS/2 had to provide an efficient, preemptive multitasking kernel. The 
  1334. kernel had to run several programs at once, yet provide an environment where 
  1335. critical programs could get access to the CPU when necessary. OS/2 uses a 
  1336. priority-based preemptive scheduler. The preemptive nature of the OS/2 
  1337. scheduler allows it to "take away" the CPU from a currently running application 
  1338. and assign it to another application. If two programs of equal priority are 
  1339. competing for the CPU, the scheduler will run each program in turn for a short 
  1340. period of time, called a time slice. This ensures that every program will have 
  1341. access to the CPU, and that no one program can monopolize the CPU. 
  1342.  
  1343. Fourth, OS/2 had to provide a robust, protected environment. OS/2 uses the 
  1344. protect mode of the 80286 and above processors, which has a built-in memory 
  1345. protection scheme. Applications that attempt to read or to write from memory 
  1346. that is not in their specific address space are terminated without compromising 
  1347. the operating system integrity. OS/2 had to run applications that were larger 
  1348. than the physical installed memory.  OS/2 accomplishes this with swapping. If a 
  1349. program asks for more memory than exists, a special fault is generated, which 
  1350. causes the existing contents of memory to be swapped out to a disk file, 
  1351. thereby freeing up the required memory. When the program accesses a function 
  1352. that has been swapped out to disk, a special fault is generated to cause the 
  1353. required functions to be swapped back into physical memory. Swapping allows 
  1354. large programs to be run with less memory than the application requires, but 
  1355. swapping can cause a considerable degradation in speed. 
  1356.  
  1357. Fifth, OS/2 had to run on the 80286 processor. At the time that OS/2 was 
  1358. designed, the 80286 was the only CPU that could run a multitasking protect mode 
  1359. operating system. The 80386 machines were not available, so IBM and Microsoft 
  1360. committed to a version of OS/2 which would run on the 80286 platform. This was 
  1361. purely a marketing decision, based on the number of 80286 machines installed at 
  1362. the time. The implementation of OS/2 on the 80286 proved to be clumsy and slow. 
  1363. The operating system had to be designed for the 16-bit architecture of the 
  1364. 80286, but really required a 32-bit architecture to perform well. The 80286 
  1365. could operate in the protect mode and real mode, but could not switch back and 
  1366. forth gracefully. It could switch from the real mode to the protect mode 
  1367. easily, but not back. The processor was designed to run in only one mode, not 
  1368. both. Because OS/2 had to support OS/2 applications and DOS applications all at 
  1369. one time, a way had to be found to change the processor mode on the fly. Gordon 
  1370. Letwin came up with the patented idea of how to do this with what has been 
  1371. referred to as "turning the car off and on at 60 MPH." 
  1372.  
  1373. Lastly, OS/2 had to run existing "well-behaved" DOS applications. Well- behaved 
  1374. DOS programs were those programs that did not directly access the hardware or 
  1375. use shortcuts to improve performance. Unfortunately, most DOS programs used 
  1376. some type of shortcut to improve performance and make up for the relatively 
  1377. slow 8088 processor they were originally written for. 
  1378.  
  1379.  
  1380. ΓòÉΓòÉΓòÉ 7.2. Processes and Threads ΓòÉΓòÉΓòÉ
  1381.  
  1382. OS/2 introduced the notion of threads. A thread is defined as an instance of 
  1383. execution or path of execution through a piece of code. OS/2's multitasking is 
  1384. thread-based. A program always has at least one thread, called the main thread, 
  1385. and may have many more threads, each executing at the same time. (see Figure 
  1386. 4-1). The additional threads are created by the main thread, and act as smaller 
  1387. "children" of the main thread. Threads inherit the environment of their 
  1388. creator, usually a process, and can be started or suspended by the main thread. 
  1389. A thread can only be destroyed by committing suicide. 
  1390.  
  1391. To aid in multitasking, OS/2 offers four classes of priorities (see Table 4-1). 
  1392. They are Real-Time-Critical, Normal, Fixed-High, and Idle-Time. Real-Time- 
  1393. Critical is the highest priority, while Idle-Time is the lowest. Within each 
  1394. priority class, there are 32 separate and distinct priorities, numbered from 0 
  1395. to 31. Most applications will run in the Normal mode, while time critical 
  1396. applications (such as a cardiac monitor) might run in the Real-Time-Critical 
  1397. class. The Fixed-High mode operates between Real-Time-Critical and Normal 
  1398. modes, and offers real time response but at priorities that can be dynamically 
  1399. modified by OS/2. The Idle-Time priority is reserved for slower background 
  1400. programs such as spoolers. 
  1401.  
  1402. Figure 4-1. Process and threads 
  1403.  
  1404.  
  1405. One of OS/2's major advantages is its time-sliced, priority-based preemptive
  1406. scheduler. This feature allows a critical or higher priority thread to preempt a
  1407. currently running thread. This preemptive feature is what sets OS/2 apart from
  1408. other multitasking systems such as UNIX. OS/2 runs the highest priority thread
  1409. until it completes or gives up the CPU by blocking on an I/O request or system
  1410. service. If a thread is currently executing and a higher priority thread needs to
  1411. run, the lower priority thread will be preempted and the higher priority thread
  1412. allowed to run. When the higher priority thread finishes or blocks waiting on a
  1413. system service, the lower priority thread will get a chance to run again. If two
  1414. threads with the same priority are competing for the CPU, each thread will
  1415. alternate for one time slice worth of time.
  1416.  
  1417. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1418. ΓöéPriority          ΓöéUse               ΓöéModified by OS/2  Γöé
  1419. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1420. ΓöéIdle              ΓöéSpoolers, batch   ΓöéYes               Γöé
  1421. Γöé                  Γöéprocessors        Γöé                  Γöé
  1422. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1423. ΓöéRegular           ΓöéNormal            ΓöéYes               Γöé
  1424. Γöé                  Γöéapplications      Γöé                  Γöé
  1425. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1426. ΓöéFixed-High        ΓöéSpecial           ΓöéYes               Γöé
  1427. Γöé(Foreground       Γöéapplications      Γöé                  Γöé
  1428. ΓöéServer)           Γöé                  Γöé                  Γöé
  1429. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1430. ΓöéReal-Time-CriticalΓöéReal-time         ΓöéNo                Γöé
  1431. Γöé                  Γöéapplications      Γöé                  Γöé
  1432. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1433. Table 4-1. OS/2 Priority Structure 
  1434.  
  1435. Most UNIX systems do not use threads, so priorities in a UNIX system are per 
  1436. process-based, rather than thread-based. Since most UNIX kernels are not 
  1437. preemptive, a UNIX application will run until it blocks on I/O or system 
  1438. resource, or exhausts its time slice. Currently running processes cannot be 
  1439. preempted, thus a critical program needing CPU time has to wait until the CPU 
  1440. is free. The UNIX scheduler is a round-robin scheduler, that is, the system 
  1441. allocates equal time to every process in a round-robin fashion. If three 
  1442. processes are running, process A gets a time slice, process B gets a time 
  1443. slice, then process C gets a time slice, and then the whole operation begins 
  1444. again with process A. 
  1445.  
  1446.  
  1447. ΓòÉΓòÉΓòÉ 7.3. OS/2 1.0 - OS/2 Arrives ΓòÉΓòÉΓòÉ
  1448.  
  1449. OS/2 1.0 was introduced in the fourth quarter of 1987. The first release did 
  1450. not contain a graphical user interface, but instead contained two side-by-side 
  1451. list boxes with names of programs to execute. The Application Programming 
  1452. Interface, or API, was incomplete and unstable. Device  support was virtually 
  1453. nonexistent, and OS/2 1.0 was only guaranteed to run on the IBM PC AT and IBM 
  1454. PS/2 line of computers. Many DOS applications did not run in the DOS 
  1455. compatibility box, and only a few thousand copies of OS/2 1.0 were sold. 
  1456.  
  1457.  
  1458. ΓòÉΓòÉΓòÉ 7.4. OS/2 1.1 - Presentation Manager Arrives ΓòÉΓòÉΓòÉ
  1459.  
  1460. The next major release of OS/2 contained the graphical user interface, dubbed 
  1461. Presentation Manager. OS/2 was beginning to take shape. It contained a better 
  1462. DOS compatibility box, which caused fewer DOS programs to crash, and had a 
  1463. consistent, more bug-free set of API routines. Documentation, in the form of 
  1464. manuals and books, was beginning to appear, and a few more DOS applications 
  1465. were recompiled and relinked under OS/2. None of these programs used the 
  1466. Presentation Manager, as they were not redesigned for OS/2. As a result, the 
  1467. applications were dull, character-based programs that didn't take advantage of 
  1468. any of OS/2's multitasking abilities or Presentation Manager. The lack of 
  1469. applications, together with the cost of a hardware upgrade, kept most users 
  1470. away from OS/2. 
  1471.  
  1472.  
  1473. ΓòÉΓòÉΓòÉ 7.5. OS/2 1.2 - A Better File System ΓòÉΓòÉΓòÉ
  1474.  
  1475. OS/2 had been using the file system known as FAT, named after the DOS File 
  1476. Allocation Table. The FAT was where DOS (and OS/2) kept a running "picture" of 
  1477. the hard disk, including the utilization and amount of free space. The DOS FAT 
  1478. file system was limited by design to filenames with a maximum length of 11 
  1479. characters, and  was inefficient in storing and retrieving files. The High 
  1480. Performance File System, or HPFS, was introduced in OS/2 1.2 to provide more 
  1481. efficient handling of large files and volumes, and to remove the 11-character 
  1482. filename restriction. HPFS can handle filenames with up to 254 characters, 
  1483. files as large as two gigabytes, and provides a very fast searching algorithm 
  1484. for storing and locating files. Unlike the FAT file system, HPFS is an 
  1485. installable file system, and a special device driver must be loaded before 
  1486. using it. 
  1487.  
  1488. The DOS compatibility box was improved, but OS/2 still could not run many DOS 
  1489. applications. This was due, in part, to the fact that the compatibility box did 
  1490. not offer the full amount of memory usually available to DOS applications. The 
  1491. size of the DOS compatibility box memory was reduced when device drivers were 
  1492. loaded, and often would only offer 500K bytes or less for running DOS programs. 
  1493. OS/2 was used primarily by companies that had real-time multitasking 
  1494. requirements for their systems, but not for running DOS applications. For DOS 
  1495. applications which would not run in the OS/2 1.2 compatibility box, OS/2 had a 
  1496. built-in dual-boot facility which allowed the user to selectively boot up DOS 
  1497. or OS/2. While OS/2 was running, however, the compatibility box was virtually 
  1498. useless. 
  1499.  
  1500. Printers did not work correctly. OS/2 did not work with the most popular laser 
  1501. printers, such as the Hewlett Packard Laserjets. The future of OS/2 was bleak. 
  1502.  
  1503. When Microsoft announced that they would be abandoning OS/2 in favor of Windows 
  1504. 3.0, OS/2 faced an uncertain future. Microsoft had been stating that OS/2 was 
  1505. the PC operating system platform of the future, and now had reversed that 
  1506. statement. Many large companies had previously begun conversion of their 
  1507. flagship programs, such as Lotus 1-2-3, to run under OS/2, and were taken by 
  1508. surprise by Microsoft's change in direction. IBM was forced to take over the 
  1509. development of OS/2, and Microsoft could free up its programming resources to 
  1510. concentrate on Windows software. Microsoft and IBM did agree to cross-license 
  1511. each other's products, and together they agreed that IBM would assume complete 
  1512. responsibility for OS/2. 
  1513.  
  1514.  
  1515. ΓòÉΓòÉΓòÉ 7.6. OS/2 1.3 - IBM's First Solo Effort ΓòÉΓòÉΓòÉ
  1516.  
  1517. Although OS/2 1.0, 1.1, and 1.2 were developed jointly by IBM and Microsoft, 
  1518. OS/2 Version 1.3 (dubbed OS/2 Lite) was the first version of OS/2 to be done 
  1519. entirely by IBM. It took IBM a while to get up to speed with OS/2, but when 
  1520. OS/2 1.3 was released, many features that had never worked correctly had been 
  1521. fixed.  Version 1.3 had better networking, communications, and graphics support 
  1522. and could finally print correctly.  The OS/2 kernel was slimmed down and ran 
  1523. considerably faster than its predecessors.  IBM produced detailed documentation 
  1524. and began to actively support developers through the IBM Developer's Assistance 
  1525. Program. However, OS/2 was used primarily by IBM installations for their 
  1526. PC-to-mainframe connection, and by OEMs for specialized applications. 
  1527.  
  1528. IBM was still not actively marketing OS/2. Information was difficult to come 
  1529. by, and it was almost impossible to buy OS/2. Most IBM dealers didn't even know 
  1530. what OS/2 was, or how to order it. IBM failed to inform their resellers how to 
  1531. demonstrate and sell OS/2. OS/2 was going nowhere fast. 
  1532.  
  1533.  
  1534. ΓòÉΓòÉΓòÉ 7.7. OS/2 2.0- What OS/2 Was Really Meant to Be ΓòÉΓòÉΓòÉ
  1535.  
  1536. Before deciding to scrap its OS/2 development, Microsoft had been working on a 
  1537. new version of OS/2, called OS/2 2.0. Microsoft first displayed early running 
  1538. versions of OS/2 2.0 in the middle of 1990, and had released the infamous 
  1539. System Developer's Kit, or SDK, with a whopping $2600 price tag. The OS/2 2.0 
  1540. SDK included early releases of the OS/2 kernel, 32-bit compiler, assembler, and 
  1541. linker. Many developers, however, balked at the price. The software contained 
  1542. several serious bugs, and for most developers, proved to be unusable. 
  1543.  
  1544. IBM realized that, unless it made a radical change in the way OS/2 was designed 
  1545. and marketed, OS/2 would eventually become a proprietary internal operating 
  1546. system used only by IBM. IBM formed a team to assume the development 
  1547. responsibilities of OS/2 2.0. They mounted an enormous effort, and the 
  1548. commercial release of OS/2 2.0 was the culmination of that effort. 
  1549.  
  1550. OS/2 2.1 represents a new direction for personal computer operating 
  1551. environments. Instead of having to deal with the 16-bit architecture of the 
  1552. 80286 processors, OS/2 2.1 was developed around the 32-bit architecture of the 
  1553. 80386 microprocessor. OS/2 2.1 will not run on an 80286 processor-based 
  1554. machine. This decision comes at a time when the 16-bit 80286 machines are 
  1555. obsolete, and the standard choice for personal computers is an 80486 machine 
  1556. with 8MB of RAM as a minimum configuration. With memory prices at $35 per 
  1557. megabyte of RAM, memory configurations of 8 and 16MB are becoming commonplace. 
  1558. Hard disk storage has decreased significantly in price, and most systems are 
  1559. sold with 100MB or more of disk storage as minimum. 
  1560.  
  1561. OS/2 2.1 allows DOS programs to run in their own one megabyte of memory space 
  1562. without knowledge of other programs in the system. Even the most ill- behaved 
  1563. DOS applications, such as games, run flawlessly in their own protected area. In 
  1564. addition, users can boot any version of DOS they choose into a DOS session. The 
  1565. number of DOS sessions that can be started is unlimited in OS/2 2.1. DOS 
  1566. programs have access to 48MB of extended memory. OS/2 2.1 also supports DOS 
  1567. programs designed to use the DOS Protect Mode Interface, or DPMI Version 0.9. 
  1568. OS/2 2.1 runs Windows 3.0 and 3.1 applications in the real or standard mode. 
  1569. OS/2 2.1 allows Dynamic Data Exchange, or DDE, between DOS/Windows and OS/2 
  1570. applications, providing up to 512MB of DPMI memory per DOS session. 
  1571.  
  1572. OS/2 2.1 uses a desktop metaphor called the Workplace Shell for its user 
  1573. interface. The Workplace Shell represents an actual desktop using icons 
  1574. representing the actual items the user might find on his or her desk. It 
  1575. contains such items as a file folder, printer, network connection, and other 
  1576. icons that reflect the current configuration of the system. Printing a 
  1577. document, for example, is as simple as opening a folder, clicking on the 
  1578. document and dragging it over to the printer icon. 
  1579.  
  1580. OS/2 2.1 represents a common platform for supporting many different types of 
  1581. applications. It runs DOS applications, Windows 3.0 and 3.1 applications and, 
  1582. of course, native OS/2 applications, all seamlessly. There is no longer a need 
  1583. to dual-boot DOS or to load three different operating environments; OS/2 2.1 
  1584. runs them all. 
  1585.  
  1586.  
  1587. ΓòÉΓòÉΓòÉ 7.8. The OS/2 Application Programming Interface ΓòÉΓòÉΓòÉ
  1588.  
  1589. OS/2 2.1 offers a rich set of Application Program Interfaces (APIs) to allow 
  1590. programs to access system services. The OS/2 APIs are classified into eight 
  1591. major categories. They are: 
  1592.  
  1593. 1. File System
  1594.   File Systems (FAT, Super FAT, HPFS)
  1595.   Network Access (LAN Server, NetBIOS)
  1596.   Permissions
  1597.   DASD Media Management
  1598.  
  1599. 2. Graphics Interface
  1600.   Graphics Programming Interface
  1601.   Video Input and Output
  1602.  
  1603. 3. Inter Process Communications
  1604.   Shared Memory
  1605.   Semaphores
  1606.   Named Pipes
  1607.   Queues
  1608.   Dynamic Data Exchange (DDE)
  1609.  
  1610. 4. System Services
  1611.   Device Monitors
  1612.   Timer Services
  1613.  
  1614. 5. Process Management
  1615.   Threads
  1616.   Processes
  1617.   Child Processes
  1618.   Scheduler/Priorities
  1619.  
  1620. 6. Memory Management
  1621.  
  1622. 7. Signals
  1623.  
  1624. 8. Dynamic Linking
  1625.  
  1626.  
  1627. ΓòÉΓòÉΓòÉ 8. Chapter 5 - The Anatomy of an OS/2 Device Driver ΓòÉΓòÉΓòÉ
  1628.  
  1629. OS/2 device drivers, like other multitasking device drivers, shield the 
  1630. application code that performs I/O from device-specific hardware requirements. 
  1631. The application program need not concern itself with the physical constraints 
  1632. of a particular I/O device, such as timing or I/O port addressing, as these are 
  1633. handled entirely by the device driver. If an I/O card address is moved or a 
  1634. different interrupt selected, the device driver can be recompiled (notice I did 
  1635. not say reassembled) without modifying or recompiling the application code. 
  1636.  
  1637. It should be noted that OS/2 device drivers can be configured during boot-up 
  1638. operation by placing adapter-specific parameters in the DEVICE= entry in 
  1639. CONFIG.SYS. The driver can retrieve the parameters and configure itself during 
  1640. the INIT section. 
  1641.  
  1642. Conceptually, OS/2 device drivers are similar to device drivers in other 
  1643. multitasking systems, but they have the added responsibility of handling 
  1644. processor-specific anomalies such as the segmented architecture and operating 
  1645. modes of the Intel processors. 
  1646.  
  1647.  
  1648. ΓòÉΓòÉΓòÉ 8.1. Application-to-Driver Interface ΓòÉΓòÉΓòÉ
  1649.  
  1650. OS/2 device drivers are called by the kernel on behalf of the application 
  1651. needing I/O service. The application program makes an I/O request call to the 
  1652. kernel, specifying the type of operation needed. The kernel verifies the 
  1653. request, translates the request into a valid device driver Request Packet and 
  1654. calls the device driver for service. The device driver handles all of the 
  1655. hardware details, such as register setup, interrupt handling, and error 
  1656. checking. When the request is complete, the device driver massages the data 
  1657. into a format recognizable by the application. It sends the data or status to 
  1658. the application and notifies the kernel that the request is complete. If the 
  1659. request cannot be handled immediately, the device driver may either block the 
  1660. requesting thread or return a 'request not done' to the kernel. Either method 
  1661. causes the device driver to relinquish the CPU, allowing other threads to run. 
  1662. If an error is detected, the device driver returns this information to the 
  1663. kernel with a 'request complete' status. The OS/2 device driver may also "queue 
  1664. up" requests to be handled later in a work queue. The OS/2 Device Helper 
  1665. (DevHlp) library contains several DevHlps for manipulating the device driver's 
  1666. work queue. 
  1667.  
  1668.  
  1669. ΓòÉΓòÉΓòÉ 8.2. DOS Device Drivers and OS/2 Device Drivers ΓòÉΓòÉΓòÉ
  1670.  
  1671. DOS device drivers have no direct OS/2 counterpart. DOS device drivers are 
  1672. simple, single-task, polling device drivers. Even interrupt device drivers 
  1673. under DOS poll until interrupt processing is complete. DOS device drivers 
  1674. support only one request at a time, and simultaneous multiple requests from DOS 
  1675. will cause the system to crash. 
  1676.  
  1677. While the DOS device driver is a single-threaded polled routine, the OS/2 
  1678. device driver must handle overlapping requests from different processes and 
  1679. threads. Because of this, the OS/2 device driver must be reentrant. The OS/2 
  1680. device driver must also handle interrupts from the device and optionally from a 
  1681. timer handler. It must handle these operations in an efficient manner, allowing 
  1682. other threads to gain access to the CPU. Most importantly, it must do all of 
  1683. these reliably. The OS/2 device driver, because it operates at Ring 0, is the 
  1684. only program that has direct access to critical system functions, such as the 
  1685. interrupt system and system timer. The device driver, therefore, must be 
  1686. absolutely bug- free, as any error in the device driver will cause a fatal 
  1687. system crash. 
  1688.  
  1689. OS/2 2.1 device drivers no longer have to deal with the real-protect mode 
  1690. switching of OS/2 1.x, as all programs run in protect mode. OS/2 device drivers 
  1691. must have the capability to deinstall when requested, releasing any memory used 
  1692. by the device driver to the OS/2 kernel. OS/2 device drivers may also support 
  1693. device monitors, programs that wish to monitor data as it is passed to and from 
  1694. the device driver. OS/2 offers a wide range of device driver services to 
  1695. provide this functionality. 
  1696.  
  1697.  
  1698. ΓòÉΓòÉΓòÉ 8.3. Designing an OS/2 Device Driver ΓòÉΓòÉΓòÉ
  1699.  
  1700. Designing an OS/2 device driver requires a thorough understanding of the role 
  1701. of a device driver, as well as a solid working knowledge of the OS/2 operating 
  1702. system and design philosophy. Debugging OS/2 device drivers can be difficult, 
  1703. even with the proper tools. The OS/2 device driver operates at Ring 0 with full 
  1704. access to the system hardware. However, it has almost no access to OS/2 support 
  1705. services, except for a handful of DevHlp routines. Many device driver failures 
  1706. occur in a real time context, such as in the midst of interrupt handling. It 
  1707. may be difficult or impossible to find a device driver problem using normal 
  1708. debugging techniques. In such cases, it is necessary to visualize the operation 
  1709. of the device driver and OS/2 at the time of the error to help locate the 
  1710. problem. 
  1711.  
  1712.  
  1713. ΓòÉΓòÉΓòÉ 8.4. Tools Necessary For Driver Development ΓòÉΓòÉΓòÉ
  1714.  
  1715. One of the most important tools for device driver development is the device 
  1716. driver debugger. Generally, the best choice is the OS/2 2.1 kernel debugger or 
  1717. KDB. KDB uses a standard ASCII terminal attached to one of the serial COM ports 
  1718. via a null-modem cable. When OS/2 is started, KDB looks for a COM port to 
  1719. perform its I/O to the debugging terminal. For systems with only one COM port, 
  1720. KDB will use COM1. For systems with two COM ports, KDB will use COM2. 
  1721.  
  1722. The KDB is not simply a debugger, but is a replacement kernel that replaces the 
  1723. OS/2 standard system kernel called OS2KRNL. KDB has knowledge of internal OS/2 
  1724. data structures and provides a powerful command set for debugging OS/2 device 
  1725. drivers. Installing the debugging kernel is easy. The attributes of the hidden 
  1726. file OS2KRNL are changed to non-hidden and non-system, and the file is copied 
  1727. to OS2KRNL.OLD. The debug kernel is then copied to OS2KRNL, and OS/2 is 
  1728. rebooted. KDB will issue a sign-on message to the debugging terminal indicating 
  1729. that it is active. KDB can be entered by typing <cntl-c> on the debug terminal, 
  1730. or if KDB encounters an INT 3 instruction. These procedures are described in 
  1731. more detail in Chapter 13. The kernel debugger comes with the IBM OS/2 2.1 
  1732. Toolkit, and is installed easily with the installation program supplied with 
  1733. the Toolkit. 
  1734.  
  1735.  
  1736. ΓòÉΓòÉΓòÉ 8.5. The Basics of Driver Design ΓòÉΓòÉΓòÉ
  1737.  
  1738. The device driver receives two basic types of requests: requests that can be 
  1739. completed immediately and those that cannot (see Figure 5-1). It receives these 
  1740. requests via a standard data structure called a Request Packet (see Example 
  1741. 5-1). 
  1742.  
  1743. Requests that can be completed immediately are handled as they come in, and 
  1744. sent back to the requestor. Requests that cannot be handled immediately (such 
  1745. as disk seeks) are queued up for later dispatch by the device driver. The 
  1746. device driver manipulates Request Packets using the DevHlp routines. To 
  1747. minimize head movement, disk device drivers usually sort pending requests for 
  1748. disk seeks in sector order. 
  1749.  
  1750. The OS/2 device driver plays an additional role in system performance and 
  1751. operation. When a device driver is called to perform a request that cannot be 
  1752. completed immediately, the device driver Blocks the requesting thread. This 
  1753. relinquishes the CPU and allows other threads to run. When the request is 
  1754. complete, usually as the result of an interrupt or error occurring, the thread 
  1755. is immediately UnBlocked and Run. The device driver then queries the request 
  1756. queue for any pending requests that may have come in while the thread was 
  1757. blocked. It is important to note that when an application calls a device 
  1758. driver, the application program's LDT is directly accessible by the device 
  1759. driver. Figure 5-1. Application-to-device driver interface 
  1760.  
  1761.  
  1762. ΓòÉΓòÉΓòÉ 8.6. Request Packets ΓòÉΓòÉΓòÉ
  1763.  
  1764. The first entry in the Request Packet Header (see Example 5-1)  is the Request 
  1765. Packet length, filled in by the kernel.  The second parameter is the unit code. 
  1766. Applicable for block devices only, this field should be set by the device 
  1767. driver writer to zero for the first unit, one for the second, etc. The third 
  1768. field is the command code.  The command code is filled in by the kernel.  This 
  1769. is the code used by the switch routine in the Strategy section to decode the 
  1770. type of request from the kernel.  The next field is the status word returned to 
  1771. the kernel.  This field will contain the result of the device driver operation, 
  1772. along with the 'DONE' bit to notify the kernel that the request is complete 
  1773. (this is not always the case; the device driver may return without the 'done' 
  1774. bit set).  To make things easier, a C language union should be used to access 
  1775. specific types of requests.  The Request Packet structures are placed in an 
  1776. include file, which is included by the device driver mainline.  Refer to the 
  1777. Standard OS/2 Device Driver Include File in Appendix C. 
  1778.  
  1779. typedef struct ReqPacket {
  1780.    UCHAR   RPlength;             // Request Packet length
  1781.    UCHAR   RPunit;               // unit code for block DD only
  1782.    UCHAR   RPcommand;            // command code
  1783.    USHORT  RPstatus;             // status word
  1784.    UCHAR   RPreserved[4];        // reserved bytes
  1785.    ULONG   RPqlink;              // queue linkage
  1786.    UCHAR   avail[19];            // command specific data
  1787.    } REQPACKET;
  1788.  
  1789. Example 5-1. Request Packet. 
  1790.  
  1791.  
  1792. ΓòÉΓòÉΓòÉ 8.7. OS/2 Device Driver Architecture ΓòÉΓòÉΓòÉ
  1793.  
  1794. OS/2 device drivers come in two flavors, block and character. Block device 
  1795. drivers are used for mass storage devices such as disk and tape. Character 
  1796. device drivers are used for devices that handle data one character at a time, 
  1797. such as a modem. OS/2 device drivers are capable of supporting multiple 
  1798. devices, such as a serial communications adapter with four channels or a disk 
  1799. device driver which supports multiple drives. 
  1800.  
  1801. OS/2 device drivers receive requests from the OS/2 kernel on behalf of an 
  1802. application program thread. When the device driver is originally opened with a 
  1803. DosOpen API call, the kernel returns a handle to the thread that requested 
  1804. access to the device driver. This handle is used for subsequent access to the 
  1805. device driver. 
  1806.  
  1807. When an application makes a call to a device driver, the kernel intercepts the 
  1808. call and formats the device driver request into a standard Request Packet. The 
  1809. Request Packet contains data and pointers for use by the device driver to 
  1810. complete the request. In the case of a DosRead or DosWrite, for example, the 
  1811. Request Packet contains the verified and locked physical address of the 
  1812. caller's buffer. In the case of an IOCtl, the Request Packet contains the 
  1813. virtual address of a Data and Parameter Buffer. Depending on the type of 
  1814. request, the data in the Request Packet will change, but the Request Packet 
  1815. header length and format remain fixed. The kernel sends the Request Packet to 
  1816. the driver by passing it a 16:16 pointer to the Request Packet. 
  1817.  
  1818. Device drivers are loaded by the OS/2 loader at boot time, and the kernel keeps 
  1819. a linked list of the installed device drivers by name, using the link pointer 
  1820. in the Device Header. Before a device driver is used, it must be "DosOpen"ed 
  1821. from the application. The DosOpen specifies an ASCII-Z string with the device 
  1822. name as a parameter, which is the eight character ASCII name located in the 
  1823. Device Header. (see Example 5-2). The kernel compares this name with its list 
  1824. of installed device drivers, and if it finds a match, it calls the OPEN section 
  1825. of the device driver Strategy routine to open the device.  If the open was 
  1826. successful, the kernel returns to the application a handle to use for future 
  1827. device driver access.  The device handles are usually assigned sequentially, 
  1828. starting with 3 (0, 1, and 2 are claimed by OS/2).  However, the handle value 
  1829. should never be assumed. 
  1830.  
  1831. typedef struct DeviceHdr
  1832. {
  1833.    struct DeviceHdr far *DHnext; // ptr to next header, or FFFF
  1834.    USHORT DHattribute;           // device attribute word
  1835.    OFF    DHstrategy;            // offset of strategy routine
  1836.    OFF    DHidc;                 // offset of IDC routine
  1837.    UCHAR  DHname[8];             // dev name (char) or #units (blk)
  1838.    char   reserved[8];
  1839. } DEVICEHDR;
  1840.  
  1841.  
  1842. DEVICEHDR devhdr =
  1843. {
  1844.   (void far *) 0xFFFFFFFF,          // link
  1845.   (DAW_CHR | DAW_OPN | DAW_LEVEL1), // attribute
  1846.   (OFF) STRAT,                      // &strategy
  1847.   (OFF) 0,                          // &IDCroutine
  1848.   "DEVICE1 ",                       // device name
  1849. };
  1850.  
  1851. Example 5-2. OS/2 device driver header. 
  1852.  
  1853.  
  1854. ΓòÉΓòÉΓòÉ 8.8. Device Driver Modes ΓòÉΓòÉΓòÉ
  1855.  
  1856. OS/2 2.1 device drivers operate in three different modes. The first, INIT mode, 
  1857. is a special mode entered at system boot time and executed at Ring 3. When the 
  1858. OS/2 system loader encounters a "DEVICE=" statement in the CONFIG.SYS file on 
  1859. boot-up, it loads the device driver .SYS file and calls the INIT function of 
  1860. the device driver. What makes this mode special is that the boot procedure is 
  1861. running in Ring 3 which normally has no I/O privileges, yet OS/2 allows Ring 0- 
  1862. type operations. The device driver is free to do port I/O and even turn 
  1863. interrupts off, but must ensure they are back on before exiting the INIT 
  1864. routine. The INIT routine can be used to initialize a Universal Asynchronous 
  1865. Receiver Transmitter (UART) or anything else necessary to ready a device. 
  1866.  
  1867. Ring 3 operation during INIT is necessary to protect the integrity of code that 
  1868. has already been loaded up to that point, and to make sure that the device 
  1869. driver itself does not corrupt the operating system during initialization. Ring 
  1870. 3 operation also allows the device driver initialization routine to call a 
  1871. limited number of system API routines to aid in the initialization process. For 
  1872. example, a device driver might use the API routines to read a disk file that 
  1873. contains data to initialize an adapter. The device driver also uses the API 
  1874. routines to display driver error and sign-on messages. The INIT code is only 
  1875. called once, during system boot. For this reason, the INIT code is usually 
  1876. located at the end of the code segment so it can be discarded after 
  1877. initialization. 
  1878.  
  1879. The second mode, called Kernel mode, is in effect when the device driver is 
  1880. called by the kernel as a result of an I/O request. 
  1881.  
  1882. The third mode, called Interrupt mode, is in effect when the device driver's 
  1883. interrupt handler is executing in response to an external interrupt, such as a 
  1884. character being received from a serial port. 
  1885.  
  1886. In general, the OS/2 device driver consists of a Strategy section, an INIT 
  1887. section, and optional interrupt and timer sections. The Strategy section 
  1888. receives requests from the kernel, in the form of Request Packet. The Strategy 
  1889. section verifies the request, and if it can be completed immediately, completes 
  1890. the request and sends the result back to the kernel. If the request cannot be 
  1891. completed immediately, the device driver optionally queues up the request to be 
  1892. completed at a later time and starts the I/O operation, if necessary. The 
  1893. kernel calls the Strategy routine directly by finding its offset address in the 
  1894. Device Header. 
  1895.  
  1896.  
  1897. ΓòÉΓòÉΓòÉ 8.9. The Device Header ΓòÉΓòÉΓòÉ
  1898.  
  1899. A simple OS/2 device driver consists of at least one code segment and one data 
  1900. segment, although more memory can be allocated if necessary. The first item of 
  1901. data that appears in the data segment must be the device driver header. The 
  1902. device driver header is a fixed length, linked list structure that contains 
  1903. information for use by the kernel during INIT and normal operation. 
  1904.  
  1905. The first entry in the header is a link pointer to the next device that the 
  1906. device driver supports. If no other devices are supported, the pointer is set 
  1907. to - 1L. A - 1L terminates the list of devices supported by this device driver. 
  1908. If the device driver supports multiple devices, such as a four-port serial 
  1909. board or multiple disk controller, the link is a far pointer to the next device 
  1910. header. When OS/2 loads device drivers at INIT time, it forms a linked list of 
  1911. all device driver device headers. The last device driver header will have a 
  1912. link address of -1L. When a DEVICE= statement is found in CONFIG.SYS, the last 
  1913. loaded device driver's link pointer is set to point to the new device driver's 
  1914. device header, and the new device driver's link pointer now terminates the 
  1915. list. 
  1916.  
  1917. The next entry in the device header is the Device Attribute Word (see Table 5- 
  1918. 1). The Device Attribute Word is used to define the operational characteristics 
  1919. of the device driver. 
  1920.  
  1921. The next entry is a one word offset to the device driver Strategy routine. Only 
  1922. the offset is necessary, because the device driver is written in the small 
  1923. model with a 64K code segment and a 64K data segment (this is not always 
  1924. true-in special cases, the device driver can allocate more code and data space 
  1925. if needed, and can even be written in the large model). 
  1926.  
  1927. DEVICEHDR devhdr[2] =
  1928. {
  1929.  { (void far *) &devhdr[1],    // link to next dev
  1930.  (DAW_CHR | DAW_OPN | DAW_LEVEL1), // attribute
  1931.  (OFF) STRAT1,                     // &strategy
  1932.  (OFF) 0,                          // &IDCroutine
  1933.  "DEVICE1 ",
  1934.  },
  1935.  
  1936.  {(void far *) 0xFFFFFFFF,         // link(no more devs)
  1937.  (DAW_CHR | DAW_OPN | DAW_LEVEL1), // attribute
  1938.  (OFF) STRAT2,                     // &strategy
  1939.  (OFF) 0,                          // &IDCroutine
  1940.  "DEVICE2 ",
  1941.   }
  1942. };
  1943.  
  1944. Example 5-3. Device driver header, multiple devices. 
  1945.  
  1946. The next entry is an offset address to an IDC routine, if the device driver 
  1947. supports inter-device driver communications. (The DAW_IDC bit in the device 
  1948. attribute word must also be set, otherwise the AttachDD call from the other 
  1949. device driver will fail.) The last field is the device name, which must be 
  1950. eight characters in length. Names with less than eight characters must be 
  1951. space- padded. Remember, any mistake in coding the device driver header will 
  1952. cause an immediate crash and burn when booting. 
  1953.  
  1954. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1955. ΓöéBit(s)ΓöéDescription                             Γöé
  1956. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1957. Γöé15    Γöéset if character driver, 0 if block     Γöé
  1958. Γöé      Γöédriver                                  Γöé
  1959. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1960. Γöé14    Γöéset if driver supports inter-device     Γöé
  1961. Γöé      Γöécommunications (IDC)                    Γöé
  1962. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1963. Γöé13    Γöéfor block drivers, set if non-IBM       Γöé
  1964. Γöé      Γöéformat, for character drivers, set if   Γöé
  1965. Γöé      Γöédriver supports output-until-busy       Γöé
  1966. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1967. Γöé12    Γöéif set, device supports sharing         Γöé
  1968. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1969. Γöé11    Γöéset. if block device, supports removableΓöé
  1970. Γöé      Γöémedia, if character device, supports    Γöé
  1971. Γöé      Γöédevice open/close                       Γöé
  1972. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1973. Γöé10    Γöéreserved, must be 0                     Γöé
  1974. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1975. Γöé9-7   Γöédriver function level                   Γöé
  1976. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1977. Γöé      Γöé001 = OS/2 device driver                Γöé
  1978. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1979. Γöé      Γöé010 = supports DosDevIOCtl2 and ShutdownΓöé
  1980. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1981. Γöé      Γöé011 = capabilites bit strip in device   Γöé
  1982. Γöé      Γöéheader                                  Γöé
  1983. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1984. Γöé6     Γöéreserved, must be 0                     Γöé
  1985. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1986. Γöé5     Γöéreserved, must be 0                     Γöé
  1987. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1988. Γöé4     Γöéreserved, must be 0                     Γöé
  1989. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1990. Γöé3     Γöéset if this is the CLOCK device         Γöé
  1991. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1992. Γöé2     Γöéset if this is a NUL device (character  Γöé
  1993. Γöé      Γöédriver only)                            Γöé
  1994. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1995. Γöé1     Γöéset if this is the new stdout device    Γöé
  1996. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1997. Γöé0     Γöéset if this is the new stdin device     Γöé
  1998. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1999. Table 5-1. Device Attribute Word 
  2000.  
  2001.  
  2002. ΓòÉΓòÉΓòÉ 8.10. Capabilities Bit Strip ΓòÉΓòÉΓòÉ
  2003.  
  2004. The Capabilities Bit Strip word defines additional features supported on level 
  2005. 3 drivers only (see Table 5-2). 
  2006.  
  2007. Note that if the device driver is an ADD device driver, and sets bit 7 and 8 in 
  2008. the device attribute word as well as bit 3 in the capabilities bit strip, the 
  2009. Init request packet sent by the kernel will be formatted differently than the 
  2010. standard PDD Init request packet. Refer to the appropriate ADD documentation 
  2011. for a description of the ADD Init request packet format. 
  2012.  
  2013. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  2014. ΓöéBit(s)ΓöéDescription                             Γöé
  2015. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2016. Γöé0     Γöéset if driver supports DosDevIOCtl2     Γöé
  2017. Γöé      Γöépackets and has Shutdown support        Γöé
  2018. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2019. Γöé1     Γöéfor character drivers, set if driver    Γöé
  2020. Γöé      Γöésupports 32-bit memory addressing, for  Γöé
  2021. Γöé      Γöéblock drivers, this bit must be 0       Γöé
  2022. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2023. Γöé2     Γöéif set, the device driver supports      Γöé
  2024. Γöé      Γöéparallel ports                          Γöé
  2025. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2026. Γöé3     Γöéif set, the device driver is an ADD     Γöé
  2027. Γöé      Γöédriver                                  Γöé
  2028. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2029. Γöé4     Γöéif set, kernel will issue the           Γöé
  2030. Γöé      ΓöéCmdInitComplete strategy command        Γöé
  2031. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2032. Γöé5-31  Γöéreserved, must be 0                     Γöé
  2033. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  2034. Table 5-2. Capabilities Bit Strip 
  2035.  
  2036.  
  2037. ΓòÉΓòÉΓòÉ 8.11. Providing a Low-Level Interface ΓòÉΓòÉΓòÉ
  2038.  
  2039. The data segment, which contains the Device Header, must appear as the very 
  2040. first data item. No data items or code can be placed before the Device Header. 
  2041. An OS/2 device driver which does not adhere to this rule will not load. Since 
  2042. our OS/2 device drivers are written in C, a mechanism must be provided for 
  2043. putting the code and data segments in the proper order, as well as providing a 
  2044. low-level interface to handle device and timer interrupts. Since the Device 
  2045. Header must be the first item that appears in the data segment, the C compiler 
  2046. must be prevented from inserting the normal C start-up code before the Device 
  2047. Header. Additionally, a method of detecting which device is being requested 
  2048. needs to be provided for device drivers that support multiple devices. 
  2049.  
  2050. These requirements are handled with a small assembly language stub that is 
  2051. linked in with the device driver (refer to Example 5-4). The __acrtused entry 
  2052. point prevents the C start-up code from being inserted before the device driver 
  2053. data segment.  The segment-ordering directives ensure that the data segment 
  2054. precedes the code segment. 
  2055.  
  2056. ;
  2057. ;    C start-up routine, one device
  2058. ;
  2059.             EXTRN _main:near
  2060.             PUBLIC _STRAT
  2061.             PUBLIC __acrtused
  2062.  
  2063. _DATA       segment word public 'DATA'
  2064. _DATA       ends
  2065.  
  2066. CONST       segment word public 'CONST'
  2067. CONST       ends
  2068.  
  2069. _BSS        segment word public 'BSS'
  2070. _BSS        ends
  2071.  
  2072. DGROUP      group CONST,_BSS,_DATA
  2073.  
  2074. _TEXT       segment word public 'CODE'
  2075.             assume cs:_TEXT,ds:DGROUP,es:NOTHING,ss:NOTHING
  2076.             .286P
  2077. ;
  2078. _STRAT      proc far
  2079. __acrtused:          ;no start-up code
  2080. ;
  2081.      push   0
  2082.      jmp    start    ;signal device 0
  2083. ;
  2084. start:
  2085.      push   es       ;send Request Packet address
  2086.      push   bx
  2087.      call   _main    ;call driver mainline
  2088.      pop    bx       ;restore es:bx
  2089.      pop    es
  2090.      add    sp,2     ;clean up stack
  2091.      mov    word ptr es:[bx+3],ax ;send completion status
  2092.      ret
  2093. ;
  2094. _STRAT      endp
  2095. ;
  2096. _TEXT       ends
  2097.             end
  2098.  
  2099. Example 5-4. Start-up routine, one device. 
  2100.  
  2101. Note the _STRAT entry point. Remember that this is the address placed in the 
  2102. device driver's Device Header. The kernel, when making a request to the device 
  2103. driver, looks up this address in the Device Header and makes a far call to it. 
  2104. The assembly language routine then, in turn, calls the C mainline. Thus, the 
  2105. linkage from the kernel to the device driver is established. 
  2106.  
  2107. Note the "push 0" in the beginning of the _STRAT routine. This is to notify the 
  2108. device driver which device is being requested. Each device supported by the 
  2109. device driver requires its own separate Device Header. Note also that each 
  2110. Device Header contains an offset address to its own Strategy routine. Using the 
  2111. assembly language interface, the device number is pushed on the stack and 
  2112. passed to the device driver Strategy section for service. The device driver 
  2113. retrieves the parameter and determines which device was requested. One of the 
  2114. parameters to main is the int dev (see Example 5-7),  the device number that 
  2115. was passed from the assembly language start-up routine. The assembly language 
  2116. start-up routine is modified to support multiple devices by adding entry points 
  2117. for each device's Strategy section. The modified source for this routine is 
  2118. shown in Example 5-5. 
  2119.  
  2120. The assembly language routine in Example 5-6 provides the interrupt handler and 
  2121. timer handler entry points.  The interrupt handler entry point provides a 
  2122. convenient place to put a breakpoint before entering the C code of the main 
  2123. interrupt handler.  The timer handler entry point provides a place to save and 
  2124. restore the CPU registers.  Note that the interrupt handler does not need to 
  2125. save the register contents, as this is done by the OS/2 kernel.  The timer 
  2126. handler, however, must save and restore register contents. 
  2127.  
  2128. ;
  2129. ;    C start-up routine, 4 devices
  2130. ;
  2131.             EXTRN _main:near
  2132.             PUBLIC _STRAT1
  2133.             PUBLIC _STRAT2
  2134.             PUBLIC _STRAT3
  2135.             PUBLIC _STRAT4
  2136.             PUBLIC __acrtused
  2137.  
  2138. _DATA       segment word public 'DATA'
  2139. _DATA       ends
  2140.  
  2141. CONST       segment word public 'CONST'
  2142. CONST       ends
  2143.  
  2144. _BSS        segment word public 'BSS'
  2145. _BSS        ends
  2146.  
  2147. DGROUP      group CONST, _BSS, _DATA
  2148.  
  2149. _TEXT       segment word public 'CODE'
  2150.  
  2151.  assume     cs:_TEXT,ds:DGROUP,es:NOTHING,ss:NOTHING
  2152.             .286P
  2153. ;
  2154. _STRAT1     proc far
  2155. __acrtused:          ;satisfy EXTRN modules
  2156. ;
  2157.      push   0
  2158.      jmp    start    ;signal device 0
  2159. ;
  2160. _STRAT1     endp
  2161.  
  2162. _STRAT2 proc far
  2163. ;
  2164.      push   1        ;signal second device
  2165.      jmp    start
  2166. ;
  2167. _STRAT2     endp
  2168.  
  2169. _STRAT3     proc far
  2170. ;
  2171.      push   2        ;signal third device
  2172.      jmp    start
  2173. ;
  2174. _STRAT3 endp
  2175.  
  2176. _STRAT4 proc far
  2177. ;
  2178.      push   3        ;signal fourth device
  2179.      jmp    start
  2180. ;
  2181. start:
  2182.      push   es       ;send address
  2183.      push   bx
  2184.      call   _main    ;call driver mainline
  2185.      pop    bx       ;restore es:bx
  2186.      pop    es
  2187.      add    sp,2     ;clean up stack
  2188.      mov    word ptr es:[bx+3],ax ;send completion status
  2189.      ret
  2190. ;
  2191. _STRAT4     endp
  2192. ;
  2193. _TEXT       ends
  2194.             end
  2195.  
  2196. Example 5-5. Start-up routine, four devices. 
  2197.  
  2198. ;
  2199. ;    C start-up routine, one device, w/interrupt and timer
  2200. ;
  2201.             PUBLIC _STRAT
  2202.             PUBLIC __acrtused
  2203.             PUBLIC _INT_HNDLR
  2204.             PUBLIC _TIM_HNDLR
  2205.  
  2206.             EXTRN  _interrupt_handler:near
  2207.             EXTRN  _timer_handler:near
  2208.             EXTRN  _main:near
  2209.  
  2210. _DATA       segment word public 'DATA'
  2211. _DATA       ends
  2212.  
  2213. CONST       segment word public 'CONST'
  2214. CONST       ends
  2215.  
  2216. _BSS        segment word public 'BSS'
  2217. _BSS        ends
  2218.  
  2219. DGROUP      group CONST, _BSS, _DATA
  2220.  
  2221. _TEXT       segment word public 'CODE'
  2222.  
  2223.   assume    cs:_TEXT,ds:DGROUP,es:NOTHING, ss:NOTHING
  2224.             .286P
  2225. ;
  2226. _STRAT      proc far
  2227. __acrtused:          ; no start-up code
  2228. ;
  2229.      push   0
  2230.      jmp    start    ; signal device 0
  2231. ;
  2232. start:
  2233.      push   es       ;send Request Packet address
  2234.      push   bx
  2235.      call   _main    ;call driver mainline
  2236.      pop    bx       ;restore es:bx
  2237.      pop    es
  2238.      add    sp,2     ;clean up stack
  2239.      mov    word ptr es:[bx+3],ax ;send completion status
  2240.      ret
  2241. ;
  2242. _STRAT  endp
  2243. ;
  2244. _INT_HNDLR  proc far
  2245. ;
  2246.      call   _interrupt_handler ;handle interrupts
  2247.      ret                       ;bail out
  2248. ;
  2249. _INT_HNDLR  endp
  2250. ;
  2251. _TIM_HNDLR  proc far
  2252. ;
  2253.      pusha
  2254.      push   es
  2255.      push   ds
  2256.      call   _timer_handler
  2257.      pop    ds
  2258.      pop    es
  2259.      popa
  2260.      ret
  2261. ;
  2262. _TIM_HNDLR  endp
  2263. ;
  2264. _TEXT       ends
  2265.             end
  2266.  
  2267. Example 5-6. Start-up routine with timer and interrupt handler. 
  2268.  
  2269.  
  2270. ΓòÉΓòÉΓòÉ 8.12. The Strategy Section ΓòÉΓòÉΓòÉ
  2271.  
  2272. The Strategy section is nothing more than a big switch statement (see Example 
  2273. 5-7). Common device driver requests, such as DosWrite and DosRead, have 
  2274. predefined function codes assigned to them.  The device driver may elect to 
  2275. ignore any or all of these requests by returning a DONE status to the kernel. 
  2276. This tells the kernel that the request has been completed. The status returned 
  2277. to the kernel may optionally include error information that the kernel returns 
  2278. to the calling program. 
  2279.  
  2280. int main(PREQPACKET rp, int dev)
  2281. {
  2282.     switch(rp->RPcommand)
  2283.     {
  2284.     case RPINIT:          // 0x00
  2285.  
  2286.         // init called by kernel in protected mode
  2287.  
  2288.         return Init(rp);
  2289.  
  2290.     case RPREAD:          // 0x04
  2291.  
  2292.         return (RPDONE);
  2293.  
  2294.     case RPWRITE:         // 0x08
  2295.  
  2296.         return (RPDONE);
  2297.  
  2298.     case RPINPUT_FLUSH:   // 0x07
  2299.  
  2300.         return (RPDONE);
  2301.  
  2302.     case RPOUTPUT_FLUSH:  // 0x0b
  2303.  
  2304.         return (RPDONE);
  2305.  
  2306.     case RPOPEN:          // 0x0d
  2307.  
  2308.         return (RPDONE);
  2309.  
  2310.     case RPCLOSE:         // 0x0e
  2311.  
  2312.          return (RPDONE);
  2313.     case RPIOCTL:         // 0x10
  2314.  
  2315.         switch (rp->s.IOCtl.function)
  2316.         {
  2317.         case 0x00:        // our function def #1
  2318.  
  2319.             return (RPDONE);
  2320.  
  2321.         case 0x01:        // our function def #2
  2322.  
  2323.             return (RPDONE);
  2324.         }
  2325.  
  2326.     // deinstall request
  2327.  
  2328.     case RPDEINSTALL:     // 0x14
  2329.  
  2330.         return(RPDONE | RPERR | ERROR_BAD_COMMAND);
  2331.  
  2332.     // all other commands are flagged
  2333.  
  2334.     default:
  2335.         return(RPDONE | RPERR | ERROR_BAD_COMMAND);
  2336.  
  2337.     }
  2338. }
  2339.  
  2340. Example 5-7. Skeleton strategy section. 
  2341.  
  2342. Note, however, that in the case of one of the standard device driver functions, 
  2343. the kernel will re-map the error value returned from the device driver to one 
  2344. of the standard device driver return codes. 
  2345.  
  2346. If the device driver must return special error codes, it should use an IOCtl 
  2347. request. IOCtls are used for special types of operations, device 
  2348. driver-specific, which do not fit into the architecture of the standard device 
  2349. driver functions. An example might be such as port I/O or initialization of a 
  2350. UART. The IOCtl section of the device driver is called when the application 
  2351. issues a DosDevIOCtl call with the device driver's handle. Using IOCtls, the 
  2352. device driver can return specialized codes that might contain, for example, 
  2353. the contents of an I/O port or the status of the device. This flexibility 
  2354. allows the device driver writer to customize the device driver to fit any 
  2355. device. 
  2356.  
  2357. Examine the skeleton Strategy section in Example 5-7. Note the switch on the 
  2358. Request Packet command.  A number of standard device driver functions have 
  2359. command codes predefined in OS/2 (see Table 5-3).  It is up to the device 
  2360. driver writer to act upon or ignore any of the requests to the device driver. 
  2361.  
  2362. The Strategy section is entered when the kernel calls the device driver to 
  2363. perform a particular operation. Refer to Table 5-3. 
  2364.  
  2365. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  2366. ΓöéEvent             ΓöéStrategy section called Γöé
  2367. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2368. ΓöéDosOpen           ΓöéRPOPEN                  Γöé
  2369. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2370. ΓöéDosClose          ΓöéRPCLOSE                 Γöé
  2371. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2372. Γöéboot              ΓöéRPINIT                  Γöé
  2373. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2374. ΓöéDosDevIOCtl       ΓöéRPIOCTL                 Γöé
  2375. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2376. Γöé<cntl-C>          ΓöéRPCLOSE                 Γöé
  2377. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2378. Γöé<cntl-break>      ΓöéRPCLOSE                 Γöé
  2379. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2380. ΓöéDosRead           ΓöéRPREAD                  Γöé
  2381. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2382. ΓöéDosWrite          ΓöéRPWRITE                 Γöé
  2383. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  2384. Table 5-3. Device Driver Strategy Calls 
  2385.  
  2386.  
  2387. ΓòÉΓòÉΓòÉ 8.13. Initialization ΓòÉΓòÉΓòÉ
  2388.  
  2389. The first thing that must be done in the initialization section is to save the 
  2390. DevHlp entry point address, passed in the Request Packet. This is the only time 
  2391. that the address is made available to the device driver, and it must be saved 
  2392. in the device driver's data segment. The INIT code generally performs two other 
  2393. functions. First, it issues the sign-on message to the screen that the device 
  2394. driver is attempting to load. Second, it finds the address of the last data and 
  2395. last code item, and sends them back to OS/2. OS/2 uses the code and data offset 
  2396. values to size memory. Only the first code and data segment of the device 
  2397. driver is re-sized by OS/2, so it may be desirable to place the INIT code and 
  2398. data into another segment which is discarded after the device driver is loaded. 
  2399. If a device driver fails installation, it must send back zero offsets for its 
  2400. code and data segments so OS/2 can use the memory space that the device driver 
  2401. had occupied during installation. Depending on the type of driver, you may wish 
  2402. to use this section to initialize your device, hook an interrupt or start a 
  2403. timer. 
  2404.  
  2405. It should be noted that for Micro Channel and EISA bus systems which share 
  2406. interrupts, it is desirable to hook the interrupt in the OPEN section and 
  2407. release it in the CLOSE section. This allows other adapters which use the same 
  2408. interrupt to register for the interrupt without being refused. ISA bus 
  2409. interrupts should be hooked during INIT, since the driver should fail 
  2410. initialization if the interrupt cannot be given to the device driver. 
  2411.  
  2412. If the device driver supports multiple devices, it will contain a Device Header 
  2413. with an entry for each device, with the previous Device Header pointing to the 
  2414. next Device Header. The last Device Header will contain a -1L, which terminates 
  2415. the list. For each device, the OS/2 kernel will call the Strategy entry point 
  2416. to initialize the device. If the driver supports, for example, four serial 
  2417. ports that use a single interrupt level, only the last valid initialized device 
  2418. should hook the interrupt. This will prevent previously installed devices from 
  2419. generating interrupts before the initialization has been completed. The code 
  2420. and data segment values returned to OS/2 to size memory should be exactly the 
  2421. same each time the INIT section is called. 
  2422.  
  2423. During INIT, a limited number of API functions may be called by the device 
  2424. driver. This is possible because INIT runs as a single Ring 3 thread. Some of 
  2425. the APIs, especially those that perform file I/O, are especially helpful for 
  2426. initializing adapters using data that is resident in disk files. Refer to the 
  2427. INIT Strategy Command in Chapter 6 for a more detailed description of device 
  2428. driver initialization. 
  2429.  
  2430. The driver should allocate necessary resources during initialization, such as 
  2431. memory and GDT selectors. If the driver supports a memory mapped adapter, the 
  2432. physical adapter address may be mapped to a GDT selector. However, because INIT 
  2433. is performed as a Ring 3 thread, the GDT selector cannot be accessed during 
  2434. initialization. Any function which creates or uses a GDT selector during INIT, 
  2435. such as AttachDD, will not allow you to use that selector during INIT. This is 
  2436. because INIT is run at Ring 3, and does not have access to the GDT. 
  2437.  
  2438. With IBM PS/2s, the device driver should search the system for an adapter card 
  2439. with the correct ID and verify that it is configured correctly. The device 
  2440. driver may call special PS/2 Advance BIOS (ABIOS) routines (see Chapter 8) to 
  2441. verify the correct configuration of the adapter. 
  2442.  
  2443.  
  2444. ΓòÉΓòÉΓòÉ 8.14. A Common Strategy ΓòÉΓòÉΓòÉ
  2445.  
  2446. One of the most common techniques in OS/2 device driver design is for the 
  2447. Strategy section to request service from the device and wait for a device or 
  2448. timer interrupt to signal completion of the request. In this case, the Strategy 
  2449. section starts the I/O and issues a Block DevHlp call, which blocks the calling 
  2450. thread. When the device interrupt signals that the operation is done, the 
  2451. interrupt section Runs the blocked thread, completing the request. To protect 
  2452. against the request never being completed, such as with a down device, the 
  2453. Block call can contain a time-out parameter. If the timeout expires before the 
  2454. completion interrupt occurs, the Blocked thread is Run, allowing the Strategy 
  2455. section to send the proper error message back to the kernel. 
  2456.  
  2457. Another method of timing-out a device is the use of the SetTimer DevHlp 
  2458. routine. A timer handler can be hooked into the OS/2 system clock, and ticks 
  2459. counted down until a time-out occurs. The Blocked thread can then be Run by the 
  2460. timer handler. 
  2461.  
  2462. The number and type of commands supported by the Strategy section are up to the 
  2463. device driver writer. The device driver can process only the commands it needs 
  2464. to, and let the others simply pass through by sending a DONE status back to the 
  2465. kernel. Illegal function calls may optionally be trapped, and ERROR_BAD_COMMAND 
  2466. returned to the kernel. 
  2467.  
  2468. Note that the OS/2 kernel periodically issues special requests to the device 
  2469. driver which are not generated by the application which opened the driver. An 
  2470. example of this would be the 5-48 Code Page IOCtl which the kernel sends to 
  2471. every OS/2 device driver immediately following the open. 
  2472.  
  2473. If the application that opened the device driver fails or is aborted with a 
  2474. <cntl- c> or <cntl-break>, the device driver is UnBlocked by the kernel with an 
  2475. unusual wake-up return code. The driver must return ERROR_CHAR_CALL_INTERRUPTED 
  2476. to the kernel, which will in turn call the CLOSE section of the driver. 
  2477.  
  2478. In general, it's a good practice to trap all unsupported requests by returning 
  2479. the DONE and ERROR_BAD_COMMAND status to the kernel, but be aware you may have 
  2480. to make some exceptions for the unsolicited calls. 
  2481.  
  2482. In the simplest of device drivers, the Strategy section may only contain an 
  2483. OPEN, CLOSE, and READ or WRITE section. In a complicated device driver, such as 
  2484. a disk device driver, the Strategy section may contain over two dozen standard 
  2485. device driver functions and dozens of additional IOCtl calls. IOCtl calls are 
  2486. actually Strategy functions, but are broken down one step further to provide 
  2487. more detailed or device-specific operations (see Chapter 6). For instance, a 
  2488. device driver might send a list of parameters to be used in initializing an I/O 
  2489. port, and return the status of that initialization operation. This type of 
  2490. function would not be able to be done with one of the standard set of device 
  2491. driver function calls because it is so device-specific. The IOCtl, however, is 
  2492. well suited to this type of functionality. 
  2493.  
  2494.  
  2495. ΓòÉΓòÉΓòÉ 8.15. Interrupt Section ΓòÉΓòÉΓòÉ
  2496.  
  2497. The interrupt section handles interrupts from the device. Interrupts may be 
  2498. caused by a character having been received, a character finished transmitting, 
  2499. or any number of external events. Interrupt processing should be quick and 
  2500. straightforward. The routine that handles the interrupt is appropriately called 
  2501. the interrupt handler. The interrupt handler is a subroutine that is entered 
  2502. upon the receipt of an interrupt for the IRQ level registered with the SetIRQ 
  2503. DevHlp call. All interrupts in OS/2 are handled by the kernel. With DOS, all a 
  2504. program had to do was to hook the interrupt vector that it wanted. OS/2, 
  2505. however, does not allow interrupt vectors to be changed, and if an attempt is 
  2506. made to change one, the application will immediately be kicked off the system. 
  2507.  
  2508. To register for an OS/2 interrupt, the device driver must send the address of 
  2509. its interrupt handler and the requested interrupt (IRQ) level to OS/2 via a 
  2510. SetIRQ DevHlp call. If the SetIRQ is successful, OS/2 will call the interrupt 
  2511. handler upon receipt of an interrupt on that IRQ. 
  2512.  
  2513. OS/2 will call the interrupt handler that registered for a particular IRQ until 
  2514. the interrupt handler claims the interrupt by clearing the carry flag (CLC). 
  2515.  
  2516. The interrupt handler must be located in the first code segment of the device 
  2517. driver. A sample interrupt handler is shown in Example 5-8. 
  2518.  
  2519. {
  2520.     int  rupt_dev;
  2521.     int  source;
  2522.     int  cmd_b;
  2523.     int  st_b;
  2524.     int  port;
  2525.     int  temp;
  2526.     int  rxlevel;
  2527.  
  2528.  
  2529.     port=UART_PORT_ADDRESS;
  2530.     outp((port+2),0x20);            // switch to bank 1
  2531.     source = getsrc ();             // get vector
  2532.     switch (source)
  2533.     {
  2534.  
  2535.     // optional timer service routine
  2536.  
  2537.     case timer :
  2538.  
  2539.         st_b=inp (port+3);          // dec transmit cnt
  2540.         if ( ThisReadRP == 0)       // nobody waiting
  2541.             break;
  2542.         ThisReadRP->RPstatus=(RPDONE | RPERR | ERROR_NOT_READY);
  2543.         Run ((ULONG)  ThisWriteRP); // run thread
  2544.         ThisWriteRP=0;
  2545.         break;
  2546.  
  2547.     case txm   :
  2548.     case txf   :
  2549.  
  2550.         // spurious write interrupt
  2551.  
  2552.         if ( ThisWriteRP == 0)
  2553.         {
  2554.             temp=inp(port+2);
  2555.             break;
  2556.         }
  2557.  
  2558.         // keep transmitting until no data left
  2559.  
  2560.         if  (!(QueueRead(&tx_queue,&outchar)))
  2561.         {
  2562.              outp((port), outchar);
  2563.              tickcount=MIN_TIMEOUT;
  2564.              break;
  2565.         }
  2566.  
  2567.         // done writing, run blocked thread
  2568.  
  2569.         tickcount=MIN_TIMEOUT;
  2570.         disable_write();
  2571.         ThisWriteRP->RPstatus = (RPDONE);
  2572.         Run ((ULONG)  ThisWriteRP);
  2573.         ThisWriteRP=0;
  2574.         break;
  2575.  
  2576.     case ccr   :
  2577.  
  2578.         // control character, treat as normal
  2579.  
  2580.         inchar=inp(port+5);
  2581.  
  2582.     case rxf   :
  2583.  
  2584.         // rx fifo service routine
  2585.  
  2586.         if ( ThisReadRP == 0)
  2587.            inchar=inp (port);       // get character
  2588.         else
  2589.         {
  2590.         temp=inp(port+4);
  2591.         rxlevel=(temp & 0x70) / 0x10;
  2592.  
  2593.         // empty out chip FIFO
  2594.  
  2595.         while (rxlevel !=0)
  2596.         {
  2597.  
  2598.           inchar=inp (port);        // get character
  2599.           rxlevel--;
  2600.           tickcount=MIN_TIMEOUT;
  2601.  
  2602.           // write input data to queue
  2603.  
  2604.           if(QueueWrite(&rx_queue,inchar))
  2605.  
  2606.             // error, queue must be full
  2607.  
  2608.            {
  2609.            ThisReadRP->RPstatus = (RPDONE|RPERR|ERROR_GEN_FAILURE);
  2610.            Run ((ULONG) ThisReadRP);
  2611.            ThisReadRP=0;
  2612.            break;
  2613.            }
  2614.          com_error_word |= inp(port+5);
  2615.  
  2616.         } // while rxlevel
  2617.      } // else
  2618.   } // switch (source)
  2619.  EOI (IRQnum); // send EOI
  2620. }
  2621.  
  2622. Example 5-8. Interrupt handler. 
  2623.  
  2624. If the device driver is running on an ISA bus machine, OS/2 calls the device 
  2625. driver's interrupt handler with interrupts disabled, since interrupts cannot be 
  2626. shared. On an EISA or Micro Channel machine, interrupts remain enabled when the 
  2627. interrupt handler is entered. Shared interrupts are one of the features of the 
  2628. IBM Micro Channel and EISA bus architectures, which allow more than one device 
  2629. to share a single interrupt level. 
  2630.  
  2631. Device drivers which share interrupts must claim interrupts that belong to them 
  2632. by clearing the carry flag. Interrupt handlers on EISA and Micro Channel 
  2633. machines can refuse the interrupt by setting the carry flag before exiting the 
  2634. interrupt handler. The OS/2 kernel will continue to call all of the interrupt 
  2635. handlers registered for the particular IRQ until one of the handlers claims the 
  2636. interrupt. Only the interrupt handler that claims the interrupt should issue an 
  2637. EOI, which resets the interrupt so the interrupt handler can be entered again. 
  2638. If you don't issue the EOI, you'll never get another interrupt. Only the 
  2639. interrupt handler that owns the interrupt should issue the EOI. 
  2640.  
  2641. Any extended time spent in the interrupt handler can cause performance 
  2642. problems. The interrupt handler must quickly perform its functions and exit. In 
  2643. the case of character devices, the OS/2 DevHlp library supports fast reads and 
  2644. writes to circular character queues. 
  2645.  
  2646. For block devices, interrupt handling is fast because the interrupt is usually 
  2647. caused by a DMA completion or disk-seek complete. Data is usually transferred 
  2648. to the user buffer using DMA, eliminating the need to transfer data during 
  2649. interrupt processing. On a DMA transfer, the DMA controller is set-up, started, 
  2650. and the device driver exited to allow other threads to run. When the DMA 
  2651. completes, it will generate a DMA completion interrupt, causing the device 
  2652. driver's interrupt handler to be entered. The interrupt handler can then take 
  2653. the appropriate action, such as starting a new DMA transfer. Note that the 
  2654. interrupt handler is written in C. It could have written using assembly 
  2655. language, but it's much easier to write and debug when written in C. 
  2656.  
  2657. Most UARTs and adapters contain some type of buffering, which allows a device 
  2658. driver a little slack when servicing higher data rates. The example in Example 
  2659. 5-8  shows an interrupt handler for a serial I/O port utilizing the Intel 82050 
  2660. UART. The UART has an internal 4-byte buffer and two internal timers. When an 
  2661. interrupt occurs, the UART is examined to determine the type of interrupt: 
  2662. transmit, receive, or clock. 
  2663.  
  2664. The interrupt handler is not entered directly from OS/2, but is called from our 
  2665. small assembly language start-up routine (see Example 5-6). When the SetIRQ 
  2666. call is made to register the interrupt handler, the address passed in the call 
  2667. is the address of the interrupt handler entry point in the device driver 
  2668. start-up code.  The start-up code in turn calls the C language interrupt 
  2669. handler. 
  2670.  
  2671. The interrupt handler routine is not difficult to write or understand. It can, 
  2672. however, be difficult to debug. Errors that occur in the interrupt handler 
  2673. frequently appear only in a real time context ; that is, while the interrupt 
  2674. handler is being entered as a result of a hardware interrupt. The C library 
  2675. function printf, for example, cannot be called from within an interrupt 
  2676. handler. Application debuggers, such as CodeView, cannot be used in an 
  2677. interrupt handler. A debugger such as the OS/2 kernel debugger or similar must 
  2678. be used. A breakpoint placed in the interrupt routine will cause the program to 
  2679. stop, and further interrupts may pass undetected while the program is stopped. 
  2680. A problem may not appear when breakpoints are inserted, but will reappear when 
  2681. the program executes normally. It then becomes necessary for the device driver 
  2682. writer to "visualize" the operation of the interrupt handler and begin applying 
  2683. solutions until the problem is fixed. 
  2684.  
  2685. The interrupt handler may receive unsolicited or spurious interrupts from the 
  2686. hardware, and they should be handled accordingly by the OS/2 device driver. In 
  2687. the sample interrupt handler, a check is made to see whether a valid read or 
  2688. write request is pending. If not, the device is reset and the interrupt handler 
  2689. is exited, effectively ignoring the interrupt. This is not a recommended 
  2690. practice. 
  2691.  
  2692. Examine the case rxf section of the interrupt handler in Example 5-8. This is 
  2693. where a received character is detected.  When the UART receives a complete 
  2694. character, it sets the RX FIFO register bit which generates an interrupt.  The 
  2695. interrupt handler examines the interrupt source register to determine if the 
  2696. interrupt was caused by a received character.  If so, it checks to see whether 
  2697. a valid request is pending.  If not, the character is thrown away and the 
  2698. interrupt handler exited.  If a valid read request is pending, the UART is 
  2699. queried to see how many characters are in its four-character FIFO.  (At high 
  2700. data rates, it is possible that a character had come in while we were handling 
  2701. an interrupt.)  Each character is taken out of the FIFO one by one and written 
  2702. to a circular character queue.  The OS/2 DevHlp library supports fast reads and 
  2703. writes to these circular queues.  To prevent collision, queue reads and writes 
  2704. are protected by disabling interrupts around the queue accesses.  The interrupt 
  2705. handler continues to receive characters and place them into the receive queue 
  2706. until the queue becomes full or a specified time period has elapsed. 
  2707.  
  2708. In the sample interrupt handler, data is passed back to the Strategy section of 
  2709. the device driver when the queue becomes full or when a specified time has 
  2710. passed without the reception of a new character. If the sample device driver 
  2711. was intended for use as a terminal device driver, the interrupt handler could 
  2712. have sent the data back to the Strategy section upon receipt of an end 
  2713. character, such as a carriage return. Optionally, the interrupt handler can 
  2714. return each character to the Strategy section as it is received. This method is 
  2715. more CPU intensive, however, and is generally not recommended. Data rates of 
  2716. 9600 baud and below can generally use the single-character method, but speeds 
  2717. in excess of 9600 baud may require external buffering, DMA, or a 
  2718. microprocessor-based adapter card. Overall system configuration should play a 
  2719. part in the design of your interrupt handler. A heavily loaded system may not 
  2720. be able to respond fast enough to multiple, high-speed interrupts on a 
  2721. character-by-character basis, especially if the driver is servicing several 
  2722. devices on the same interrupt level. 
  2723.  
  2724.  
  2725. ΓòÉΓòÉΓòÉ 8.16. The Timer Handler ΓòÉΓòÉΓòÉ
  2726.  
  2727. At 9600 baud, the time required to receive a character via a serial port is 
  2728. approximately one millisecond. If we received several characters, and no more 
  2729. characters were received within two or three hundred milliseconds, we could 
  2730. assume that there was an interruption of data. This could be caused by the lack 
  2731. of data, or because a terminal operator simply stopped typing. In any case, 
  2732. this would be a perfect opportunity to send the received data back to the 
  2733. application. 
  2734.  
  2735. In OS/2, a device driver can "hook" the system timer interrupt with a call to 
  2736. the DevHlp library SetTimer function. The device driver passes OS/2 a pointer 
  2737. to a timer handler, and OS/2 calls the timer handler (see Example 5-9) each 
  2738. time it receives a system clock interrupt.  OS/2 also calls any other timer 
  2739. handlers that had been previously registered. 
  2740.  
  2741. void timer_handler()
  2742. {
  2743.   if (ThisReadRP == 0)         // make sure we're waiting
  2744.         return;
  2745.  
  2746.   ThisReadRP->RPstatus=(RPDONE)// exceeded tick cnt,run thread
  2747.   Run ((ULONG) ThisReadRP);
  2748.   ThisReadRP=0L;               // insure no more entry here
  2749. }
  2750.  
  2751. Example 5-9. Timer handler. 
  2752.  
  2753. The operation is simple. If no data appears within eight or ten 32-millisecond 
  2754. system time ticks, the assumption can be made that the flow of input data has 
  2755. stopped, or at least paused. The timer handler checks for a valid pending read 
  2756. request. This is necessary because the timer handler will continue to be called 
  2757. every 32 milliseconds, even if the device driver is idle. If a valid request is 
  2758. pending, the DevHlp Run function is called to Run the Blocked thread and send 
  2759. the data back to the requesting application. When the Strategy section becomes 
  2760. unblocked, it retrieves the data from the receiver queue and sends it to the 
  2761. application's data buffer. 
  2762.  
  2763. The TickCount DevHlp could also be used to set up a timer handler that gets 
  2764. called every eight or ten ticks and checks if data has been read. (see Example 
  2765. 5-10). The TickCount method is more efficient, as the timer handler is not 
  2766. called until the count specified in the TickCount call is reached. The 
  2767. TickCount DevHlp routine can be also used to reset the tick count for a 
  2768. previously registered time handler. 
  2769.  
  2770. void timer_handler()
  2771. {
  2772.   if (ThisReadRP == 0)             // make sure we're waiting
  2773.         return;
  2774.  
  2775.   tickcount--;                     // decrement counter
  2776.   if(tickcount == 0)  {
  2777.     ThisReadRP->RPstatus=(RPDONE); // run blocked thread
  2778.     Run ((ULONG) ThisReadRP);
  2779.     ThisReadRP=0L;                 // keep us out of here
  2780.     tickcount=MIN_TIMEOUT;         // reset tick-based cntr
  2781.     }
  2782. }
  2783.  
  2784. Example 5-10. TickCount timer handler. 
  2785.  
  2786.  
  2787. ΓòÉΓòÉΓòÉ 9. Chapter 6 - Device Driver Strategy Commands ΓòÉΓòÉΓòÉ
  2788.  
  2789. Strategy commands are the commands that the driver receives from the OS/2 
  2790. kernel, usually in response to a driver request from an application thread. The 
  2791. kernel uses the device driver Request Packet (see Example 6-1)  to communicate 
  2792. with the device driver.  The kernel sends a request to the device driver by 
  2793. filling in the proper fields in the Request Packet, and sending the driver a 
  2794. pointer to the Request Packet. 
  2795.  
  2796. OS/2 does not guarantee the order that the Request Packets arrive at the device 
  2797. driver are preserved in the same order that the API requests were issued from 
  2798. the application threads. It is possible that Request Packets may arrive out of 
  2799. order, and the OS/2 device driver is responsible for providing the 
  2800. synchronization mechanism between itself and application thread requests. 
  2801.  
  2802. A Request Packet consists of two main parts:  the Request Header and the 
  2803. command-specific data field. 
  2804.  
  2805. RPlength contains the total length in bytes of the Request Packet (the length 
  2806. of the Request Header plus the length of the command-specific data). 
  2807.  
  2808. typedef struct ReqPacket
  2809. {
  2810.    UCHAR   RPlength;             // Request Packet length
  2811.    UCHAR   RPunit;               // unit code for block DD only
  2812.    UCHAR   RPcommand;            // command code
  2813.    USHORT  RPstatus;             // status word
  2814.    UCHAR   RPreserved[4];        // reserved bytes
  2815.    ULONG   RPqlink;              // queue linkage
  2816.    UCHAR   avail[19];            // command specific data
  2817. } REQPACKET;
  2818.  
  2819. Example 6-1. Request Packet definition 
  2820.  
  2821. RPunit identifies the unit for which the request is intended. This field has no 
  2822. meaning for character devices. 
  2823.  
  2824. RPcommand indicates the requested device driver function. 
  2825.  
  2826. RPStatus is defined only for OPEN and CLOSE Request Packets on entry to the 
  2827. Strategy routine. For all other Request Packets, the status field is undefined 
  2828. on entry. 
  2829.  
  2830. For an OPEN Request Packet, bit 3 (MON_OPEN_STATUS,08H) of the status field is 
  2831. set if the packet was generated from a DosMonOpen; otherwise it was a DosOpen. 
  2832.  
  2833. #define RPERR                       0x8000 //  error occurred
  2834. #define RPDEV                       0x4000 //  error code
  2835. #define RPBUSY                      0x0200 //  device is busy
  2836. #define RPDONE                      0x0100 //  driver done bit
  2837.  
  2838. #define ERROR_WRITE_PROTECT         0x0000 // Write Prot
  2839. #define ERROR_BAD_UNIT              0x0001 // Unknown Unit
  2840. #define ERROR_NOT_READY             0x0002 // Device Not Ready
  2841. #define ERROR_BAD_COMMAND           0x0003 // Unknown Command
  2842. #define ERROR_CRC                   0x0004 // CRC Error
  2843. #define ERROR_BAD_LENGTH            0x0005 // Bad Driver Req Len
  2844. #define ERROR_SEEK                  0x0006 // Seek Error
  2845. #define ERROR_NOT_DOS_DISK          0x0007 // Unknown Media
  2846. #define ERROR_SECTOR_NOT_FOUND      0x0008 // Sector Not Found
  2847. #define ERROR_OUT_OF_PAPER          0x0009 // Out of Paper
  2848. #define ERROR_WRITE_FAULT           0x000A // Write Fault
  2849. #define ERROR_READ_FAULT            0x000B // Read Fault
  2850. #define ERROR_GEN_FAILURE           0x000C // General Failure
  2851. #define ERROR_DISK_CHANGE           0x000D // Change Disk
  2852. #define ERROR_UNCERTAIN_MEDIA       0x0010 // Uncertain Media
  2853. #define ERROR_CHAR_CALL_INTERRUPTED 0x0011 // Char Call Interrupt
  2854. #define ERROR_NO_MONITOR_SUPPORT    0x0012 // Mons Not supported
  2855. #define ERROR_INVALID_PARAMETER     0x0013 // Invalid Parameters
  2856. #define ERROR_DEVICE_IN_USE         0x0014 // Dev Already In Use
  2857.  
  2858. Example 6-2. Standard OS/2 device driver errors. 
  2859.  
  2860. For a CLOSE Request Packet, bit 3 (MON_CLOSE_STATUS,08H) of the status field is 
  2861. set if the packet was generated by a DosMonClose or a DosClose of a handle that 
  2862. was generated by a DosMonOpen. Otherwise, it was a DosClose on a non-monitor 
  2863. handle. 
  2864.  
  2865. Upon exit from the Strategy routine, the status field describes the resulting 
  2866. state of the request. (see Example 6-2). 
  2867.  
  2868. Bit 15 (RPERR) is the Error bit. If this bit is set, the low 8 bits of the 
  2869. status word (7-0) indicate the error code. The error code is processed by OS/2 
  2870. in one of the following ways: 
  2871.  
  2872.  
  2873. o If the IOCtl category is 'User Defined' (greater than 127), FF00 is
  2874.  INCLUSIVE OR'd with the byte-wide error code.
  2875.  
  2876. o If not 'User Defined' and Bit 14 (RPDEV - device driver defined error
  2877.  code)  is set, FE00 is INCLUSIVE OR'd with the byte-wide error code.
  2878.  
  2879. o Otherwise, the error code must be one of those shown and is mapped by the
  2880.  kernel into one of the standard OS/2 API return codes before being returned
  2881.  to the application.
  2882.  
  2883. Bit 14 (RPDEV) is a device-driver defined error if set in conjunction with bit 
  2884. 15. 
  2885.  
  2886. Bits 13 - 10 are reserved. 
  2887.  
  2888. Bit 9 (RPBUSY) is the Busy bit. 
  2889.  
  2890. Bit 8 (RPDONE) is the Done bit. If it is set, it means that the operation is 
  2891. complete. The driver normally sets the done when it exits. 
  2892.  
  2893. Bits 7-0 are the low 8 bits of the status word. If bit 15 is set, bits 7-0 
  2894. contain the error code. 
  2895.  
  2896. ERROR_UNCERTAIN_MEDIA (10H) should be returned when the state of the media in 
  2897. the drive is uncertain. This response should NOT be returned to the INIT 
  2898. command. For fixed disks, the device driver must begin in a media uncertain 
  2899. state in order to have the media correctly labelled. 
  2900.  
  2901. ERROR_CHAR_CALL_INTERRUPTED (11H) should be returned when the thread performing 
  2902. the I/O was interrupted out of a DevHlp Block before completing the requested 
  2903. operation. 
  2904.  
  2905. ERROR_NO_MON_SUPPORT (12H) should be returned for monitor requests (DosMonOpen, 
  2906. DosMonClose, DosMonRegister), if device monitors are not supported by the 
  2907. device driver. 
  2908.  
  2909. ERROR_INVALID_PARAMETER (13H) should be returned when one or more fields of the 
  2910. Request Packet contain invalid values. 
  2911.  
  2912. RPqlink is provided to maintain a linked list of Request Packets. It is a 
  2913. pointer to the next packet in the chain, or -1L if this is the end of the 
  2914. chain. The device driver may use the Request Packet management DevHlp services 
  2915. PullReqPacket, PushReqPacket, FreeReqPacket, SortReqPacket, PullParticular, and 
  2916. AllocReqPacket to manipulate the linked list of Request Packets. 
  2917.  
  2918.  
  2919. ΓòÉΓòÉΓòÉ 9.1. Summary of Device Driver Commands ΓòÉΓòÉΓòÉ
  2920.  
  2921. Table 6-1 contains a summary of device driver Strategy commands. The commands 
  2922. are described in detail in the following subsections of this chapter. 
  2923.  
  2924. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  2925. ΓöéCode  ΓöéMeaning             ΓöéDevices           Γöé
  2926. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2927. Γöé0x00  ΓöéInit                ΓöéCharacter, Block  Γöé
  2928. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2929. Γöé0x01  ΓöéMedia Check         ΓöéBlock Only        Γöé
  2930. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2931. Γöé0x02  ΓöéBuild BIOS ParameterΓöéBlock Only        Γöé
  2932. Γöé      ΓöéBlock               Γöé                  Γöé
  2933. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2934. Γöé0x03  ΓöéReserved            ΓöéN/A               Γöé
  2935. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2936. Γöé0x04  ΓöéRead                ΓöéCharacter, Block  Γöé
  2937. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2938. Γöé0x05  ΓöéNon-destructive     ΓöéCharacter Only    Γöé
  2939. Γöé      Γöéread, no wait       Γöé                  Γöé
  2940. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2941. Γöé0x06  ΓöéInput Status        ΓöéCharacter Only    Γöé
  2942. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2943. Γöé0x07  ΓöéFlush Input Buffer  ΓöéCharacter Only    Γöé
  2944. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2945. Γöé0x08  ΓöéWrite               ΓöéCharacter, Block  Γöé
  2946. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2947. Γöé0x09  ΓöéWrite With Verify   ΓöéCharacter, Block  Γöé
  2948. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2949. Γöé0x0a  ΓöéOutput Status       ΓöéCharacter Only    Γöé
  2950. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2951. Γöé0x0b  ΓöéFlush Output Buffer ΓöéCharacter Only    Γöé
  2952. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2953. Γöé0x0c  ΓöéReserved            ΓöéN/A               Γöé
  2954. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2955. Γöé0x0d  ΓöéOpen Device         ΓöéCharacter, Block  Γöé
  2956. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2957. Γöé0x0e  ΓöéClose Device        ΓöéCharacter, Block  Γöé
  2958. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2959. Γöé0x0f  ΓöéRemovable Media     ΓöéBlock Only        Γöé
  2960. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2961. Γöé0x10  ΓöéGeneric IOCtl       ΓöéCharacter, Block  Γöé
  2962. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2963. Γöé0x11  ΓöéReset Media         ΓöéBlock Only        Γöé
  2964. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2965. Γöé0x12  ΓöéGet Logical Drive   ΓöéBlock Only        Γöé
  2966. Γöé      ΓöéMap                 Γöé                  Γöé
  2967. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2968. Γöé0x13  ΓöéSet Logical Drive   ΓöéBlock Only        Γöé
  2969. Γöé      ΓöéMap                 Γöé                  Γöé
  2970. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2971. Γöé0x14  ΓöéDeinstall           ΓöéCharacter Only    Γöé
  2972. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2973. Γöé0x15  ΓöéReserved            ΓöéN/A               Γöé
  2974. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2975. Γöé0x16  ΓöéPartitionable Disk  ΓöéBlock Only        Γöé
  2976. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2977. Γöé0x17  ΓöéGet Fixed Disk Map  ΓöéBlock Only        Γöé
  2978. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2979. Γöé0x18  ΓöéReserved            ΓöéN/A               Γöé
  2980. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2981. Γöé0x19  ΓöéReserved            ΓöéN/A               Γöé
  2982. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2983. Γöé0x1a  ΓöéReserved            ΓöéN/A               Γöé
  2984. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2985. Γöé0x1b  ΓöéReserved            ΓöéN/A               Γöé
  2986. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2987. Γöé0x1c  ΓöéShutdown            ΓöéCharacter, Block  Γöé
  2988. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2989. Γöé0x1d  ΓöéGet Driver          ΓöéBlock Only        Γöé
  2990. Γöé      ΓöéCapabilities        Γöé                  Γöé
  2991. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2992. Γöé0x1e  ΓöéReserved            ΓöéN/A               Γöé
  2993. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2994. Γöé0x1f  ΓöéCmdInitComplete     ΓöéCharacter, Block  Γöé
  2995. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  2996. Table 6-1. Device Driver Strategy Commands 
  2997.  
  2998.  
  2999. ΓòÉΓòÉΓòÉ 9.2. 0h / Init ΓòÉΓòÉΓòÉ
  3000.  
  3001. Initialize the device. 
  3002.  
  3003. Format Of Request Packet 
  3004.  
  3005. union
  3006.   {
  3007.     struct {                     // init packet(one entry,exit)
  3008.       UCHAR      units;          // number of units
  3009.       FPFUNCTION DevHlp;         // &DevHlp
  3010.       char far   *args;          // & init arg pointers
  3011.       UCHAR      drive;          // drive #
  3012.       }Init;
  3013.     struct {
  3014.       UCHAR     units;           // same as input
  3015.       OFF       finalCS;         // final code offset
  3016.       OFF       finalDS;         // final data offset
  3017.       FARPOINTER BPBarray;       // &BPB
  3018.       } InitExit;
  3019.   }
  3020.  
  3021. Comments 
  3022.  
  3023. The INIT function is called by the kernel during driver installation at boot 
  3024. time. The INIT section should initialize the adapter and device. For example, 
  3025. if the device was a serial port, the initialization section might set the baud 
  3026. rate, parity, stop bits, etc. on a serial port or check to see if the device is 
  3027. installed correctly. INIT is called in a special mode at Ring 3 with some Ring 
  3028. 0 capabilities. For example, the driver may turn off interrupts during INIT, 
  3029. but they must be turned back on before returning to the kernel. The INIT code 
  3030. may also perform direct port I/O without generating protection violations. 
  3031. Usually, the driver will allocate buffers and data storage during INIT, to 
  3032. ensure that the driver will work when installed. Because the memory allocations 
  3033. are done at Ring 3, the system can check to make sure the allocations are 
  3034. valid. If not, the driver can remove itself from memory, freeing up any 
  3035. previously allocated space for other system components. Since the INIT code is 
  3036. executed only once, and during system boot, its not necessary to optimize the 
  3037. INIT code. Do all of the work you can up front in the INIT section, as it may 
  3038. be time-prohibitive or even impossible to do some initialization during normal 
  3039. kernel-mode driver operation. 
  3040.  
  3041. On entry, the INIT Request Packet contains the following fields as inputs to 
  3042. the device driver: 
  3043.  
  3044. o A pointer to the DevHlp entry point. (in OS/2 1.x, this is a bimodal pointer)
  3045.  
  3046. o A pointer to the initialization arguments from the DEVICE= line in
  3047.  CONFIG.SYS.
  3048.  
  3049. o The drive number for the first block device unit.
  3050.  
  3051. The pointer to the initialization parameters allows a device driver to be 
  3052. configured at boot time, based on arguments placed on the DEVICE= line in 
  3053. CONFIG.SYS. See Chapter 8 for a discussion of how to do this, and a listing of 
  3054. the INIT section of an actual driver that performs this function. 
  3055.  
  3056. When a base block device driver or ADD gets initialized, the pointer to the 
  3057. initialization arguments is actually a pointer to up to five pointers. In OS/2 
  3058. 1.x, the list contains three pointers. In OS/2 2.0, the list contains four 
  3059. pointers. In OS/2 2.2, the list contains five pointers. The first pointer 
  3060. points to the InitCache parameter list. The second pointer points to the disk 
  3061. configuration table. The third pointer points to the IRQ vector table. The 
  3062. fourth pointer points to the argument list from the DEVICE= statement in 
  3063. CONFIG.SYS. The fifth pointer points to the MachineConfigurationInfo structure, 
  3064. which contains the information shown in Example 6-3. 
  3065.  
  3066. typedef _MachineConfigurationInfo
  3067. {
  3068.  USHORT Length;         // length of info
  3069.  USHORT BusInfo;        // 1=MCA, 2=EISA, 3=ISA, 4-8=?
  3070.  USHORT CPUInfo;        // 1=386, 2=486
  3071.  UCHAR Submodel;        // system submodel
  3072.  UCHAR Model;           // system model
  3073.  USHORT ABIOSRevision;  // revision of system ABIOS (PS/2)
  3074.  USHORT HardDriveCount; // number of hard drives
  3075.  UCHAR Reserved;        // reserved for future
  3076. } MachineConfigurationInfo;
  3077.  
  3078. Example 6-3. MachineConfigurationInfo structure. 
  3079.  
  3080. Upon the completion of initialization, the device driver must set certain 
  3081. fields in the Request Packet as follows: 
  3082.  
  3083. o The number of logical block devices or units the driver supports (block
  3084.  devices only).
  3085.  
  3086. o The WORD offset to the end of the code segment.
  3087.  
  3088. o The WORD offset to the end of the data segment.
  3089.  
  3090. o A pointer to the BIOS Parameter Block or BPB (block devices only).
  3091.  
  3092. A block device driver must also return the number of logical devices or units 
  3093. that are available. The kernel's file system layer will assign sequential drive 
  3094. letters to these units. A character device driver should set the number of 
  3095. devices to 0. 
  3096.  
  3097. As a final step in initialization, both block and character device drivers must 
  3098. return the offsets to the end of the code and data segments. This allows the 
  3099. device driver to release code and data needed only by the device driver's 
  3100. initialization routine. To facilitate this, the initialization code and data 
  3101. should be located at the end of the appropriate segments. A device driver which 
  3102. fails initialization should return 0 for both offset values. 
  3103.  
  3104. A block device driver must return an array of BPBs for each of the logical 
  3105. units that it supports. A character device driver should set the BPB pointer to 
  3106. 0. 
  3107.  
  3108. If initialization is successful, the status field in the Request Header must be 
  3109. set to indicate no errors and the done status (RPDONE). 
  3110.  
  3111. If the device driver determines that it cannot initialize the device, it should 
  3112. return with the error bit (RPERR) in the Request Header status field set. The 
  3113. device driver should return RPERR | RPDONE | ERROR_GEN_FAILURE. Whatever the 
  3114. reason for the failure, the status must always indicate that the request is 
  3115. done (RPDONE). 
  3116.  
  3117. The system loader records the last non-zero code and data segment offsets 
  3118. returned for the devices which successfully completed initialization. These 
  3119. offset values are used to re-size the device driver's code and data segments. 
  3120.  
  3121. If the device driver supports multiple devices or units, the kernel will call 
  3122. the initialization section for each of the devices or units. If your device 
  3123. driver has a single initialization section, the offset values returned to the 
  3124. kernel should be the same for each device initialization that is successful. 
  3125.  
  3126. A limited number of OS/2 system API routines are available to the device driver 
  3127. during initialization. Those API routines are listed in Table 6-2. 
  3128.  
  3129. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3130. ΓöéRoutine Name      ΓöéDescription                   Γöé
  3131. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3132. ΓöéDosGetMessage     ΓöéGet a system message          Γöé
  3133. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3134. ΓöéDosOpen           ΓöéOpen a file or device driver  Γöé
  3135. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3136. ΓöéDosPutMessage     ΓöéDisplay message               Γöé
  3137. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3138. ΓöéDosQCurDir        ΓöéQuery current directory       Γöé
  3139. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3140. ΓöéDosQCurDisk       ΓöéQuery current disk            Γöé
  3141. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3142. ΓöéDosQFileInfo      ΓöéQuery file information        Γöé
  3143. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3144. ΓöéDosQFileMode      ΓöéQuery file mode               Γöé
  3145. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3146. ΓöéDosRead           ΓöéRead from file or device      Γöé
  3147. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3148. ΓöéDosSMResgisterDD  ΓöéRegister driver for SM events Γöé
  3149. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3150. ΓöéDosWrite          ΓöéWrite to file or device       Γöé
  3151. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3152. Table 6-2. API routines available during Init. 
  3153.  
  3154. For more information about these functions, refer to the IBM OS/2 2.1 Control 
  3155. Program Reference. 
  3156.  
  3157.  
  3158. ΓòÉΓòÉΓòÉ 9.3. 1H/ Media Check ΓòÉΓòÉΓòÉ
  3159.  
  3160. Determine the state of the media. 
  3161.  
  3162. Format Of Request Packet 
  3163.  
  3164.     struct {                     // MEDIA_CHECK
  3165.       UCHAR      media;          // media descriptor
  3166.       UCHAR      return_code;    // see below
  3167.       FARPOINTER prev_volume;    // &previous volume ID
  3168.       } MediaCheck;
  3169.  
  3170. Comments 
  3171.  
  3172. On entry, the Request Packet will have the media descriptor field set for the 
  3173. drive identified in the Request Header (see Table 6-3). 
  3174.  
  3175. The device driver must perform the following actions for the MEDIA CHECK 
  3176. request: 
  3177.  
  3178. o Set the status word in the Request Header.
  3179.  
  3180. o Set the return code where:
  3181.  -1 = Media has been changed
  3182.  0 = Unsure if media has been changed
  3183.  1 = Media unchanged
  3184.  
  3185. To determine whether you are using a single-sided or a double-sided 8-inch 
  3186. diskette (FEh), attempt to read the second side. If an error occurs, you can 
  3187. assume the diskette is single-sided. 
  3188.  
  3189. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3190. ΓöéDisk type Γöé#Sides  Γöé#Sectors perΓöéMedia       Γöé
  3191. Γöé          Γöé        Γöétrack       Γöédescriptor  Γöé
  3192. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3193. ΓöéFixed diskΓöé-----   Γöé-----       Γöé0xF8        Γöé
  3194. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3195. Γöé3.5 inch  Γöé2       Γöé9           Γöé0xF9        Γöé
  3196. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3197. Γöé3.5 inch  Γöé2       Γöé18          Γöé0xF0        Γöé
  3198. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3199. Γöé5.25 inch Γöé2       Γöé15          Γöé0xF9        Γöé
  3200. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3201. Γöé5.25 inch Γöé1       Γöé9           Γöé0xFC        Γöé
  3202. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3203. Γöé5.25 inch Γöé2       Γöé9           Γöé0xFD        Γöé
  3204. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3205. Γöé5.25 inch Γöé1       Γöé8           Γöé0xFE        Γöé
  3206. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3207. Γöé5.25 inch Γöé2       Γöé8           Γöé0xFF        Γöé
  3208. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3209. Γöé8 inch    Γöé1       Γöé26          Γöé0xFE        Γöé
  3210. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3211. Γöé8 inch    Γöé2       Γöé26          Γöé0xFD        Γöé
  3212. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3213. Γöé8 inch    Γöé2       Γöé8           Γöé0xFE        Γöé
  3214. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3215. Table 6-3. Media descriptor byte 
  3216.  
  3217. The Media Check function is called by the kernel prior to disk access, and is 
  3218. therefore valid only for block devices. The kernel sends to the driver the 
  3219. media ID byte for the type of disk that it expects to find in the selected 
  3220. drive. 
  3221.  
  3222.  
  3223. ΓòÉΓòÉΓòÉ 9.4. 2H / Build BPB ΓòÉΓòÉΓòÉ
  3224.  
  3225. Build the BIOS Parameter Block (BPB). The driver receives this request when the 
  3226. media has changed or when the media type is uncertain. 
  3227.  
  3228. Format Of Request Packet 
  3229.  
  3230.    struct {                      // BUILD_BPB
  3231.       UCHAR      media;          // media descriptor
  3232.       FARPOINTER buffer;         // 1-sector buffer FAT
  3233.       FARPOINTER BPBarray;       // &BPB array
  3234.       UCHAR      drive;          // drive #
  3235.       } BuildBPB;
  3236.  
  3237. Comments 
  3238.  
  3239. On entry, the Request Packet will have the media descriptor set for the drive 
  3240. identified in the Request Header. The transfer address is a virtual address to 
  3241. a buffer containing the boot sector media, if the block device driver attribute 
  3242. field has bit 13 (DAW_IBM) set; otherwise, the buffer contains the first sector 
  3243. of the File Allocation Table (FAT). 
  3244.  
  3245. The device driver must perform the following actions: 
  3246.  
  3247. o Set the pointer to the BPB table.
  3248.  
  3249. o Update the media descriptor.
  3250.  
  3251. o Set the status word in the Request Header.
  3252.  
  3253. The device driver must determine the media type in the drive, in order to 
  3254. return the pointer to the BPB table. Previously, the FAT ID byte determined the 
  3255. structure and layout of the media. Because the FAT ID byte has only eight 
  3256. possible values (F8 through FF), it is clear that, as new media types are 
  3257. invented, the available values will soon be exhausted. With the varying media 
  3258. layouts, OS/2 needs to be aware of the location of the FATs and directories 
  3259. before it reads them. 
  3260.  
  3261. The device driver should read the boot sector from the specified buffer. If the 
  3262. boot sector is for DOS 2.10, 2.10, 3.00, 3.10, 3.20, or OS/2, the device driver 
  3263. returns the BPB from the boot sector. If the boot sector is for DOS 1.00 or 
  3264. 1.10, the device driver reads the first sector of the FAT into the specified 
  3265. buffer. The FAT ID is examined and the corresponding BPB is returned. 
  3266.  
  3267. The information relating to the BPB for a particular media is kept in the boot 
  3268. sector for the media (see Table 6-4). 
  3269.  
  3270. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3271. ΓöéField                               ΓöéLength    Γöé
  3272. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3273. ΓöéShort jump (0xeb) followed by NOP   Γöé2 bytes   Γöé
  3274. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3275. ΓöéOEM name and version                Γöé8 bytes   Γöé
  3276. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3277. ΓöéBytes per sector                    Γöéword      Γöé
  3278. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3279. ΓöéSectors per allocation unit (base 2)Γöébyte      Γöé
  3280. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3281. ΓöéReserved sectors (starting at 0)    Γöéword      Γöé
  3282. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3283. ΓöéNumber of FATs                      Γöébyte      Γöé
  3284. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3285. ΓöéNumber of root dir. entries (max)   Γöéword      Γöé
  3286. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3287. ΓöéNumber of sectors (total)           Γöéword      Γöé
  3288. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3289. ΓöéMedia descriptor                    Γöébyte      Γöé
  3290. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3291. ΓöéNumber of sectors in a single FAT   Γöéword      Γöé
  3292. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3293. ΓöéSectors per track                   Γöéword      Γöé
  3294. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3295. ΓöéNumber of heads                     Γöéword      Γöé
  3296. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3297. ΓöéNumber of hidden sectors            Γöéword      Γöé
  3298. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3299. Table 6-4. Boot Sector Format 
  3300.  
  3301. The last three WORDs in Table 6-4 help the device driver understand the media. 
  3302. The number of heads is useful for supporting different multiple head drives 
  3303. that have the same storage capacity but a different number of surfaces. The 
  3304. number of hidden sectors is useful for supporting drive partitioning schemes. 
  3305.  
  3306. For drivers that support volume identification and disk change, this call 
  3307. should cause a new volume identification to be read off the disk. This call 
  3308. indicates that the disk was properly changed. 
  3309.  
  3310.  
  3311. ΓòÉΓòÉΓòÉ 9.5. 4H, 8H, 9H / Read or Write ΓòÉΓòÉΓòÉ
  3312.  
  3313. Read from or write to a device.  Read (4H) / Write (8H) / Write with Verify 
  3314. (9H) 
  3315.  
  3316. Format Of Request Packet 
  3317.  
  3318.    struct {                      // READ, WRITE, WRITE_VERIFY
  3319.      UCHAR      media;           // media descriptor
  3320.      PHYSADDR   buffer;          // transfer address
  3321.      USHORT     count;           // bytes/sectors
  3322.      ULONG      startsector;     // starting sector #
  3323.      USHORT     reserved;
  3324.      } ReadWrite;
  3325.  
  3326. Comments 
  3327.  
  3328. On entry, the Request Packet will have the media descriptor set for the drive 
  3329. identified in the Request Header. The transfer address is a 32-bit physical 
  3330. address of the buffer for the data. The byte/sector count is set to the number 
  3331. of bytes to transfer (for character device drivers) or the number of sectors to 
  3332. transfer (for block device drivers). The starting sector number is set for 
  3333. block device drivers. The System File Number is a unique number associated with 
  3334. an open request. 
  3335.  
  3336. The device driver must perform the following actions: 
  3337.  
  3338. o Perform the requested function.
  3339.  
  3340. o Set the actual number of sectors or bytes transferred.
  3341.  
  3342. o Set the status word in the Request Packet.
  3343.  
  3344. The DWORD transfer address in the Request Packet is a locked 32-bit physical 
  3345. address. The device driver can use it to call the DevHlp function PhysToVirt 
  3346. and obtain a segment swapping address for the current mode. The device driver 
  3347. does not need to unlock the address when the request is completed. 
  3348.  
  3349. READ is a standard driver request. The application calls the READ Strategy 
  3350. entry point by issuing a DosRead with the handle obtained during the DosOpen. 
  3351. The READ routine may return one character at a time, but more often returns a 
  3352. buffer full of data. How the READ function works is up to the driver writer. 
  3353. The driver returns the count of characters read and stores the received data in 
  3354. the data segment of the application. READ returns one of the standard driver 
  3355. return codes. 
  3356.  
  3357. Note: The functions IOCtl Read and IOCtl Write are not supported by the 
  3358. standard base OS/2 device drivers. 
  3359.  
  3360. WRITE is a standard driver request, called by the application as a result of a 
  3361. DosWrite call. The application passes the address of data to write (usually in 
  3362. the applications data segment) to the driver and the count of the characters to 
  3363. write. The driver writes the data and returns the status to the application, 
  3364. along with the number of characters that were actually written. WRITE returns a 
  3365. standard driver return code. 
  3366.  
  3367.  
  3368. ΓòÉΓòÉΓòÉ 9.6. 5H / Nondestructive Read No Wait ΓòÉΓòÉΓòÉ
  3369.  
  3370. Read a character from an input buffer without removing it. 
  3371.  
  3372. Format Of Request Packet 
  3373.  
  3374.    struct {                      // NON_DESTRUCT READ/NO WAIT
  3375.      UCHAR      char_returned;   // returned character
  3376.      } ReadNoWait;
  3377.  
  3378. Comments 
  3379.  
  3380. The device driver must perform the following actions: 
  3381.  
  3382. o Return a byte from the device.
  3383.  
  3384. o Set the status word in the Request Header.
  3385.  
  3386. For input on character devices with a buffer, the device driver should return 
  3387. from this function with the busy bit (RPBUSY) clear, along with a copy of the 
  3388. first character in the buffer. The busy bit is set to indicate that there are 
  3389. no characters in the buffer. This function allows the operating system to look 
  3390. ahead one input character without blocking in the device driver. 
  3391.  
  3392.  
  3393. ΓòÉΓòÉΓòÉ 9.7. 6H, AH / Input or Output Status ΓòÉΓòÉΓòÉ
  3394.  
  3395. Determine the input or output status of a character device. 
  3396.  
  3397. Format Of Request Packet 
  3398.  
  3399. No Parameters 
  3400.  
  3401. Comments 
  3402.  
  3403. The device driver must perform the following actions: 
  3404.  
  3405. o Perform the requested function.
  3406.  
  3407. o Set the busy bit.
  3408.  
  3409. o Set the status word in the Request Header.
  3410.  
  3411. For output status on character devices, if the busy bit (RPBUSY) is returned 
  3412. set, an output request is currently pending. If the busy bit is returned set to 
  3413. 0, there is no current request pending. 
  3414.  
  3415. For input status on character devices with a buffer, if the busy bit is 
  3416. returned set, there are no characters currently buffered in the device driver. 
  3417. If the busy bit is returned clear, there is at least one character in the 
  3418. device driver buffer. The effect of busy bit = 0 is that a read of one 
  3419. character will not need blocking. Devices that do not have an input buffer in 
  3420. the device driver should always return with the busy bit clear. This is a 
  3421. "peek" function, to determine the presence of data. 
  3422.  
  3423.  
  3424. ΓòÉΓòÉΓòÉ 9.8. 7H, BH / Input Flush or Output Flush ΓòÉΓòÉΓòÉ
  3425.  
  3426. Flush or terminate all pending requests. 
  3427.  
  3428. Format Of Request Packet 
  3429.  
  3430. No Parameters 
  3431.  
  3432. Comments 
  3433.  
  3434. The device driver must perform the following actions: 
  3435.  
  3436. o Perform the requested function.
  3437.  
  3438. o Set the status word in the Request Header.
  3439.  
  3440. This call tells the device driver to flush (terminate) all known pending 
  3441. requests. Its primary use is to flush the input or output queue on character 
  3442. devices. The Input Buffer Flush should flush any receiver queues or buffers, 
  3443. and return DONE to the kernel. The Output Buffer Flush should flush any 
  3444. transmitter queues or buffers. 
  3445.  
  3446.  
  3447. ΓòÉΓòÉΓòÉ 9.9. DH,EH / Open or Close ΓòÉΓòÉΓòÉ
  3448.  
  3449. Open or Close a Device. 
  3450.  
  3451. Format Of Request Packet 
  3452.  
  3453.     struct {                     // OPEN/CLOSE
  3454.      USHORT sys_file_num ;       // system file number
  3455.      } OpenClose;
  3456.  
  3457. Comments 
  3458.  
  3459. The System File Number is a unique number associated with an open request. The 
  3460. device driver must perform the following actions: 
  3461.  
  3462. o Perform the requested function.
  3463.  
  3464. o Set the status word in the Request Header.
  3465.  
  3466. Character device drivers may use OPEN/CLOSE requests to correlate using their 
  3467. devices with application activity. For instance, the device driver may increase 
  3468. a reference count for every OPEN, and decrease the reference count for every 
  3469. CLOSE. When the count goes to 0, the device driver can flush its buffers. This 
  3470. can be thought of as a "last close causes flush." 
  3471.  
  3472. The OPEN function is called as a result of the application issuing a DosOpen 
  3473. call. The kernel makes note of the DosOpen request, and if it is successful, 
  3474. the kernel sends back a handle to the application to use for subsequent driver 
  3475. service. The driver writer can use this section to initialize a device, flush 
  3476. any buffers, reset any buffer pointers, initialize character queues, or 
  3477. anything necessary for a clean starting operation. 
  3478.  
  3479. The CLOSE is usually called as a result of the application doing a DosClose 
  3480. with the correct driver handle, but it is also called when the application that 
  3481. opened the driver terminates or is aborted with a <cntl-c> or <cntl-break>. 
  3482.  
  3483. In most cases, its a good idea to make sure that the application closing the 
  3484. driver is the same one that opened it. To ensure this, the device driver should 
  3485. save the PID of the application that opened the driver, and make sure that the 
  3486. closing PID is the same. If not, the device driver should reject it as a bogus 
  3487. request. The driver can get the PID of the calling program using the GetDOSVar 
  3488. DevHlp routine. 
  3489.  
  3490. All devices associated with the device driver should be made quiescent at CLOSE 
  3491. time. 
  3492.  
  3493.  
  3494. ΓòÉΓòÉΓòÉ 9.10. FH / Removable Media ΓòÉΓòÉΓòÉ
  3495.  
  3496. Check for removable media. 
  3497.  
  3498. Format Of Request Packet 
  3499.  
  3500. No Parameters 
  3501.  
  3502. Comments 
  3503.  
  3504. The device driver must perform the following actions: 
  3505.  
  3506. o Set the busy bit to 1 if the media is non-removable.
  3507.  
  3508. o Set the busy bit to 0 if the media is removable.
  3509.  
  3510. o Set the status word in the Request Header.
  3511.  
  3512. The driver receives this request as a result of an application generating an 
  3513. IOCtl call to Category 8, Function 0x20. Instead of calling the IOCtl section 
  3514. of the device driver, the kernel issues this request. The driver must set the 
  3515. busy bit (RPBUSY) of the Request Packet status if the media is non-removable, 
  3516. and must clear it if the media is removable. 
  3517.  
  3518.  
  3519. ΓòÉΓòÉΓòÉ 9.11. 1OH / Generic IOCtl ΓòÉΓòÉΓòÉ
  3520.  
  3521. Send I/O control commands to a device. 
  3522.  
  3523. Format Of Request Packet (DosDevIOCtl) 
  3524.  
  3525.      struct {                    // IOCtl
  3526.       UCHAR      category;       // category code
  3527.       UCHAR      function;       // function code
  3528.       FARPOINTER parameters;     // ¶meters
  3529.       FARPOINTER buffer;         // &buffer
  3530.       USHORT     sys_file_num;   // system file number
  3531.       } IOCtl;
  3532.  
  3533. Format of Request Packet (DosDevIOCtl2) 
  3534.  
  3535.      struct {                    // IOCtl
  3536.       UCHAR      category;       // category code
  3537.       UCHAR      function;       // function code
  3538.       FARPOINTER parameters;     // ¶meters
  3539.       FARPOINTER buffer;         // &buffer
  3540.       USHORT     sys_file_num;   // system file number
  3541.       USHORT     parm_buf_length;// length of parameter buffer
  3542.       USHORT     data_buf_length // length of data buffer
  3543.       } IOCtl;
  3544.  
  3545. Comments 
  3546.  
  3547. On entry, the request packet will have the IOCtl category code and function 
  3548. code set. The parameter buffer and the data buffer addresses are passed as 
  3549. virtual addresses. Note that some IOCtl functions do not require data and/or 
  3550. parameters to be passed. For these IOCtls, the parameter and data buffer 
  3551. addresses may contain NULL pointers. The System File Number is a unique number 
  3552. associated with an OPEN request. 
  3553.  
  3554. If the device driver indicates (in the function level of the device attribute 
  3555. field of its Device Header) that it supports DosDevIOCtl2, the Generic IOCtl 
  3556. request packets passed to the device driver will have two additional words, 
  3557. containing the lengths of the Parameter Buffer and Data Buffer, respectively. 
  3558. If the device driver indicates through the function level that it supports 
  3559. DosDevIOCtl2, but the application issues DosDevIOCtl, the Parameter Buffer and 
  3560. Data Buffer length fields will be set to zero. 
  3561.  
  3562. The device driver must perform the following actions: 
  3563.  
  3564. o Perform the requested function.
  3565.  
  3566. o Set the status word in the Request Header.
  3567.  
  3568. The device driver is responsible for locking the parameter and data buffer 
  3569. segments, and converting the pointers to 32-bit physical addresses, if 
  3570. necessary. 
  3571.  
  3572. Refer to the OS/2 Version 2.1 Programming Reference and the OS/2 Version 2.1 
  3573. Application Programming Guide for more detailed information on the generic 
  3574. IOCtl interface for applications. 
  3575.  
  3576. The third and fourth command-specific parameters of an IOCtl are the address of 
  3577. the application program's data buffer and parameter buffer, respectively. The 
  3578. format of the two buffers is entirely up to the driver writer. The parameter 
  3579. buffer might contain a list of USHORTs, UCHARs, or pointers. However, pointers 
  3580. are not recommended because, depending on the type of application sending them 
  3581. (16:16 or 0:32), the pointers might require further translation, affecting 
  3582. portability. 
  3583.  
  3584. The data buffer parameter might be the address of a data buffer in the 
  3585. application program where the driver would store data from the device. It 
  3586. should also be noted that the IOCtl need not pass or receive any data. 
  3587.  
  3588. Another feature of an IOCtl is its ability to send back device-specific 
  3589. information to the application. A standard driver request, such as DosRead or 
  3590. DosWrite, returns a value to the application which is used to determine whether 
  3591. or not the operation was successful. For something like a terminal driver, a 
  3592. simple pass/fail indication might be sufficient. Suppose, however, that the 
  3593. driver needed to tell the application that the data was in ASCII or binary 
  3594. format, or that a parity error was detected while receiving it. Here an IOCtl 
  3595. would be a better choice because the kernel 'massages' return codes from 
  3596. standard function calls to fit within the standard error definitions. The 
  3597. IOCtl, however, will pass back special error codes to the application exactly 
  3598. as they were set in the driver. 
  3599.  
  3600.  
  3601. ΓòÉΓòÉΓòÉ 9.12. 11H / Reset Media ΓòÉΓòÉΓòÉ
  3602.  
  3603. Reset the Uncertain Media error condition and allow OS/2 to identify the media. 
  3604.  
  3605. Format Of Request Packet 
  3606.  
  3607. No Parameters 
  3608.  
  3609. Comments 
  3610.  
  3611. On entry, the unit code identifies the drive number to be reset. The device 
  3612. driver must perform the following actions: 
  3613.  
  3614. o Set the status word in the Request Header.
  3615.  
  3616. o Reset the error condition for the drive.
  3617. Before this command, the driver had returned ERROR_UNCERTAIN_MEDIA for the 
  3618. drive. This action informs the device driver that it no longer needs to return 
  3619. the error for the drive. 
  3620.  
  3621.  
  3622. ΓòÉΓòÉΓòÉ 9.13. 12H, 13H / Get/Set Logical Drive ΓòÉΓòÉΓòÉ
  3623.  
  3624. Get/Set Logical Drive Mapping 
  3625.  
  3626. Format Of Request Packet 
  3627.  
  3628. No Parameters 
  3629.  
  3630. Comments 
  3631.  
  3632. On entry, the unit code contains the unit number of the drive on which this 
  3633. operation is to be performed. 
  3634.  
  3635. The device driver must perform the following actions: 
  3636.  
  3637. o For GET, it must return the logical drive that is mapped onto the physical
  3638.  drive indicated by the unit number in the Request Header.
  3639.  
  3640. o For SET, it must map the logical drive represented by the unit number onto
  3641.  the physical drive that has the mapping of logical drives.
  3642.  
  3643. o The logical drive is returned in the unit code field. This field is set to 0 if
  3644.  there is only one logical drive mapped onto the physical drive.
  3645.  
  3646. o Set the status word in the Request Header.
  3647.  
  3648.  
  3649. ΓòÉΓòÉΓòÉ 9.14. 14H / Deinstall ΓòÉΓòÉΓòÉ
  3650.  
  3651. Request deinstall of driver. 
  3652.  
  3653. Format Of Request Packet 
  3654.  
  3655. No Parameters 
  3656.  
  3657. Comments 
  3658.  
  3659. When a device driver is loaded, the attribute field and name in its header are 
  3660. used to determine if the new device driver is attempting to replace a driver 
  3661. (device) already installed. If so, the previously installed device driver is 
  3662. requested by the operating system to DEINSTALL. If the installed device driver 
  3663. refuses the DEINSTALL command, the new device driver is not allowed to be 
  3664. loaded. If the installed device driver performs the DEINSTALL, the new device 
  3665. driver is loaded. 
  3666.  
  3667. If a character device driver honors the DEINSTALL request, it must perform the 
  3668. following actions: 
  3669.  
  3670. o Release any allocated physical memory.
  3671.  
  3672. o UnSet any hardware interrupt vectors that it had claimed.
  3673.  
  3674. o Remove any timers.
  3675.  
  3676. o Clear the error bit in the status word to indicate a successful DEINSTALL.
  3677.  
  3678. If the character device driver determines that it cannot or will not deinstall, 
  3679. it should set the error bit (RPERR) in the status field and set the error code 
  3680. to ERROR_BAD_COMMAND (03H). 
  3681.  
  3682. Deinstall Considerations 
  3683.  
  3684. An ABIOS device driver maps its device name to a unit within a Logical ID 
  3685. (LID). It receives a DEINSTALL request for its device name, which implies a 
  3686. single unit of a LID. To honor the DEINSTALL request, it must relinquish the 
  3687. LID by calling DevHlp FreeLIDEntry at DEINSTALL time. 
  3688.  
  3689. In honoring a DEINSTALL command, a device driver must remove its claim on the 
  3690. interrupt level by issuing an UnSetIRQ DevHlp call. 
  3691.  
  3692. If the device driver's device is ill-behaved (that is, it cannot be told to 
  3693. stop generating interrupts), the device driver must not remove its interrupt 
  3694. handler, and must refuse the DEINSTALL request. 
  3695.  
  3696.  
  3697. ΓòÉΓòÉΓòÉ 9.15. 16H / Partitionable Fixed Disks ΓòÉΓòÉΓòÉ
  3698.  
  3699. This call is used by the system to ask the device driver how many physical 
  3700. partitionable fixed disks the device driver supports. 
  3701.  
  3702. Format Of Request Packet 
  3703.  
  3704.     struct {                     // PARTITIONABLE fixed disks
  3705.       UCHAR      count;          // number of disks supported
  3706.       ULONG      reserved;
  3707.       } Partitionable;
  3708.  
  3709. Comments 
  3710.  
  3711. This is done to allow the Category 9 Generic IOCtls to be routed appropriately 
  3712. to the correct device driver. This call is not tied to a particular unit that 
  3713. the device driver owns, but is directed to the device driver as a general query 
  3714. of its device support. 
  3715.  
  3716. The device driver must perform the following actions: 
  3717.  
  3718. o Set the count (1- based).
  3719.  
  3720. o Set the status word in the Request Header.
  3721.  
  3722.  
  3723. ΓòÉΓòÉΓòÉ 9.16. 17H / Get Fixed Disk/Logical Unit Map ΓòÉΓòÉΓòÉ
  3724.  
  3725. Get Fixed Disk/LU Map. 
  3726.  
  3727. Format Of Request Packet 
  3728.  
  3729.     struct {                     // Get Fixed Disk/Log Unit Map
  3730.       ULONG      units;          // units supported
  3731.       ULONG      reserved;
  3732.       } GetFixedMap;
  3733.  
  3734. Comments 
  3735.  
  3736. This call is used by the system to determine which logical units supported by 
  3737. the device driver exist on the physical partitionable fixed disk. 
  3738.  
  3739. On entry, the request packet header unit field identifies a physical disk 
  3740. number (0-based) instead of a logical unit number. The device driver returns a 
  3741. bitmap of which logical units exist on the physical drive. The physical drive 
  3742. relates to the partitionable fixed disks reported to the system by way of the 
  3743. PARTITIONABLE FIXED DISKS command. It is possible that no logical units exist 
  3744. on a given physical disk because it has not yet been initialized. 
  3745.  
  3746. The device driver must perform the following actions: 
  3747.  
  3748. o Set the 4-byte bit mask to indicate which logical units it owns. The logical
  3749.  units must exist on the physical partitionable fixed disk for which the
  3750.  information is being requested.
  3751.  
  3752. o Set the status word in the Request Packet header.
  3753.  
  3754. The bit mask is set up as follows: A 0 means that the logical unit does not 
  3755. exist, and a 1 means it does. The first logical unit that the device driver 
  3756. supports is the low-order bit of the first byte. The bits are used from right 
  3757. to left, starting at the low-order bit of each following byte. It is possible 
  3758. that all of the bits will be 0. 
  3759.  
  3760.  
  3761. ΓòÉΓòÉΓòÉ 9.17. 1CH / Shutdown ΓòÉΓòÉΓòÉ
  3762.  
  3763. Begin shutdown procedure. 
  3764.  
  3765. Format Of Request Packet 
  3766.  
  3767.     struct {                     // Shutdown
  3768.       UCHAR      func;           // shutdown function code
  3769.       ULONG      reserved;
  3770.      } Shutdown;
  3771.  
  3772. Comments 
  3773.  
  3774. This call is used by the system to notify a device driver to flush any data to 
  3775. the device and prepare to shutdown. 
  3776.  
  3777. The driver is called twice, once for a Start Shutdown and then again for an End 
  3778. Shutdown. The function code is 0 for the Start Shutdown call and 1 for the End 
  3779. Shutdown call. 
  3780.  
  3781. Level 2 device drivers are called with the Shutdown request. Level 3 drivers 
  3782. are only called if the shutdown flag of the Capabilities field is set in the 
  3783. Device Header. 
  3784.  
  3785.  
  3786. ΓòÉΓòÉΓòÉ 9.18. 1DH/ Get Driver Capabilities ΓòÉΓòÉΓòÉ
  3787.  
  3788. Get a disk device driver's capabilities. 
  3789.  
  3790. Format Of Request Packet 
  3791.  
  3792.     struct {                     // Get Driver Capabilities
  3793.       UCHAR      res[3];         // reserved, must be 0
  3794.       FARPOINTER CapStruct;      // 16:16 pointer to DCS
  3795.       FARPOINTER VolCharStruct;  // 16:16 pointer to VCS
  3796.       } GetDriverCaps;
  3797.  
  3798. Comments 
  3799.  
  3800. This command returns the functional capabilities of the driver for device 
  3801. drivers supporting the Extended Device Driver Interface. 
  3802.  
  3803. This command is issued by the system to see whether the driver supports the 
  3804. scatter/gather protocol. The driver must initialize this structure. The first 
  3805. pointer is a 16:16 pointer to the Driver Capabilities Structure, and the second 
  3806. pointer is 1 16:16 pointer to the Volume Characteristics Structure. Refer to 
  3807. Chapter 12 for more detailed information on this command and its associated 
  3808. data structures. 
  3809.  
  3810.  
  3811. ΓòÉΓòÉΓòÉ 9.19. 1FH / CMDInitComplete ΓòÉΓòÉΓòÉ
  3812.  
  3813. Notify device driver that all PDDs and IFS drivers have been loaded. 
  3814.  
  3815. Format of Request Packet 
  3816.  
  3817. No Parameters 
  3818.  
  3819. Comments 
  3820.  
  3821. This command notifies the device driver that all drivers have been loaded, 
  3822. allowing the device driver to initiate any driver-to-driver communications or 
  3823. initialization. This command removes any problems associated with the order in 
  3824. which device drivers appear in the CONFIG.SYS file. 
  3825.  
  3826. This command is issued by the system only if the device driver is a level 3 
  3827. driver and has set bit 4 in the Capabilities Bit Strip word in the device 
  3828. header. 
  3829.  
  3830.  
  3831. ΓòÉΓòÉΓòÉ 10. Chapter 7 - A Simple OS/2 Physical Device Driver ΓòÉΓòÉΓòÉ
  3832.  
  3833. This chapter outlines the operation of an actual OS/2 Physical Device Driver 
  3834. (PDD). PDDs are the only type of drivers that can interface directly with 
  3835. adapter or system hardware. Chapter 5 discussed the various parts and design of 
  3836. an OS/2 PDD. This chapter will bring the parts together to form a PDD that can 
  3837. be loaded and tested under OS/2. 
  3838.  
  3839.  
  3840. ΓòÉΓòÉΓòÉ 10.1. Device Driver Specifications ΓòÉΓòÉΓòÉ
  3841.  
  3842. The requirement for this device driver is to perform I/O to an 8-bit parallel 
  3843. port, a common requirement. Although this device driver is designed for the 
  3844. 8255 parallel chip, it can easily be modified for any other type of 8-bit 
  3845. parallel adapter. This driver performs the I/O using the standard DosRead and 
  3846. DosWrite, and also shows how to perform the I/O using IOCtls. It is a good 
  3847. example of handling the differences between standard device driver request and 
  3848. IOCtls. 
  3849.  
  3850. Parallel adapters are frequently used for reading switches or other pieces of 
  3851. hardware which cause single bits to be set or clear. I've added an additional 
  3852. function to this device driver to show how an OS/2 device driver can be written 
  3853. to wait for a single bit to be set or clear without using interrupts or 
  3854. compromising system performance. Writing a similar device driver under DOS 
  3855. would be simple. Since DOS runs only one program at a time, the program could 
  3856. wait around forever for the particular bit to be set. OS/2, however, runs many 
  3857. programs at the same time, and cannot afford to wait around for a bit to be set 
  3858. while keeping all other programs dormant. To accomplish this without polling, 
  3859. the OS/2 device driver hooks a timer interrupt, and reads the port at every 
  3860. tick of the OS/2 system clock (31.25 milliseconds). Between each clock tick, 
  3861. the driver is either idle or blocked by an application request, so other 
  3862. threads continue to run. 
  3863.  
  3864. It is important to note that the amount of memory available for the stack in a 
  3865. device driver is extremely small, approximately 4K bytes, so it is important to 
  3866. keep the amount of local variables at a minimum. 
  3867.  
  3868. The complete listing of this device driver can be found in the Appendix C. 
  3869.  
  3870.  
  3871. ΓòÉΓòÉΓòÉ 10.2. Application Program Design ΓòÉΓòÉΓòÉ
  3872.  
  3873. When the application is first started, it opens the device driver with a 
  3874. DosOpen API call described in Example 7-1. 
  3875.  
  3876. .
  3877. .
  3878. if ((RetCode=DosOpen("DIGIO$",
  3879.     &digio_handle,
  3880.     &ActionTaken,
  3881.     FileSize,
  3882.     FileAttribute,
  3883.     FILE_OPEN,
  3884.     OPEN_SHARE_DENYNONE | OPEN_FLAGS_FAIL_ON_ERROR
  3885.     | OPEN_ACCESS_READWRITE,Reserved)) !=0)
  3886.        printf("\nopen error = %d",RetCode);
  3887. .
  3888. .
  3889.  
  3890. Example 7-1. Application call to open the driver. 
  3891.  
  3892. If successful, the DosOpen call returns a handle to the application which it 
  3893. can use for subsequent access to the device driver. A handle is nothing more 
  3894. than a special cookie that OS/2 uses to allow access to a particular driver. 
  3895.  
  3896.  
  3897. ΓòÉΓòÉΓòÉ 10.3. Device Driver Operation ΓòÉΓòÉΓòÉ
  3898.  
  3899. Refer to the device driver source code in Appendix C. Note the Device Header 
  3900. and the name assigned to the driver. For this example, the driver name has been 
  3901. assigned DIGIO$. The name must be eight characters in length, and must be 
  3902. space-padded for up to eight character positions. The '$' character was used in 
  3903. case a file or directory had the same name as the driver, for instance, 
  3904.  
  3905. \drivers\digio.
  3906.  
  3907. INIT
  3908.  
  3909. In the INIT section in Example 7-2, the DevHlp routine SetTimer is called to 
  3910. register the timer handler we will use to periodically check a bit from the 
  3911. parallel port. If the SetTimer call fails, the driver returns a failure to the 
  3912. kernel and gives up the memory it had occupied during initialization. If the 
  3913. call was successful, the driver displays a sign-on message and returns the DONE 
  3914. status to the kernel. The INIT section also initializes the 8255 parallel chip 
  3915. to setup port address base'0 as the read-port address, and base'1 as the 
  3916. write-port address. 
  3917.  
  3918. As soon as the timer handler is registered, the timer handler begins receiving 
  3919. timer interrupts every 31.25 milliseconds. The ReadID variable is used to 
  3920. ignore timer interrupts when no driver requests are pending. 
  3921.  
  3922. int Init(PREQPACKET rp)
  3923. {
  3924.     // store DevHlp entry point
  3925.  
  3926.     DevHlp = rp->s.Init.DevHlp;
  3927.  
  3928.     // install timer handler
  3929.  
  3930.     if(SetTimer((PFUNCTION)TIMER_HANDLER)) {
  3931.  
  3932.       // if we failed, effectively deinstall driver with cs+ds=0
  3933.  
  3934.       DosPutMessage(1, 8, devhdr.DHname);
  3935.       DosPutMessage(1,strlen(FailMessage),FailMessage);
  3936.       rp->s.InitExit.finalCS = (OFF) 0;
  3937.       rp->s.InitExit.finalDS = (OFF) 0;
  3938.       return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  3939.       }
  3940.  
  3941.     // configure 8255 parallel chip
  3942.  
  3943.     outp (DIGIO_CONFIG,0x91);
  3944.  
  3945.     // output initialization message
  3946.  
  3947.     DosPutMessage(1, 2, CrLf);
  3948.     DosPutMessage(1, 8, devhdr.DHname);
  3949.     DosPutMessage(1, strlen(InitMessage1), InitMessage1);
  3950.     DosPutMessage(1, strlen(InitMessage2), InitMessage2);
  3951.  
  3952.     // send back our code and data end values to os/2
  3953.  
  3954.     if (SegLimit(HIUSHORT((void far *) Init),
  3955.       &rp->s.InitExit.finalCS) || SegLimit(HIUSHORT((void far *)
  3956.       InitMessage2), &rp->s.InitExit.finalDS))
  3957.         Abort();
  3958.     return(RPDONE);
  3959. }
  3960.  
  3961. Example 7-2. INIT section. 
  3962.  
  3963. OPEN 
  3964.  
  3965. When the application program is started, it issues a DosOpen call to the 
  3966. kernel, which routes it to the driver via an OPEN Request Packet. If the 
  3967. DosOpen is successful, the kernel returns a handle to the application for 
  3968. subsequent driver access. When the driver receives the OPEN Request Packet, 
  3969. (see Example 7-3),  it checks to see whether the driver had been opened prior 
  3970. to this call.  This might happen if more than one thread of an application 
  3971. opened the driver.  If the driver had not been opened, it gets the PID of the 
  3972. opening program and saves it for later use.  It then bumps the open counter and 
  3973. returns DONE to the kernel.  The DONE status with no errors is mapped to the 
  3974. standard "no error" return to the DosOpen call, and returned to the 
  3975. application.  If the open count was greater than zero, the PID of the opening 
  3976. program is compared to the previously saved PID to see if they are the same. 
  3977. If the new PID is not the same as the old PID, the request is rejected by 
  3978. sending the BUSY status back to the kernel.  The kernel maps the return to a 
  3979. standard return code and sends that code to the application as a failure.  In 
  3980. all cases, whether errors occurred or not, the driver must return with the DONE 
  3981. status. 
  3982.  
  3983. case RPOPEN:                 // 0x0d open driver
  3984.  
  3985.   // get current processes' id
  3986.  
  3987.   if (GetDOSVar(2,&ptr))
  3988.          return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  3989.  
  3990.   // get process info
  3991.  
  3992.   liptr = *((PLINFOSEG far *) ptr);
  3993.  
  3994.   // if this device never opened, can be opened by anyone
  3995.  
  3996.   if (opencount == 0)      // first time this dev opened
  3997.   {
  3998.       opencount=1;         // bump open counter
  3999.       savepid = liptr->pidCurrent; // save current PID
  4000.   }
  4001.   else
  4002.   {
  4003.       if (savepid != liptr->pidCurrent) // another proc
  4004.           return (RPDONE | RPERR | ERROR_NOT_READY);//err
  4005.       ++opencount;         // bump counter, same pid
  4006.   }
  4007.   return (RPDONE);
  4008.  
  4009. Example 7-3. OPEN section. 
  4010.  
  4011. CLOSE 
  4012.  
  4013. The driver will receive a close Request Packet as a result of a DosClose API 
  4014. call from the application, or from the kernel in the event that the application 
  4015. was terminated by a <cntl-c>, <cntl-break> or other fault. In the CLOSE 
  4016. section, (see Example 7-4),  the driver checks the PID of the closing 
  4017. application to make sure that it has the same PID as the program that opened 
  4018. it.  If not, the request is rejected by returning an error to the kernel.  If 
  4019. it is the same, it was a valid close request, so the driver decrements the open 
  4020. counter and returns the DONE status to the kernel. 
  4021.  
  4022. case RPCLOSE:                // 0x0e DosClose,ctl-C, kill
  4023.  
  4024.     // get process info of caller
  4025.  
  4026.     if (GetDOSVar(2,&ptr))
  4027.         return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  4028.  
  4029.     // get process info from os/2
  4030.  
  4031.     liptr= *((PLINFOSEG far *) ptr); // ptr to linfoseg
  4032.  
  4033.     //
  4034.     make sure that the process attempting to close this device
  4035.     is the one that originally opened it and the device was
  4036.     open in the first place.
  4037.  
  4038.  
  4039.     if (savepid != liptr->pidCurrent || opencount == 0)
  4040.         return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  4041.  
  4042.     --opencount;             // close counts down open cntr
  4043.     return (RPDONE);         // return 'done' status
  4044.  
  4045. Example 7-4. CLOSE section. 
  4046.  
  4047. IOCtls 
  4048.  
  4049. The IOCtl Request Packets are received as a result of a DosDevIOCtl API call 
  4050. from the application. In this example, the driver supports three IOCtls. They 
  4051. are read a byte from a port, write a byte to a port, and read a port with wait. 
  4052.  
  4053. The IOCtl section first checks to make sure that the category is correct for 
  4054. this driver. Each device driver should have its own category, assigned by the 
  4055. driver writer. Categories from 0 to 127 are reserved for OS/2, and categories 
  4056. 128-255 are available for use by special drivers. You should avoid using 
  4057. category 128, however, as this category is sometimes used by OS/2 for drivers 
  4058. such as VDISK.SYS or OEMHLP. There are some cases where the category of a 
  4059. device driver might be the same as the category for an existing OS/2 device 
  4060. driver. An example would be a driver that replaced the COM01.SYS or COM02.SYS 
  4061. serial driver, or one that augmented an existing device driver. An example of 
  4062. this might be a device driver that adds support for COM5-COM12. Since certain 
  4063. IOCtls of a particular category are used to perform operations such as setting 
  4064. parity, changing the baud rate or the character length, the replacement driver 
  4065. should support the same number and type of IOCtl requests. 
  4066.  
  4067. If the category is not valid, the driver returns the DONE status to the kernel 
  4068. without performing any operations. It is generally acceptable to ignore 
  4069. unrecognized IOCtl requests, because the kernel will, from time to time, issue 
  4070. IOCtls to your driver which your driver does not support. 
  4071.  
  4072. If the category is valid, the driver checks the IOCtl function code. 
  4073.  
  4074. CASE 0x01 
  4075.  
  4076. If the IOCtl request is a 1, the write-port function has been requested (see 
  4077. Example 7-5). The driver calls the DevHlp routine VerifyAccess with the virtual 
  4078. address of the IOCtl parameter buffer to verify that the caller owns the memory 
  4079. that it points to.  It also checks to see that the application has the correct 
  4080. read and write privileges.  If the address is valid, the driver copies the byte 
  4081. to be output from the application, using a simple virtual-to-virtual copy. 
  4082. Using the standard run-time library routine outp, the driver writes the byte to 
  4083. the particular port.  The driver then sends the DONE status back to the kernel 
  4084. and exits. 
  4085.  
  4086.  case 0x01:               // write byte to digio port
  4087.  
  4088.    // verify caller owns this buffer area
  4089.  
  4090.    if(VerifyAccess(
  4091.    SELECTOROF(rp->s.IOCtl.parameters), // selector
  4092.    OFFSETOF(rp->s.IOCtl.parameters),   // offset
  4093.    1,                                  // 1 byte
  4094.    0) )                                // read only
  4095.        return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  4096.  
  4097.    if(MoveBytes(rp->s.IOCtl.parameters,(FARPOINTER)&output_char,1))
  4098.        return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  4099.  
  4100.    outp(DIGIO_OUTPUT,output_char);     //send to digio
  4101.  
  4102.    return (RPDONE);
  4103.  
  4104. Example 7-5. IOCtl 0x01, write port. 
  4105.  
  4106. CASE 0x02 
  4107.  
  4108. If the IOCtl code was 2, read with wait, the driver performs the identical 
  4109. operations to the previous IOCtl. (see Example 7-6). In this IOCtl, the 
  4110. application sends the driver a bit to wait for, and the driver will not return 
  4111. until that particular bit becomes set. 
  4112.  
  4113. First, the driver verifies the IOCtl virtual buffer pointer to make sure that 
  4114. the application owns the memory. Note that in this particular IOCtl, the data 
  4115. buffer pointer was used and not the parameter buffer pointer. The data buffer 
  4116. contains not only the port address to read from, but the space for the data 
  4117. read by the driver. Either buffer area can be used for reading or writing data. 
  4118. In this case, the data buffer was used for read IOCtls and the parameter buffer 
  4119. was used for write IOCtls. Which buffers are used and how they are interpreted 
  4120. is entirely up to the driver writer. 
  4121.  
  4122. Since the driver will Block until completion, it must lock down the 
  4123. applications buffer to ensure it is still there when the driver is UnBlocked. 
  4124. Otherwise, the buffer addresses previously UnBlocked might not be valid due to 
  4125. swapping. Once the memory has been verified and locked, the data is transferred 
  4126. from the application to the driver. In this driver, the data is only one byte 
  4127. in size, which contains the bit to wait for. Next, the variable ReadID is cast 
  4128. to a ULONG of the Request Packet pointer to be used as an ID for the DevHlp 
  4129. Block call. The driver then Blocks with a -1L for a time-out, which indicates 
  4130. that the driver will wait forever (no timeout). When the Block returns, it was 
  4131. either the result of a signal, such as <cntl-c>, or a call to the DevHlp Run 
  4132. routine with the same 32- bit ID used for the Block. The driver checks the 
  4133. return code from the Block. If the error code is a 2, which means a <cntl-c> 
  4134. caused the return from the Block, the driver returns 
  4135. ERROR_CHAR_CALL_INTERRUPTED to the kernel. If the error code was not a 2, the 
  4136. driver assumes that it was a valid Run call that caused the driver to become 
  4137. UnBlocked. The driver copies the result of the port read to the application, 
  4138. UnBlocked the caller's memory and returns the DONE status to the kernel. How 
  4139. the data is actually read from the I/O port is detailed in the Timer Handler 
  4140. section in Example 7-9. The driver copies the result of the port read to the 
  4141. application. 
  4142.  
  4143. Note that, in this IOCtl, the device driver locked the application's buffer to 
  4144. prevent it from being swapped out. This is necessary when the device driver 
  4145. issues a DevHlp Block request, but is not necessary in the other two IOCtls, 
  4146. where no Blocking occurs. 
  4147.  
  4148. case 0x02:               // read byte w/wait from port
  4149.  
  4150.    // verify caller owns this buffer area
  4151.  
  4152.    if(VerifyAccess(
  4153.    SELECTOROF(rp->s.IOCtl.buffer), // selector
  4154.    OFFSETOF(rp->s.IOCtl.buffer),   // offset
  4155.    1,                              // 1 bytes)
  4156.    0))                             // read only
  4157.       return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  4158.  
  4159.    // lock the segment down temp
  4160.  
  4161.    if(LockSeg(
  4162.    SELECTOROF(rp->s.IOCtl.buffer), // selector
  4163.    1,                              // lock forever
  4164.    0,                              // wait for seg loc
  4165.    (PLHANDLE) &lock_seg_han))      // handle returned
  4166.       return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  4167.  
  4168.    if(MoveBytes(rp->s.IOCtl.parameters,(FARPOINTER)&input_mask,1))
  4169.        return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  4170.  
  4171.    // wait for bit to be set
  4172.  
  4173.    ReadID = (ULONG)rp;
  4174.    if (Block(ReadID,-1L,0,&err))
  4175.      if (err == 2)
  4176.        return(RPDONE | RPERR | ERROR_CHAR_CALL_INTERRUPTED);
  4177.  
  4178.    // move result to users buffer
  4179.  
  4180.    if(MoveBytes((FARPOINTER)&input_char,rp->s.IOCtl.buffer,1))
  4181.         return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  4182.  
  4183.    // unlock segment
  4184.  
  4185.    if(UnLockSeg(lock_seg_han))
  4186.        return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  4187.  
  4188.    return (RPDONE);
  4189.  
  4190. Example 7-6. IOCtl 0x02. 
  4191.  
  4192. CASE 0x03 
  4193.  
  4194. The purpose of this case is to provide a read without wait. (see Example 7-7). 
  4195. Instead of waiting for a bit to be set as in IOCtl 0x02, this IOCtl returns 
  4196. immediately with the value of a port. Instead of Blocking, the driver calls the 
  4197. run-time library routine inp to get the contents of the port and sends the data 
  4198. back to the application. 
  4199.  
  4200. case 0x03:               // read byte immed digio port
  4201.  
  4202.     // verify caller owns this buffer area
  4203.  
  4204.     if(VerifyAccess(
  4205.     SELECTOROF(rp->s.IOCtl.buffer), // selector
  4206.     OFFSETOF(rp->s.IOCtl.buffer),   // offset
  4207.     1,                              // 1 byte
  4208.     0))                             // read only
  4209.         return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  4210.  
  4211.     input_char = inp(DIGIO_INPUT);  // get data
  4212.  
  4213.     if(MoveBytes((FARPOINTER)&input_char,rp->s.IOCtl.buffer,1))
  4214.         return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  4215.  
  4216.     return (RPDONE);
  4217.  
  4218. Example 7-7. IOCtl 0x03. 
  4219.  
  4220. READ And WRITE 
  4221.  
  4222. The READ and WRITE sections are entered as the result of a DosRead or DosWrite 
  4223. standard driver request from the application. The use of the standard read and 
  4224. write requests in Example 7-8 is shown as an example to contrast the 
  4225. differences of the standard READ and WRITE functions with the IOCtl read and 
  4226. write functions.  The READ section performs the exact same operation as the 
  4227. IOCtl function 0x03, read without wait, and the WRITE section does the same for 
  4228. IOCtl function 0x01, write a byte.  Either call will perform the same 
  4229. operation.  Instead of issuing an IOCtl request to write a byte to a port, the 
  4230. application can issue a DosWrite with the byte to be written. Instead of 
  4231. issuing an IOCtl function 0x03, the application can issue a DosRead. 
  4232.  
  4233. The standard READ and WRITE sections are slightly different than their IOCtl 
  4234. counterparts. First, the application's buffer address in the Request Packet is 
  4235. the physical address, not the virtual address, and second, OS/2 verifies and 
  4236. locks the buffer segment prior to calling the device driver. Since our data 
  4237. transfer routine requires virtual pointers, the device driver calls the 
  4238. PhysToVirt DevHlp to convert the physical address to a virtual address and the 
  4239. data is transferred. 
  4240.  
  4241. case RPREAD:                  // 0x04
  4242.  
  4243.    rp->s.ReadWrite.count = 0;       // in case we fail
  4244.  
  4245.    input_char = inp(DIGIO_INPUT);   // get data
  4246.  
  4247.    if (PhysToVirt( (ULONG) rp->s.ReadWrite.buffer,
  4248.       1,0,&appl_ptr))
  4249.         return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  4250.  
  4251.    if (MoveBytes((FARPOINTER)&input_char,appl_ptr,1))
  4252.         return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  4253.  
  4254.    rp->s.ReadWrite.count = 1;       // one byte read
  4255.    return (RPDONE);
  4256.  
  4257.  case RPWRITE:                // 0x08
  4258.  
  4259.    rp->s.ReadWrite.count = 0;
  4260.  
  4261.    if (PhysToVirt( (ULONG) rp->s.ReadWrite.buffer,
  4262.       1,0,&appl_ptr))
  4263.         return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  4264.  
  4265.    if (MoveBytes(appl_ptr,(FARPOINTER)&output_char,1))
  4266.         return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  4267.  
  4268.    outp (DIGIO_OUTPUT,output_char); // send byte
  4269.  
  4270.    rp->s.ReadWrite.count = 1;       // one byte written
  4271.    return (RPDONE);
  4272.  
  4273. Example 7-8. READ and WRITE section. 
  4274.  
  4275.  
  4276. ΓòÉΓòÉΓòÉ 10.4. Timer Handler ΓòÉΓòÉΓòÉ
  4277.  
  4278. In CASE 0x02, the driver blocks waiting for a particular bit to be set before 
  4279. returning to the caller. Other threads in the system will run only when the 
  4280. driver completes its job and returns DONE to the kernel, or when the driver 
  4281. becomes Blocked. Recall earlier that SetTimer was called to hook the OS/2 timer 
  4282. interrupt, and that access to the timer handler was controlled by the variable 
  4283. ReadID. In CASE 0x02, the ReadID was set to a ULONG cast of the Request Packet 
  4284. pointer. Since the ReadID is no longer zero, each time that the timer handler 
  4285. (see Example 7-9)  is entered, the driver can do an inp of the parallel port, 
  4286. "and" it to the bit mask, and if non-zero, run the Blocked driver thread. The 
  4287. input port value is checked every tick of the OS/2 system clock, or every 31.25 
  4288. milliseconds. If the bit is not set, the driver will block forever until a 
  4289. <cntl-c> or <cntl-break> is detected, or the bit finally becomes set. If set, 
  4290. the driver clears the timer handler entry flag, ReadID. It then calls the Run 
  4291. DevHlp to UnBlock the driver Strategy thread, which set the DONE status in the 
  4292. Request Packet and returns to the OS/2 kernel. 
  4293.  
  4294. timr_handler()
  4295. {
  4296.  
  4297.    if (ReadID != 0) {
  4298.  
  4299.       // read data from port
  4300.  
  4301.       input_char = inp(DIGIO_INPUT );   // get data
  4302.  
  4303.       if ((input_char && input_mask) !=0) {
  4304.          Run (ReadID);
  4305.          ReadID=0L;
  4306.          }
  4307.     }
  4308. }
  4309.  
  4310. Example 7-9. Timer handler. 
  4311.  
  4312.  
  4313. ΓòÉΓòÉΓòÉ 11. Chapter 8 - The Micro Channel Bus ΓòÉΓòÉΓòÉ
  4314.  
  4315. The Micro Channel bus is found on most IBM PS/2 machines and on Micro Channel 
  4316. machines supplied by other manufacturers such as Reply and NCR. The Micro 
  4317. Channel bus provides increased speeds, interrupt sharing, full 32-bit data path 
  4318. and increased noise immunity. Current specifications for Micro Channel II 
  4319. provide for transfers at speeds of 160MB per second. 
  4320.  
  4321.  
  4322. ΓòÉΓòÉΓòÉ 11.1. Micro Channel Adapter Cards ΓòÉΓòÉΓòÉ
  4323.  
  4324. Micro Channel adapters have no interrupt or address jumpers. Information about 
  4325. the adapter, such as interrupt level and memory-mapped address, is stored on 
  4326. the board in a set of nonvolatile registers called the Programmable Option 
  4327. Select, or POS, registers. The information stored in the POS registers is 
  4328. either factory-set or configured by a setup disk supplied by the manufacturer. 
  4329. On an IBM PS/2, this is usually done with the IBM PS/2 Reference Diskette. 
  4330.  
  4331. The POS registers are not directly accessible to a program, so the driver can't 
  4332. get at them by doing simple "IN" and "OUT" instructions. A special programmable 
  4333. switch must be set to allow direct register access to the configuration 
  4334. program. The driver must, however, get the contents of the POS registers in 
  4335. order to configure itself properly. Once the POS registers are "visible", they 
  4336. can be accessed starting at I/O port  address 0x100. 
  4337.  
  4338. Normally, the driver accesses the POS registers using the PS/2 Advanced BIOS, 
  4339. or ABIOS, routines. ABIOS is a set of BIOS routines that are executable in the 
  4340. protect mode. ABIOS routines provide a device-independent access to supported 
  4341. devices through a logical ID, or LID. The driver obtains a LID from the ABIOS 
  4342. by a call to the GetLIDEntry DevHlp routine. Once the driver has the LID, it 
  4343. can use the LID to access the board registers. 
  4344.  
  4345. The Micro Channel bus is unique in that the position of each adapter in the 
  4346. motherboard or planar is important. Unlike the ISA bus where boards can be 
  4347. placed in any slot, each slot in the Micro Channel machine is addressable. For 
  4348. this reason, calls to the ABIOS routines to read the POS registers of a 
  4349. particular adapter must contain an argument specifying the slot number of that 
  4350. adapter. Slot 0 is the planar, and the remaining slots are numbered starting at 
  4351. 1. Some of the largest PS/2 models, such as the IBM PS/2 Model 80, contain 8 
  4352. slots. 
  4353.  
  4354.  
  4355. ΓòÉΓòÉΓòÉ 11.2. Micro Channel Adapter ID ΓòÉΓòÉΓòÉ
  4356.  
  4357. Each I/O card has a unique ID number, assigned by the manufacturer. IBM 
  4358. reserves IDs 8000-FFFF for its own use. These device ID numbers can be found in 
  4359. the first two POS registers, 0 and 1. The low byte is in POS register 0, the 
  4360. high byte in POS register 1. The rest of the POS register data is in POS 
  4361. registers 2-5. Thus POS register 0 can be read with an input from port address 
  4362. 0x100, and POS register 1 can be read from address 0x101. 
  4363.  
  4364. Beware of conflicting definitions. Since the card ID can't be changed, the 
  4365. first available POS register, which is actually POS register 2, is sometimes 
  4366. referred to as POS register 0. 
  4367.  
  4368. During driver INIT, it is a good idea to search the planar for a card with the 
  4369. correct ID for the device driver before trying to initialize the driver. Once 
  4370. an adapter is found, the POS registers of the adapter can be accessed. ABIOS 
  4371. requests must be formatted into a special structure called an ABIOS Request 
  4372. Block. Refer to the IBM Personal System/2 BIOS Interface Technical Reference 
  4373. for more detailed information on ABIOS Request Blocks and the various types of 
  4374. ABIOS requests. 
  4375.  
  4376. Since device drivers for the Micro Channel bus differ slightly from their ISA 
  4377. bus counterparts, it is sometimes advantageous to write one device driver that 
  4378. will handle both a Micro Channel and ISA version of a particular adapter. The 
  4379. driver can check to see if the machine has a Micro Channel bus, and if so, read 
  4380. the required driver configuration information from the POS registers. If the 
  4381. machine has an ISA bus, the driver can set hard-coded values for the driver 
  4382. configuration parameters, or can read them from the DEVICE= statement in the 
  4383. CONFIG.SYS entry for the driver. Recall from Chapter 6 that one of the pointers 
  4384. sent in the INIT request packet is the address of the parameters from the 
  4385. DEVICE= line in CONFIG.SYS. This allows the user with an ISA bus system to 
  4386. enter a line such as "DEVICE=DRIVER.SYS 3E8 D8000" in the CONFIG.SYS file, 
  4387. where 3E8 is the base port address and D8000 is the memory-mapped adapter 
  4388. address. The driver can parse the parameters, convert them to numeric values, 
  4389. and use them in the driver as actual configuration parameters. 
  4390.  
  4391. The code shown in Example 8-1 shows how to determine whether the system has a 
  4392. Micro Channel or ISA bus, and if Micro Channel, how to search the bus for a 
  4393. particular device ID and read its POS registers.  If the system has an ISA bus, 
  4394. the parameters are read from the DEVICE= line in CONFIG.SYS. 
  4395.  
  4396. Note that the ABIOS command used to read the POS registers from the card is 
  4397. READ_POS_REGS_CARD. This command specifies that the POS register contents be 
  4398. read directly from the adapter. PS/2 computers keep a copy of the current 
  4399. adapter configuration in NVRAM. When the system is powered up, the Power On 
  4400. Self Test routine, or POST, checks the installed adapter IDs against the 
  4401. current NVRAM configuration. If a difference is found, the POST issues an error 
  4402. message on the screen directing the user to run the setup program. 
  4403.  
  4404. Occasionally, a device driver may reprogram a Micro Channel adapter "on the 
  4405. fly". For example, assume the device driver had to perform Binary Synchronous 
  4406. (BiSync) communications using a modem that could only dial using the High level 
  4407. Data Link Control (HDLC) protocol. The IBM Multiprotocol Adapter, or MPA is an 
  4408. example of an adapter that supports several modes of operation. It supports 
  4409. asynchronous, BiSync and HDLC protocols, but its POS registers can only be 
  4410. configured for one type of protocol at one time. The MPA adapter's mode of 
  4411. operation is determined by the POS register settings, which are normally be 
  4412. changed only with the PS/2 Reference Diskette. 
  4413.  
  4414. The device driver for this application rewrites the POS registers on the fly. 
  4415. The device driver configures the adapter for normal BiSync operation and waits 
  4416. for a command to dial a number. When a dial command is received, the driver 
  4417. saves the contents of the MPA's POS registers and writes the HDLC configuration 
  4418. data to the POS registers. It initializes the HDLC controller, sends the dial 
  4419. information to the modem using the HDLC protocol and waits for a connection. 
  4420. When the modem is connected, the device driver rewrites the POS registers with 
  4421. the previously saved POS register data, initializing it back to BiSync 
  4422. operation. The result? Two adapters for the price of one. 
  4423.  
  4424. // Ex.INIT section, combination ISA and MicroChannel bus driver
  4425.  
  4426. // This driver is loaded in the config.sys file with the DEVICE=
  4427. // statement. For ISA configuration, the first parameter to the
  4428. // "DEVICE=" is the base port address. The next parameter is the
  4429. // board base address. All numbers are in hex. For Micro Channel
  4430. // configuration, the board address and port address are read
  4431. // from the board POS regs.
  4432. //
  4433.  
  4434. PHYSADDR    board_address;     // base board address
  4435. USHORT      port_address;      // base port address
  4436. USHORT      bus = 0;           // default ISA bus
  4437. REQBLK      ABIOS_r_blk;       // ABIOS request block
  4438. LIDBLK      ABIOS_l_blk;       // ABIOS LID block
  4439. USHORT      lid_blk_size;      // size of LID block
  4440. CARD        card[MAX_NUM_SLOTS+1];// array for IDs and POS reg
  4441. CARD        *pcard;            // pointer to card array
  4442. USHORT      matches = 0;       // match flag for card ID
  4443. USHORT      port1,port2;       // temp variables for addr calc
  4444.  
  4445. char     NoMatchMsg[]  = " no match for DESIRED card ID found.\r\n";
  4446. char     MainMsgMCA[]  = "\r\nOS/2 Micro Channel (tm) Device
  4447. Driver installed.\r\n";
  4448. char     MainMsg[] = "\r\nOS/2 ISA Device Driver installed.\r\n";
  4449.  
  4450. // prototypes
  4451.  
  4452. int      hex2bin(char);
  4453. USHORT   get_POS();
  4454. UCHAR    get_pos_data();
  4455. .
  4456. .
  4457. * Device Driver Strategy Section Here *
  4458. .
  4459. .
  4460. int  hex2bin(char c)
  4461. {
  4462.  if(c < 0x3a)
  4463.   return (c - 48);
  4464.  else
  4465.   return (( c & 0xdf) - 55);
  4466. }
  4467.  
  4468. USHORT get_POS(USHORT slot_num,USHORT far *card_ID,
  4469.        UCHAR far *pos_regs)
  4470. {
  4471. USHORT rc, i, lid;
  4472.  
  4473.     // get a POS LID
  4474.  
  4475.     if (GetLIDEntry(0x10, 0, 1, &lid))
  4476.         return (1);
  4477.  
  4478.     // Get the size of the LID request block
  4479.  
  4480.     ABIOS_l_blk.f_parms.req_blk_len = sizeof(struct lid_block_def);
  4481.     ABIOS_l_blk.f_parms.LID = lid;
  4482.     ABIOS_l_blk.f_parms.unit = 0;;
  4483.     ABIOS_l_blk.f_parms.function = GET_LID_BLOCK_SIZE;
  4484.     ABIOS_l_blk.f_parms.ret_code = 0x5a5a;
  4485.     ABIOS_l_blk.f_parms.time_out = 0;
  4486.  
  4487.     // make the actual ABIOS call
  4488.  
  4489.     if (ABIOSCall(lid,0,(void far *)&ABIOS_l_blk))
  4490.         return (1);
  4491.  
  4492.     lid_blk_size = ABIOS_l_blk.s_parms.blk_size;
  4493.  
  4494.     // Fill POS regs with 0 and card ID with FF
  4495.  
  4496.     *card_ID = 0xFFFF;
  4497.     for (i=0; i<NUM_POS_BYTES; i++) { pos_regs[i] = 0x00; };
  4498.  
  4499.     // Get the POS registers and card ID for the commanded slot
  4500.  
  4501.     ABIOS_r_blk.f_parms.req_blk_len = lid_blk_size;
  4502.     ABIOS_r_blk.f_parms.LID = lid;
  4503.     ABIOS_r_blk.f_parms.unit = 0;;
  4504.     ABIOS_r_blk.f_parms.function = READ_POS_REGS_CARD;
  4505.     ABIOS_r_blk.f_parms.ret_code = 0x5a5a;
  4506.     ABIOS_r_blk.f_parms.time_out = 0;
  4507.  
  4508.     ABIOS_r_blk.s_parms.slot_num = (UCHAR)slot_num & 0x0F;
  4509.     ABIOS_r_blk.s_parms.pos_buf = (void far *)pos_regs;
  4510.     ABIOS_r_blk.s_parms.card_ID = 0xFFFF;
  4511.  
  4512.     if (ABIOSCall(lid,0,(void far *)&ABIOS_r_blk))
  4513.        rc = 1;
  4514.      else {
  4515.        *card_ID = ABIOS_r_blk.s_parms.card_ID;// fill in ID
  4516.        rc = 0;
  4517.       }
  4518.  
  4519.     // give back the LID
  4520.  
  4521.     FreeLIDEntry(lid);
  4522.     return(rc);
  4523.  
  4524. }
  4525.  
  4526. UCHAR get_pos_data (int slot, int reg)
  4527. {
  4528.    UCHAR pos;
  4529.    CARD *cptr;
  4530.  
  4531.    cptr = &card[slot-1];            // set ptr to beg of array
  4532.    if (reg == 0)                    // card ID
  4533.       pos = LOUSHORT(cptr->card_ID);
  4534.    else
  4535.      if ( reg == 1)
  4536.       pos = HIUSHORT(cptr->card_ID);
  4537.    else
  4538.       pos = cptr->pos_regs[reg-2];  // POS data register
  4539.    return (pos);
  4540. }
  4541.  
  4542. // Device Initialization Routine
  4543.  
  4544. int Init(PREQPACKET rp)
  4545. {
  4546.     USHORT lid;
  4547.  
  4548.     register char far *p;
  4549.  
  4550.     // store DevHlp entry point
  4551.  
  4552.     DevHlp = rp->s.Init.DevHlp;// save DevHlp entry point
  4553.  
  4554.     if (!(GetLIDEntry(0x10, 0, 1, &lid))){// get LID for POS
  4555.       FreeLIDEntry(lid);
  4556.  
  4557.       // Micro Channel (tm) setup section
  4558.  
  4559.       bus = 1;                      // Micro Channel bus
  4560.  
  4561.       // Get the POS data and card ID for each of 8 slots
  4562.  
  4563.       for (i=0;i <= MAX_NUM_SLOTS; i++)
  4564.          get_POS(i+1,(FARPOINTER)&card[i].card_ID,
  4565.             (FARPOINTER)card[i].pos_regs);
  4566.  
  4567.       matches = 0;
  4568.       for (i=0, pcard = card; i <= MAX_NUM_SLOTS; i++, pcard++){
  4569.          if (pcard->card_ID == DESIRED_ID) {
  4570.             matches = 1;
  4571.             break;
  4572.             }
  4573.          }
  4574.  
  4575.       if (matches == 0) {           // no matches found
  4576.          DosPutMessage(1, 8, devhdr.DHname);
  4577.          DosPutMessage(1,strlen(NoMatchMsg),NoMatchMsg);
  4578.          rp->s.InitExit.finalCS = (OFF) 0;
  4579.          rp->s.InitExit.finalDS = (OFF) 0;
  4580.          return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  4581.          }
  4582.  
  4583.       // calculate the board address from the POS regs
  4584.  
  4585.       board_address = ((unsigned long) get_pos_data(i+1, 4)
  4586.       << 16) | ((unsigned long)(get_pos_data(i+1, 3) & 1) << 15);
  4587.  
  4588.       // calculate the port address from the POS regs data
  4589.  
  4590.       port1 = (get_pos_data(i+1, 3) << 8) & 0xf800;
  4591.       port2 = (get_pos_data(i+1, 2) << 3) & 0x07e0;
  4592.       port_address = (port1 | port2);
  4593.  
  4594.       }
  4595.    else
  4596.       {
  4597.       // ISA bus setup
  4598.       bus = 0;                      // ISA bus
  4599.  
  4600.     // get parameters, port addr and base mem addr
  4601.  
  4602.       for (p = rp->s.Init.args; *p && *p != ' ';++p);
  4603.       for (; *p == ' '; ++p);       // skip blanks after name
  4604.       if (*p)
  4605.        {
  4606.        port_address = 0;
  4607.        board_address=0;           // i/o port address
  4608.        for (; *p != ' '; ++p)     // get port address
  4609.        port_address = (port_address << 4) + (hex2bin(*p));
  4610.        for (; *p == ' '; ++p);    // skip blanks after address
  4611.        for (; *p != '\0'; ++p)    // get board address
  4612.        board_address = (board_address << 4) + (hex2bin(*p));
  4613.        }
  4614.     }
  4615.  
  4616.     if (bus)
  4617.        DosPutMessage(1,strlen(MainMsgMCA),MainMsgMCA);
  4618.     else
  4619.        DosPutMessage(1,strlen(MainMsg),MainMsg);
  4620.  
  4621.        // send back our end values to os/2
  4622.  
  4623.     if (SegLimit(HIUSHORT((void far *) Init),
  4624.         &rp->s.InitExit.finalCS) ||
  4625.         SegLimit(HIUSHORT((void far *) MainMsg),
  4626.         &rp->s.InitExit.finalDS))
  4627.           Abort();
  4628.  
  4629.     return (RPDONE);
  4630. }
  4631.  
  4632. Example 8-1. ISA and Micro Channel INIT section. 
  4633.  
  4634.  
  4635. ΓòÉΓòÉΓòÉ 11.3. Accessing the POS Register During Debug ΓòÉΓòÉΓòÉ
  4636.  
  4637. While debugging an OS/2 Micro Channel device driver, it is sometimes necessary 
  4638. to access the POS registers directly without using the ABIOS routines. Under 
  4639. OS/2, the driver should always use the ABIOS routines to access the POS 
  4640. registers, as they serialize access to the adapter. During debug, however, the 
  4641. POS register contents can be checked by using simple IN and OUT instruction 
  4642. from the kernel debugger. 
  4643.  
  4644. The -CD SETUP line, which enables the POS registers, is controlled by a 
  4645. register at I/O port address 96h. The POS registers for a particular card are 
  4646. enabled by performing an "OUT 96h,slot'7", where the slot is 0 for the 
  4647. motherboard and 1-8 for one of up to eight slots. Once a particular slot is 
  4648. enabled, the POS registers are visible with simple IN instructions. The POS 
  4649. registers are at the base address of 100h. POS register 0, which is the least 
  4650. significant bit of the adapter ID, can be read by an IN 100 command issued by 
  4651. the kernel debugger (see Chapter 13). POS register 1, the most significant byte 
  4652. of the adapter ID, can be found at address 101h. Other POS register data, which 
  4653. might contain such things as the adapter interrupt level, DMA arbitration 
  4654. level, or memory map, begins at address 102h. Only one slot can be enabled at a 
  4655. time. The -CD SETUP line is disabled by performing an OUT 96h,0. 
  4656.  
  4657.  
  4658. ΓòÉΓòÉΓòÉ 11.4. Micro Channel Interrupts ΓòÉΓòÉΓòÉ
  4659.  
  4660. Interrupts on ISA bus machines are edge-triggered and cannot be shared. Once an 
  4661. ISA bus adapter registers for a particular interrupt level, another driver 
  4662. cannot gain access to the same interrupt level. Device drivers that run on ISA 
  4663. bus machines must own their interrupt or interrupts exclusively, which severely 
  4664. limits the extendibility of ISA bus systems. With over half of the interrupts 
  4665. already assigned to system components such as the timer, hard disk, and floppy 
  4666. disk, not many interrupts are left over for other adapters. 
  4667.  
  4668. Under OS/2, the Micro Channel bus supports interrupt sharing of up to four 
  4669. adapters on the same interrupt level. Micro Channel device drivers can register 
  4670. for an interrupt level even if another device driver had previously signed up 
  4671. for it. This requires some minor changes in device driver design for the two 
  4672. different bus architectures. In a Micro Channel device driver, when registering 
  4673. the interrupt level with the SetIRQ call, the nonexclusive option is used so 
  4674. the interrupt may be shared. In an ISA bus device driver, the exclusive option 
  4675. is used because interrupts cannot be shared. In addition, the interrupt handler 
  4676. needs to be modified slightly to claim or "pass on" the interrupt to the next 
  4677. interrupt handler. A flowchart showing the differences between an ISA bus 
  4678. interrupt handler and a Micro Channel interrupt handler is shown in Figure 8-1. 
  4679. Figure 8-1. Micro Channel vs. ISA bus interrupt handler. 
  4680.  
  4681. Since any one the four adapters on a single interrupt level can cause an 
  4682. interrupt, the device driver's interrupt handler must have a way to tell the 
  4683. kernel that it accepts or denies responsibility for the interrupt. If the 
  4684. interrupt does not belong to this particular interrupt handler's device, the 
  4685. interrupt handler must set the carry flag (STC), and return to the kernel. If 
  4686. the interrupt belongs to the particular device, the interrupt handler must 
  4687. claim the interrupt by clearing the carry flag before returning to the kernel. 
  4688. If the kernel finds the carry flag set, it will call each of the interrupt 
  4689. handlers that have registered for that particular interrupt until one of the 
  4690. handlers claims the interrupt by clearing the carry flag. If the interrupt is 
  4691. not claimed, OS/2 will continue to call the registered interrupt handlers until 
  4692. one of them claims the interrupt by clearing the carry flag. 
  4693.  
  4694.  
  4695. ΓòÉΓòÉΓòÉ 12. Chapter 9 - OS/2 2.1 Virtual Device Drivers ΓòÉΓòÉΓòÉ
  4696.  
  4697. One of the shortcomings of OS/2 1.x was its inability to run DOS applications. 
  4698. Many of these DOS applications were written for the IBM PC and IBM XT 
  4699. computers, which were, by today's standards, fairly slow machines. To provide 
  4700. acceptable performance, these programs frequently accessed the system hardware 
  4701. and peripherals directly without using the BIOS or DOS system services. For 
  4702. example, instead of writing to the display with a DOS int system call, most 
  4703. programs wrote directly to video memory. Game programs frequently used 
  4704. processor-speed-dependent timing loops for making sounds or pausing between 
  4705. messages and screens. Other DOS programs reprogrammed the system timer circuit 
  4706. to generate voice-like sounds from the computer's speaker. 
  4707.  
  4708. DOS programs can write to any memory location without checking to see if that 
  4709. location is valid or being used by another program. A programming error under 
  4710. DOS will, at the worst, cause the system to crash and have to be rebooted. This 
  4711. is not generally a problem, as only one program can be running at one time. 
  4712. With OS/2, however, a system crash could represent a major problem, as many 
  4713. programs could be running at the time of the crash. The result could be a loss 
  4714. of data, corrupt files, and a host of other problems. 
  4715.  
  4716. To accommodate DOS applications, OS/2 1.x used a real mode session, referred to 
  4717. as the compatibility box, to run well-behaved DOS applications. Well-behaved 
  4718. DOS applications are those that do not directly manipulate the system hardware 
  4719. or devices, but use DOS system calls to perform their required operations. OS/2 
  4720. 1.x allowed only one real mode session to be active at one time. When the DOS 
  4721. program was running, the processor was in real mode, so a defective DOS 
  4722. application could still bring down the entire system. When the DOS session was 
  4723. switched to the background, it was frozen in its current state to prevent it 
  4724. from bringing down the system while an OS/2 application was running. 
  4725.  
  4726.  
  4727. ΓòÉΓòÉΓòÉ 12.1. The Virtual DOS Machine ΓòÉΓòÉΓòÉ
  4728.  
  4729. The Intel 80386 and 80486 processors have a built-in feature that allows real 
  4730. mode programs to run in their own one megabyte address space, isolated from the 
  4731. rest of the programs running on the system. This special mode is called the 
  4732. Virtual 8086 or V86 mode, and is used by OS/2 2.1 to run DOS applications in 
  4733. their own DOS Session. In OS/2 jargon, a DOS session in the V86 mode of the 
  4734. processor is called a Virtual DOS Machine, or VDM. OS/2 can support a large 
  4735. number of DOS VDMs, and the capability to do that is referred to as Multiple 
  4736. Virtual DOS Machines, or MVDMs. 
  4737.  
  4738. DOS programs run in their own VDM without knowledge of other programs running 
  4739. in the system. The V86 mode is a protected mode of operation, and it will 
  4740. terminate the DOS session if it attempts a memory reference outside of its own 
  4741. one megabyte space. In the V86 mode, an errant DOS application can trash its 
  4742. own DOS session, but cannot bring down the rest of the system. 
  4743.  
  4744. DOS programs that write directly to system hardware or devices are permitted to 
  4745. run in a DOS session. The DOS application does not have to be modified, but can 
  4746. run "out of the box." When the DOS program attempts to write directly to the 
  4747. system hardware or a system device, the operation is trapped by the kernel and 
  4748. routed to a Virtual Device Driver, or VDD. The VDD is a special driver that 
  4749. emulates the functions of a particular hardware device, such as the system 
  4750. timer, interrupt controller or communications port. The DOS application sees 
  4751. the VDD as the actual device, but direct access to the device is actually 
  4752. performed through a Physical Device Driver (PDD). 
  4753.  
  4754. The PDD performs the actual I/O and passes the results to the VDD, which in 
  4755. turn sends the results back to the DOS application. OS/2 2.1 is supplied with a 
  4756. set of VDDs that virtualize the standard system device services such a DMA, 
  4757. timer, COM ports, video, and PIC. 
  4758.  
  4759. When VDDs are loaded at boot time, the VDD claims ownership of the system 
  4760. resources it is responsible for while running in a VDM. The VDD can hook all 
  4761. I/O associated with a particular port or the interrupts associated with a 
  4762. particular IRQ. For example, the virtual COM driver, VCOM.SYS, claims ownership 
  4763. of I/O address 0x3f8, which is the address of COM1. A DOS program that attempts 
  4764. to perform direct I/O to 0x3f8 will be trapped by the COM VDD. The VDD must 
  4765. emulate the actual hardware device, and make the DOS application believe its 
  4766. talking directly to the device. 
  4767.  
  4768. If a DOS program attempts to access an I/O port which has not been claimed by a 
  4769. VDD, it is allowed to perform that I/O directly without going through a VDD. 
  4770. The DOS application can turn interrupts off, although OS/2 will turn the 
  4771. interrupts back on if the DOS program leaves them off too long. 
  4772.  
  4773. If an adapter can be shared by a protect mode application and a DOS 
  4774. application, a VDD should always be used to perform DOS I/O. Before performing 
  4775. I/O to the adapter, the VDD should first ask the PDD for permission to do so. 
  4776. The PDD and VDD should serialize access to the common adapter. 
  4777.  
  4778. Although VDMs can run DOS applications that access hardware directly, there are 
  4779. some limitations. Existing DOS block device drivers for disk and tape cannot be 
  4780. used in the standard VDM. For character drivers, only those that perform I/O by 
  4781. polling can be used. Standard DOS drivers for the clock and mouse are not 
  4782. permitted to be used. DOS  INT 21 requests are formatted into a standard OS/2 
  4783. Request Packets and sent to the PDD for disposition. 
  4784.  
  4785. VDMs, in which a specific version of DOS has been booted, can utilize existing 
  4786. DOS block device drivers. The block device should not be accessible to protect 
  4787. mode applications, so it must be dedicated to DOS operation. 
  4788.  
  4789. Since versions of DOS differ in functionality, a DOS Setting is provided to 
  4790. specify which version of DOS should be booted instead of the built-in DOS 
  4791. emulator. 
  4792.  
  4793. VDDs are loaded at system boot time, after any PDDs have been loaded and before 
  4794. the PM shell is started. The system first loads the base VDDs which are shared 
  4795. by multiple DOS sessions, such as the video virtual device driver, and then 
  4796. loads the installable VDDs from the DEVICE= line in CONFIG.SYS. Global code and 
  4797. data objects are loaded into low system memory to allow the PDD to call the VDD 
  4798. at interrupt time, regardless of the current process context. After the VDD is 
  4799. loaded, the VDDInit entry point is called to see if the load was performed 
  4800. without error. If so, the VDD returns TRUE, and if not, FALSE. 
  4801.  
  4802. Virtual Device Drivers use a set of C callable helper routines, called the 
  4803. Virtual Device Helper (VDH) to perform their operations. Unlike the PDD 
  4804. DevHlps, which are register-based, the VDH routines are C callable, and exist 
  4805. in a DLL. They use the 32-bit C calling convention. 
  4806.  
  4807.  
  4808. ΓòÉΓòÉΓòÉ 12.2. VDD Architecture ΓòÉΓòÉΓòÉ
  4809.  
  4810. The VDD is nothing more than a 32-bit DLL, and must contain one of the 
  4811. following: 
  4812.  
  4813. o swappable global data
  4814.  
  4815. o swappable instance data
  4816.  
  4817. o resident global code
  4818.  
  4819. o resident global data
  4820.  
  4821. o resident instance data
  4822.  
  4823. The VDD may also contain:
  4824.  
  4825. o initialization code
  4826.  
  4827. o initialization data
  4828.  
  4829. o swappable global code
  4830.  
  4831. A VDD that does not communicate with a PDD does not need a resident object 
  4832. section. Run-time memory can be private or shared. The typical VDD has a global 
  4833. code object, global data object, and a private instance data object. 
  4834.  
  4835. VDDs are loaded by the DOS emulation component after all of the PDDs have been 
  4836. loaded. When the VDD is loaded, the VDD entry point is called by OS/2 to 
  4837. initialize the VDD. The entry point of the DLL is defined by writing a small 
  4838. assembly language program, which calls the DLL initialization entry point. The 
  4839. last statement in the assembly language program should be an END statement, 
  4840. with the parameter to the END statement being the name of the entry point. If 
  4841. the name of the VDD initialization entry point is, for example, VDDInit, the 
  4842. last statement in the assembly language routine should be END VDDInit. The IBM 
  4843. C Set/2 Compiler now supports the pragma entry keyword which is used to specify 
  4844. the initialization entry point for VDDs written in C. 
  4845.  
  4846. After the VDD is loaded, the VDD entry point is called to see if the load was 
  4847. performed without error. If it was, the VDD returns TRUE, if not, the VDD 
  4848. returns FALSE. 
  4849.  
  4850.  
  4851. ΓòÉΓòÉΓòÉ 12.3. VDD Initialization ΓòÉΓòÉΓòÉ
  4852.  
  4853. The VDD performs initialization in a manner similar to the PDD. It verifies the 
  4854. presence of the hardware device, establishes contact with the corresponding 
  4855. PDD, reserves regions of linear memory containing device ROM and/or RAM, saves 
  4856. the current state of the device, and finally, sets hooks for DOS session 
  4857. events, such as session create, session destroy, and foreground/background 
  4858. switch requests. VDDs cannot make Ring 3 calls during initialization, and must 
  4859. use the Virtual Device Helper routines. 
  4860.  
  4861. When a DOS session is started, the DOS Session Manager calls the VDD, allowing 
  4862. it to perform a per-DOS session initialization. The VDD allocates memory 
  4863. regions and passes control to the DOS emulation kernel, which loads the DOS 
  4864. shell, usually COMMAND.COM. The DOS emulation kernel then calls the VDD session 
  4865. creation entry points, allowing the VDD to set up aliases to physical memory, 
  4866. and optionally to allocate a block of memory between 256K and RMSIZE for a LIM 
  4867. 4.0 alias window. 
  4868.  
  4869. When a DOS session is started, the DOS Session Manager calls each VDD that has 
  4870. registered a DOS session create hook. This allows VDDs to perform a per- 
  4871. DOS-session initialization. Control is then passed to the DOS emulation kernel, 
  4872. which loads the DOS shell, usually COMMAND.COM. At DOS session creation, the 
  4873. VDD may also: 
  4874.  
  4875. o initialize the virtual device state.
  4876.  
  4877. o initialize the ROM BIOS state.
  4878.  
  4879. o map memory.
  4880.  
  4881. o hook I/O ports.
  4882.  
  4883. o enable/disable I/O port trapping.
  4884.  
  4885. o hook the software interrupts.
  4886.  
  4887. o allocate per-DOS session memory.
  4888.  
  4889. The OS/2 Session Manager notifies the DOS Session Manager if the session is 
  4890. being switched. The DOS Session Manager notifies any VDD that has registered to 
  4891. get this event via the VDHInstallUserHook VDH call. Depending on the VDD type, 
  4892. different actions will be taken. In the case of the virtual video device 
  4893. driver, VVIDEO, the driver will appropriately disable or enable I/O port 
  4894. trapping for the video board and re-map the physical video memory to logical 
  4895. memory. The video will continue to be updated, but in logical video memory. 
  4896. When the session is switched back to the foreground, the logical memory is 
  4897. written to the physical video memory to update the display. 
  4898.  
  4899. When the DOS session is exited, the VDD must perform any clean-up that is 
  4900. necessary. This usually includes releasing any allocated memory and restoring 
  4901. the state of the device. The VDD termination entry points are called by the DOS 
  4902. Session Manager at DOS program termination time. 
  4903.  
  4904. OS/2 2.1 Virtual Device Drivers may only call OS/2 2.1 Physical Device Drivers 
  4905. that contain the "new level" bits. Older PDDs will return an error if called by 
  4906. a VDD. When a new level PDD receives an IOCtl, it must check the InfoSeg to 
  4907. determine whether it was called by a DOS session. If it was, it assumes that 
  4908. any pointers passed in IOCtl packets are in segment:offset format, computes the 
  4909. linear address directly (segment << 4 ' offset) and then uses the 
  4910. LinToGDTSelector to make a virtual address. 
  4911.  
  4912.  
  4913. ΓòÉΓòÉΓòÉ 12.4. DOS Settings ΓòÉΓòÉΓòÉ
  4914.  
  4915. OS/2 2.1 allows users to customize the configuration of a DOS session. Using 
  4916. the DOS Settings, the user can adjust certain DOS session parameters via the 
  4917. Desktop Manager's Settings menu for the DOS session. Device drivers must call 
  4918. the VDHRegisterProperty routine to register their settings. A VDD can call 
  4919. VDHQueryProperty at DOS session creation to get the value of the current DOS 
  4920. settings. The user can also change some of the settings while the DOS session 
  4921. is running, via a settings dialog box. The standard DOS settings are shown in 
  4922. Table 9-1. 
  4923.  
  4924. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  4925. ΓöéProperty  ΓöéType      ΓöéOperation                     Γöé
  4926. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4927. ΓöéBREAK     ΓöéBOOLEAN   ΓöéControls <cntl-c> checking in Γöé
  4928. Γöé          Γöé          Γöéthe INT21 path                Γöé
  4929. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4930. ΓöéFCBS      ΓöéINTEGER   ΓöéControls use of FCBs by errantΓöé
  4931. Γöé          Γöé          ΓöéDOS applications              Γöé
  4932. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4933. ΓöéDEVICE    ΓöéSTRING    ΓöéSpecifies a DOS character     Γöé
  4934. Γöé          Γöé          Γöédriver                        Γöé
  4935. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4936. ΓöéSHELL     ΓöéSTRING    ΓöéSpecifies the command         Γöé
  4937. Γöé          Γöé          Γöéinterpreter                   Γöé
  4938. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4939. ΓöéRMSIZE    ΓöéINTEGER   ΓöéSpecifies size of DOS memory  Γöé
  4940. Γöé          Γöé          Γöéarena                         Γöé
  4941. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  4942. Table 9-1. DOS settings. 
  4943.  
  4944.  
  4945. ΓòÉΓòÉΓòÉ 12.5. DOS Settings Registration ΓòÉΓòÉΓòÉ
  4946.  
  4947. At initialization time, the Virtual Device Driver must register any settings 
  4948. that it will need. This information is stored in the kernel, and used to 
  4949. support all property-related operations (see Table 9-2). 
  4950.  
  4951. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  4952. ΓöéName           ΓöéThe property name presented toΓöé
  4953. Γöé               Γöéthe user. The settings should Γöé
  4954. Γöé               Γöéhave common prefixes so that  Γöé
  4955. Γöé               Γöéthey appear sorted together.  Γöé
  4956. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4957. ΓöéOrdinal        ΓöéThe ordinal of the function   Γöé
  4958. Γöé               Γöéindependent of the name       Γöé
  4959. Γöé               Γöéstring.                       Γöé
  4960. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4961. ΓöéType           ΓöéThe property type. Boolean,   Γöé
  4962. Γöé               Γöéinteger, enumeration, and     Γöé
  4963. Γöé               Γöésingle and multiple line      Γöé
  4964. Γöé               Γöéstrings are supported.        Γöé
  4965. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4966. ΓöéFlags          ΓöéFlags control aspects of the  Γöé
  4967. Γöé               Γöéproperty, i.e., whether or notΓöé
  4968. Γöé               Γöéthey can be changed while the Γöé
  4969. Γöé               ΓöéDOS session is running.       Γöé
  4970. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4971. ΓöéDefault value  ΓöéThe value used if the user    Γöé
  4972. Γöé               Γöédoes not supply one.          Γöé
  4973. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4974. ΓöéValidation     ΓöéThis information allows the   Γöé
  4975. Γöéinformation    Γöéuser interface to validate    Γöé
  4976. Γöé               Γöéproperty values before sendingΓöé
  4977. Γöé               Γöéthem to the device driver.    Γöé
  4978. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  4979. ΓöéFunction       ΓöéThis function is used for     Γöé
  4980. Γöé               Γöévalidating string settings,   Γöé
  4981. Γöé               Γöéand for notifying the VDD whenΓöé
  4982. Γöé               Γöéthe user has changed a        Γöé
  4983. Γöé               Γöéproperty for a running DOS    Γöé
  4984. Γöé               Γöésession.                      Γöé
  4985. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  4986. Table 9-2. DOS settings information.  VDD to PDD Communications 
  4987.  
  4988. Since many VDDs virtualize or "mimic" hardware that generates interrupts, these 
  4989. drivers will generally have to interact with a PDD. The VDD uses the VDHOpenPDD 
  4990. VDH call to establish communication between the Virtual Device Driver and the 
  4991. Physical Device Driver. The two drivers exchange entry points, and are 
  4992. subsequently free to call each other using any type of protocol, including 
  4993. register-based entry points. Both drivers should also be aware of the shutdown 
  4994. protocol, in case the VDD has to shut down. 
  4995.  
  4996. VDDs can call PDDs via the OS/2 file system by using the VDHOpen, VDHWrite, 
  4997. VDHIOCtl, and VDHClose function calls. Using this method, a VDD can communicate 
  4998. with an existing PDD without requiring modification of the PDD. 
  4999.  
  5000. VDDs support Dynamic Linking, and thus can pass data back and forth to other 
  5001. VDDs via dynamic links. VDDs can also communicate with each other via the 
  5002. VDHOpenVDD, VDHRequestVDD, and VDHCloseVDD Virtual Device Helper routines. 
  5003.  
  5004.  
  5005. ΓòÉΓòÉΓòÉ 12.6. The Virtual COM Device Driver ΓòÉΓòÉΓòÉ
  5006.  
  5007. The Virtual COM Device Driver for OS/2 2.1, VCOM.SYS, allows for the emulation 
  5008. and virtualization of the 8250/16450 UART. It provides support for two virtual 
  5009. serial ports on ISA bus machines, and four ports on PS/2 and PS/2- compatible 
  5010. systems. VCOM.SYS does not support the 16550 UART. Due to the added overhead of 
  5011. context switching and system operation, the Virtual COM Device Driver only 
  5012. guarantees error-free operation at 240 characters per second, or about 2400 
  5013. bits per second. DOS applications that access the I/O hardware directly or 
  5014. through BIOS calls are supported. 
  5015.  
  5016. The Virtual COM Device Driver "looks" like the 8250 UART, including registers, 
  5017. modem lines, and interrupts. The DOS application sees the Virtual COM Device 
  5018. Driver as the actual device. The Virtual COM Device Driver contains the 
  5019. standard set of 8250/16450 port registers for access by the DOS application. 
  5020. They are: 
  5021.  
  5022. o Receive/Transmit Buffer and Divisor Latch
  5023.  
  5024. o Interrupt Enable and Divisor Latch
  5025.  
  5026. o Interrupt Identification
  5027.  
  5028. o Line Control
  5029.  
  5030. o Modem Control
  5031.  
  5032. o Line Status
  5033.  
  5034. o Modem Status
  5035.  
  5036. o Scratch
  5037.  
  5038. Interrupts supported by the Virtual COM Device Driver are:
  5039.  
  5040. o Line Status Interrupt
  5041.  
  5042. o Receive Data Available Interrupt
  5043.  
  5044. o Transmitter Empty Interrupt
  5045.  
  5046. o Modem Status Interrupt
  5047.  
  5048. Refer to Table 9-3 for a list of 8250/16450 registers supported by the Virtual 
  5049. COM Device Driver. 
  5050.  
  5051. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5052. ΓöéName      ΓöéR/W       ΓöéAddress   ΓöéPurpose             Γöé
  5053. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5054. ΓöéRBR       ΓöéR         Γöé0x3f8     ΓöéReceive buffer      Γöé
  5055. Γöé          Γöé          Γöé          Γöéregister            Γöé
  5056. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5057. ΓöéTHR       ΓöéW         Γöé0x3f8     ΓöéTransmitter holding Γöé
  5058. Γöé          Γöé          Γöé          Γöéregister            Γöé
  5059. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5060. ΓöéDLL       ΓöéR/W       Γöé0x3f8     ΓöéLow divisor latch   Γöé
  5061. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5062. ΓöéDLM       ΓöéR/W       Γöé0x3f9     ΓöéHigh divisor latch  Γöé
  5063. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5064. ΓöéIER       ΓöéR/W       Γöé0x3f9     ΓöéInterrupt enable    Γöé
  5065. Γöé          Γöé          Γöé          Γöéregister            Γöé
  5066. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5067. ΓöéIIR       ΓöéR         Γöé0x3fa     ΓöéInterrupt           Γöé
  5068. Γöé          Γöé          Γöé          Γöéidentification      Γöé
  5069. Γöé          Γöé          Γöé          Γöéregister            Γöé
  5070. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5071. ΓöéLCR       ΓöéR/W       Γöé0x3fb     ΓöéLine control        Γöé
  5072. Γöé          Γöé          Γöé          Γöéregister            Γöé
  5073. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5074. ΓöéMCR       ΓöéR/W       Γöé0x3fc     ΓöéModem control       Γöé
  5075. Γöé          Γöé          Γöé          Γöéregister            Γöé
  5076. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5077. ΓöéLSR       ΓöéR         Γöé0x3fd     ΓöéLine status registerΓöé
  5078. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5079. ΓöéMSR       ΓöéR         Γöé0x3fe     ΓöéModem status        Γöé
  5080. Γöé          Γöé          Γöé          Γöéregister            Γöé
  5081. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5082. ΓöéSCR       ΓöéR/W       Γöé0x3ff     ΓöéScratchpad register Γöé
  5083. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5084. Table 9-3. Virtualized 8250/16450 registers. 
  5085.  
  5086. Adapters with serial ports must conform to this register configuration. For 
  5087. UARTs with additional registers, I/O to those registers will be ignored by the 
  5088. Virtual COM Device Driver. All register bits are compatible with the standard 
  5089. bit assignments of the 8250/16450 UART. 
  5090.  
  5091. Since interrupts are simulated, there is no physical PIC addressed by the 
  5092. Virtual COM Device Driver. Rather, a simulated PIC, VPIC, is installed to 
  5093. arbitrate interrupt priorities and to provide an End-Of-Interrupt port for 
  5094. those applications that may issue an EOI directly to the PIC. 
  5095.  
  5096. The Virtual COM Device Driver also supports access to the serial device via INT 
  5097. 14h calls. The Virtual COM Device driver emulates the BIOS call, returning the 
  5098. same information as though the BIOS routine was actually called. 
  5099.  
  5100. When a character is received at the actual hardware, an interrupt is generated 
  5101. and the PDD gets the character from the UART receive register. The PDD then 
  5102. sends the character to the VDD for the waiting DOS application. When the DOS 
  5103. application sends a character to a port, the Virtual 8086 Emulator traps the 
  5104. operation and calls the VDD. The VDD, in turn, calls the PDD to output the 
  5105. character to the actual device. Simulated interrupts, like their physical 
  5106. counterparts, are not recognized if the interrupt system is disabled, and are 
  5107. only emulated if the interrupt system is on. To maximize performance, the PDD 
  5108. does not call the VDD at the receipt of every interrupt. Rather, it receives 
  5109. the information that PDD device driver events have taken place, and determines 
  5110. whether to continue simulating interrupts or take other action. For more 
  5111. information on the Virtual COM Device Driver, please refer to the OS/2 2.1 
  5112. Virtual Device Driver Reference. 
  5113.  
  5114.  
  5115. ΓòÉΓòÉΓòÉ 12.7. The Virtual Timer Device Driver ΓòÉΓòÉΓòÉ
  5116.  
  5117. The Virtual Timer Device driver provides support for DOS applications by 
  5118. providing the following services: 
  5119.  
  5120. o Virtualization of timer ports to allow reprogramming of the interrupt rate
  5121.  and speaker tone.
  5122.  
  5123. o Distribution of timer ticks to all DOS sessions.
  5124.  
  5125. o Maintenance of the timer tick count in the ROM BIOS data area.
  5126.  
  5127. o Serialization of timer 0 and timer 2 across multiple DOS sessions.
  5128.  
  5129. o Arbitration of the ownership of timer 0 and timer 2 between the VDD and
  5130.  the Clock PDD.
  5131.  
  5132. In DOS, timer 0 is used as the system timer, and set to interrupt every 18.2 
  5133. milliseconds. This timer is used to update the time of day clock and time-out 
  5134. the floppy disk drive motor on-off functions. DOS programs that need a higher 
  5135. tick resolution frequently program timer 0 to a higher frequency. The DOS tick 
  5136. handler intercepts the timer ticks and, at specified intervals, calls the 
  5137. system clock routine so that the time-of-day clock value is not affected. Timer 
  5138. 1 is the memory refresh timer and cannot be modified. Timer 2 is the speaker 
  5139. tone generator, and can be programmed to generate different sounds and tones. 
  5140. Timer 2 has two control bits, one to enable/disable the timer, and one to route 
  5141. the output to the speaker. 
  5142.  
  5143. Timer 0 ticks can be lost due to system loading, so the Virtual Timer Device 
  5144. Driver continually compares the actual elapsed time with the per-session DOS 
  5145. timer and updates it if necessary to make up for lost ticks. Every second, all 
  5146. of the currently running DOS sessions have their times re-synchronized. 
  5147.  
  5148. The hardware of timer 2 is virtualized, allowing it to be reprogrammed. The 
  5149. registers appear to the DOS applications exactly the same as the 8254 CTC (see 
  5150. Table 9-4). 
  5151.  
  5152. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5153. ΓöéDescription    ΓöéPort                     Γöé
  5154. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5155. ΓöéCound Word 0   Γöé0x40                     Γöé
  5156. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5157. ΓöéCount word 1   Γöé0x41                     Γöé
  5158. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5159. ΓöéCount word 2   Γöé0x42                     Γöé
  5160. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5161. ΓöéCount word 3   Γöé0x43                     Γöé
  5162. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5163. Table 9-4. Virtualized timer registers. 
  5164.  
  5165. See Table 9-5 for a list of timer registers supported by the Virtual Timer 
  5166. Device Driver. 
  5167.  
  5168. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5169. ΓöéCount word 0   Γöéread        Γöévirtualized    Γöé
  5170. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5171. ΓöéCount word 0   Γöéwrite       Γöévirtualized    Γöé
  5172. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5173. ΓöéCount word 1   Γöéread        Γöévirtualized    Γöé
  5174. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5175. ΓöéCount word 1   Γöéwrite       Γöéignored        Γöé
  5176. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5177. ΓöéCount word 2   Γöéread        Γöévirtualized    Γöé
  5178. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5179. ΓöéCount word 2   Γöéwrite       Γöévirtualized    Γöé
  5180. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5181. ΓöéControl word   Γöéread        Γöévirtualized    Γöé
  5182. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5183. ΓöéControl word   Γöéwrite       Γöévirtualized    Γöé
  5184. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5185. Table 9-5. Supported virtualized timer registers. 
  5186.  
  5187.  
  5188. ΓòÉΓòÉΓòÉ 12.8. The Virtual Disk Device Driver ΓòÉΓòÉΓòÉ
  5189.  
  5190. The VDM supplies DOS applications with a DOS-compatible disk interface via, the 
  5191. INT 13h DOS interrupt. The Virtual Disk Device Driver, VDSK, simulates ROM BIOS 
  5192. for disk access. A list of supported INT 13h functions can be found in Table 
  5193. 9-6. 
  5194.  
  5195. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5196. ΓöéAH        ΓöéFunction                                     Γöé
  5197. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5198. Γöé0x00      ΓöéReset diskette system                        Γöé
  5199. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5200. Γöé0x01      ΓöéStatus of disk system                        Γöé
  5201. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5202. Γöé0x02      ΓöéRead sectors into memory (floppy and fixed   Γöé
  5203. Γöé          Γöédisk)                                        Γöé
  5204. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5205. Γöé0x03      ΓöéWrite sectors from memory (floppy disk)      Γöé
  5206. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5207. Γöé0x04      ΓöéVerify sectors (floppy and fixed disk)       Γöé
  5208. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5209. Γöé0x05      ΓöéFormat track (floppy)                        Γöé
  5210. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5211. Γöé0x08      ΓöéGet current driver parameters (floppy and    Γöé
  5212. Γöé          Γöéfixed disk)                                  Γöé
  5213. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5214. Γöé0x15      ΓöéGet disk type (floppy and fixed disk)        Γöé
  5215. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5216. Γöé0x16      ΓöéChange of disk status (floppy)               Γöé
  5217. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5218. Γöé0x17      ΓöéSet disk type (floppy)                       Γöé
  5219. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5220. Γöé0x18      ΓöéSet media type for format (floppy)           Γöé
  5221. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5222. Table 9-6. Virtualized INT13 functions. 
  5223.  
  5224. When a DOS application issues an INT 13h request, the request is trapped by the 
  5225. Virtual Disk Device Driver, transformed into a Request Packet, and sent to the 
  5226. disk PDD for processing. If the disk is currently busy, the PDD queues up the 
  5227. request until it can process it. When the request can be completed, the PDD 
  5228. notifies the Virtual Disk Device Driver, which unblocks the DOS session. 
  5229.  
  5230. The disk VDD does not support direct register access to and from the disk 
  5231. controller. Any attempts to perform direct I/O are trapped and ignored. Some 
  5232. types of copy protection algorithms that are dependent on disk timing may fail. 
  5233.  
  5234. Floppy disk access is allowed directly to the floppy disk controller hardware, 
  5235. but only after the application gains exclusive access to the floppy disk drive. 
  5236. When a DOS application gains access to the floppy disk, it disables all port 
  5237. trapping and allows direct port access to the floppy controller (see Table 
  5238. 9-7). 
  5239.  
  5240. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5241. ΓöéPort    ΓöéFunction                      Γöé
  5242. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5243. Γöé0x3f0   ΓöéStatus register A (PS/2 only) Γöé
  5244. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5245. Γöé0x3f1   ΓöéStatus register B (PS/2 only) Γöé
  5246. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5247. Γöé0x3f2   ΓöéDigital output register       Γöé
  5248. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5249. Γöé0x3f7   ΓöéDigital input register        Γöé
  5250. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5251. Γöé0x3f7   ΓöéConfiguration register        Γöé
  5252. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5253. Γöé0x3f4   ΓöéController status register    Γöé
  5254. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5255. Γöé0x3f5   ΓöéController data register      Γöé
  5256. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5257. Table 9-7. Virtualized floppy disk ports. 
  5258.  
  5259. While the DOS session has access to the floppy disk, all interrupts from the 
  5260. floppy disk controller are reflected to the owning DOS application. Even when 
  5261. the DOS application has finished with the floppy disk, the ownership of the 
  5262. floppy disk will remain with the original DOS application until another 
  5263. application requests ownership. 
  5264.  
  5265.  
  5266. ΓòÉΓòÉΓòÉ 12.9. The Virtual Keyboard Device Driver ΓòÉΓòÉΓòÉ
  5267.  
  5268. The Virtual Keyboard Device Driver allows DOS applications that access to 
  5269. keyboard to run without a change in the VDM. The Virtual Keyboard Device Driver 
  5270. allows access to the keyboard, using the following methods: 
  5271.  
  5272. o INT 21h. DOS applications can access the keyboard using the CON device
  5273.  name, or get input from the stdin device.
  5274.  
  5275. o BIOS access via the INT 16h function.
  5276.  
  5277. o I/O port access, by reading and writing I/O ports 60h and 64h.
  5278.  
  5279. The Virtual Keyboard Device Driver must also handle the aspects of translation 
  5280. and code page tables, performance, and idle detection for those applications 
  5281. that poll the keyboard. When the physical keyboard driver receives an 
  5282. interrupt, it sends that interrupt to the Virtual Keyboard Device Driver, which 
  5283. in turn notifies the Virtual Programmable Interrupt Controller, or VPIC. The 
  5284. Virtual Keyboard Device Driver must supply the key scan codes for those 
  5285. applications that decipher the scan codes themselves. Setting the repeat rate 
  5286. is not supported. 
  5287.  
  5288. DOS applications frequently wait for a keyboard key to be pressed in a polling 
  5289. loop. The Virtual Keyboard Device Driver detects an idle loop, and adjusts the 
  5290. actual polling time as necessary. The driver increases the sleep between each 
  5291. poll, allowing other programs in the system to run. When a key is hit, the time 
  5292. between polls is reset to a short period, then increased as the inactivity 
  5293. increases. The Virtual Keyboard Device Driver uses the VDHWaitVRR VDH function 
  5294. to sleep in-between polls, and the DOS session is immediately woken up if a key 
  5295. is pressed. 
  5296.  
  5297. Normally, IRQ1 interrupts are channeled to the INT 09h interrupt service 
  5298. routine, which is usually a BIOS routine that performs key translation. The 
  5299. Virtual Keyboard Device Driver emulates the INT 09h BIOS routine, calling the 
  5300. INT 15h handler for scan code monitoring, handling <cntl-break> (INT 18h), and 
  5301. Print Screen (INT 05h) processing. 
  5302.  
  5303.  
  5304. ΓòÉΓòÉΓòÉ 12.10. The Virtual Mouse Device Driver ΓòÉΓòÉΓòÉ
  5305.  
  5306. DOS applications that require a mouse are supported via the INT 33h interface, 
  5307. which performs the following functions: 
  5308.  
  5309. o position and button tracking
  5310.  
  5311. o position and button event notification
  5312.  
  5313. o selectable pixel and mickey mappings
  5314.  
  5315. o video mode tracking
  5316.  
  5317. o pointer location and shape
  5318.  
  5319. o emulation of a light pen
  5320.  
  5321. Operation of the virtual mouse driver is similar to other virtual drivers. The 
  5322. mouse physical device driver is always aware of which session owns the mouse. 
  5323. When a full-screen DOS session owns the mouse, the mouse PDD notifies the 
  5324. virtual device driver of mouse events. If the DOS session is a windowed DOS 
  5325. session, the mouse PDD routes the mouse events to the Presentation Manager, 
  5326. which routes them to the virtual mouse device driver. The user may optionally 
  5327. set the exclusive mouse access on in the DOS Settings for the DOS windowed 
  5328. session. If  so, events from the mouse PDD are sent directly to the mouse VDD, 
  5329. bypassing the Presentation Manager. This property is used for applications that 
  5330. track and draw their own mouse pointer. 
  5331.  
  5332.  
  5333. ΓòÉΓòÉΓòÉ 12.11. The Virtual Line Printer Device Driver ΓòÉΓòÉΓòÉ
  5334.  
  5335. The Virtual Line Printer Device Driver, VLPT, allows DOS applications access to 
  5336. the parallel printer port via INT 17h BIOS calls. It also supports the BIOS INT 
  5337. 05h print screen call. The VLPT supports up to three parallel controllers, and 
  5338. virtualizes the data, status, control, and reserved ports of the printer 
  5339. controller. The VLPT also provides a direct access mode for DOS programs that 
  5340. control the parallel port hardware directly. When the VLPT recognizes that a 
  5341. DOS application wishes to perform direct I/O to the parallel port, it requests 
  5342. exclusive rights to the port from the parallel port PDD. 
  5343.  
  5344. If another application tries to use the printer after the DOS application has 
  5345. gained exclusive access to it, the access will fail. Print jobs from the 
  5346. spooler will continue to be queued up until the requested parallel port becomes 
  5347. free. 
  5348.  
  5349. The VLPT continues to handle the traps from the DOS application. The VLPT also 
  5350. traps the IRQ enable bit from a DOS application attempting to enable the 
  5351. parallel port IRQ. Interrupt transfers are not supported for the parallel port, 
  5352. so the VLPT contains no interrupt simulation routines. The VLPT also detects 
  5353. when a DOS application tries to change the direction bit, which is illegal on 
  5354. non-PS/2 systems. 
  5355.  
  5356.  
  5357. ΓòÉΓòÉΓòÉ 12.12. The Virtual Video Device Driver ΓòÉΓòÉΓòÉ
  5358.  
  5359. The Virtual Video Device Driver, or VVIDEO, provides display adapter support 
  5360. for DOS sessions. The VVIDEO driver communicates with the DOS Session Window 
  5361. Manager, ensuring that the DOS window stays relatively synchronized with the 
  5362. DOS application. Some parts of the DOS session environment have been designed 
  5363. especially for the VVIDEO driver. They are: 
  5364.  
  5365. o foreground/background notification hooks.
  5366.  
  5367. o freeze/thaw services.
  5368.  
  5369. o code page and title change notification hooks.
  5370.  
  5371. The VVIDEO driver is a base driver, loaded at boot time from CONFIG.SYS. If the 
  5372. VVIDEO driver cannot be loaded at boot time, no DOS sessions will be able to be 
  5373. started. The standard VVIDEO drivers support CGA, EGA, VGA, XGA, and 8514/A 
  5374. adapters, and monochrome adapters as secondary display adapters. All adapter 
  5375. memory sizes are supported up to 256KB, and more than one VVIDEO driver can be 
  5376. loaded for the same adapter. 
  5377.  
  5378. The DOS Window Manager starts a thread for communication to the VVIDEO driver, 
  5379. which calls the VVIDEO driver and waits for a video event. The VVIDEO driver 
  5380. supports both full screen and windowed operation, and can switch back and forth 
  5381. between full screen and windowed, and back. The VVIDEO drivers install hooks to 
  5382. trap all port accesses, maps physical screen memory to logical screen memory, 
  5383. and reports video events to the DOS Session Window Manager. Changes that are 
  5384. trapped by the DOS Session Window Manager, whether the DOS application is in 
  5385. focus or not, are: 
  5386.  
  5387. o mode changes.
  5388.  
  5389. o palette changes.
  5390.  
  5391. o a change in the cursor position.
  5392.  
  5393. o changing the session title.
  5394.  
  5395. o screen switch video memory allocation errors.
  5396.  
  5397. o scrolling and other positioning events.
  5398.  
  5399. The DOS Session Window Manager can query the state of its DOS session
  5400. video for the following:
  5401.  
  5402. o the current display mode.
  5403.  
  5404. o the current palette.
  5405.  
  5406. o the cursor position.
  5407.  
  5408. o the contents of video memory.
  5409.  
  5410. The DOS Session Window Manager can also issue the following directives:
  5411.  
  5412. o wait for video events.
  5413.  
  5414. o cancel wait for video events.
  5415.  
  5416. The VVIDEO driver opens the Virtual Mouse Device Driver, and provides it
  5417. with the following entry points:
  5418.  
  5419. o show mouse pointer.
  5420.  
  5421. o hide mouse pointer.
  5422.  
  5423. o define text mouse pointer.
  5424.  
  5425. o define graphics mouse pointer.
  5426.  
  5427. o set video page.
  5428.  
  5429. o set for light pen emulation.
  5430.  
  5431. The VVIDEO driver calls the Virtual Mouse Device Driver whenever the DOS 
  5432. session changes video modes. 
  5433.  
  5434. VVIDEO drivers can share the same video adapter by accepting to be temporarily 
  5435. shut down while another VVIDEO driver uses the adapter, and restarted when 
  5436. control of the adapter is released back to the original owner. 
  5437.  
  5438. The VVIDEO driver supports the DOS INT 10h to support drawing operations and 
  5439. the simultaneous use of the mouse pointer. The VVIDEO also supports INT 2Fh 
  5440. services, which notify an application that it is about to be switched. The 
  5441. 8514/A and XGA adapters can run only in the full screen mode of the DOS 
  5442. session, and will immediately be frozen if it attempts to write directly to the 
  5443. 8514/A or XGA adapter. 
  5444.  
  5445.  
  5446. ΓòÉΓòÉΓòÉ 12.13. Virtual DevHlp Services By Category ΓòÉΓòÉΓòÉ
  5447.  
  5448. Virtual DevHlp functions provide virtual device drivers with access to various 
  5449. services provided by the operating system and by other virtual device drivers. 
  5450. The Virtual DevHlp services are listed alphabetically, with a short explanation 
  5451. of their purpose. A complete reference to the Virtual Device Helper routines, 
  5452. including details on parameter use, can be found in the IBM OS/2 2.1 Virtual 
  5453. Device Driver Reference. Virtual DevHlp services can be divided into categories 
  5454. based on the type of service that the virtual DevHlp provides. These categories 
  5455. are: 
  5456.  
  5457. DOS Settings 
  5458.  
  5459. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5460. ΓöéVDHRegisterProperty ΓöéRegister virtual device driver property Γöé
  5461. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5462. ΓöéVDHQueryProperty    ΓöéQuery virtual device driver property    Γöé
  5463. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5464.  
  5465. File (or device) I/O Services 
  5466.  
  5467. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5468. ΓöéVDHOpen             ΓöéOpen a file or device                   Γöé
  5469. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5470. ΓöéVDHClose            ΓöéClose a file or device                  Γöé
  5471. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5472. ΓöéVDHRead             ΓöéRead from file or device                Γöé
  5473. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5474. ΓöéVDHWrite            ΓöéWrite to file or device                 Γöé
  5475. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5476. ΓöéVDHIOCtl            ΓöéPerform IOCtl                           Γöé
  5477. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5478. ΓöéVDHPhysicalDisk     ΓöéGet information about partitionable     Γöé
  5479. Γöé                    Γöédisks                                   Γöé
  5480. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5481. ΓöéVDHSeek             ΓöéMove read/write file pointer            Γöé
  5482. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5483.  
  5484. DMA Services 
  5485.  
  5486. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5487. ΓöéVDHRegisterDMAChannel ΓöéRegister a DMA channel with the       Γöé
  5488. Γöé                      Γöévirtual DMA device driver             Γöé
  5489. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5490. ΓöéVDHCallOutDMA         ΓöéLet DMA do its work                   Γöé
  5491. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5492. ΓöéVDHAllocateDMABuffer  ΓöéAllocate a DMA buffer                 Γöé
  5493. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5494. ΓöéVDHFreeDMABuffer      ΓöéRelease previously allocated DMA      Γöé
  5495. Γöé                      Γöébuffer                                Γöé
  5496. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5497.  
  5498. DOS Session Control Services 
  5499.  
  5500. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5501. ΓöéVDHKillVDM          ΓöéTerminate a DOS session                 Γöé
  5502. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5503. ΓöéVDHHaltSystem       ΓöéHalt the system                         Γöé
  5504. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5505. ΓöéVDHFreezeVDM        ΓöéFreeze a DOS session; prevent the DOS   Γöé
  5506. Γöé                    Γöésession from executing any V86 code     Γöé
  5507. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5508. ΓöéVDHThawVDM          ΓöéAllow a frozen DOS session to resume    Γöé
  5509. Γöé                    Γöéexecuting V86 code                      Γöé
  5510. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5511. ΓöéVDHIsVDMFrozen      ΓöéDetermine if DOS session is frozen      Γöé
  5512. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5513. ΓöéVDHSetPriority      ΓöéAdjust a DOS session's scheduler        Γöé
  5514. Γöé                    Γöépriority                                Γöé
  5515. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5516. ΓöéVDHYield            ΓöéYield the processor                     Γöé
  5517. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5518.  
  5519. DPMI Services 
  5520.  
  5521. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5522. ΓöéVDHGetSelBase       ΓöéGet a flat base address for an LDT      Γöé
  5523. Γöé                    Γöéselector                                Γöé
  5524. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5525. ΓöéVDHGetVPMExcept     ΓöéGet the current DOS session's protect   Γöé
  5526. Γöé                    Γöémode exception vector.                  Γöé
  5527. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5528. ΓöéVDHSetVPMExcept     ΓöéSet the current DOS session's protect   Γöé
  5529. Γöé                    Γöémode exception handler to a specified   Γöé
  5530. Γöé                    Γöévalue.                                  Γöé
  5531. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5532. ΓöéVDHChangeVPMIF      ΓöéChange the virtual interrupt flag (IF), Γöé
  5533. Γöé                    Γöéenabling or disabling protect mode      Γöé
  5534. Γöé                    Γöéinterrupts.                             Γöé
  5535. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5536. ΓöéVDHRaiseException   ΓöéRaise an exception to a DOS session, as Γöé
  5537. Γöé                    Γöéif the exception had been caused by the Γöé
  5538. Γöé                    Γöéhardware.                               Γöé
  5539. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5540. ΓöéVDHReadUBuf         ΓöéRead from protect mode address space    Γöé
  5541. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5542. ΓöéVDHWriteUBuf        ΓöéWrite to protect mode address space     Γöé
  5543. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5544. ΓöéVDHCheckPagePerm    ΓöéCheck ring 3 page permissions           Γöé
  5545. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5546. ΓöéVDHSwitchToVPM      ΓöéSwitch a DOS session to protect mode    Γöé
  5547. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5548. ΓöéVDHSwitchToV86      ΓöéSwitch a DOS session to v86 mode        Γöé
  5549. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5550. ΓöéVDHCheckVPMIntVectorΓöéDetermine if a DOS session protect mode Γöé
  5551. Γöé                    Γöéhandler exists                          Γöé
  5552. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5553. ΓöéVDHGetVPMIntVector  ΓöéReturn the DOS session's protect mode   Γöé
  5554. Γöé                    Γöéinterrupt vector                        Γöé
  5555. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5556. ΓöéVDHSetVPMIntVector  ΓöéSet the DOS session's protect mode      Γöé
  5557. Γöé                    Γöéinterrupt vector                        Γöé
  5558. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5559. ΓöéVDHArmVPMBPHook     ΓöéObtain the address of a DOS session's   Γöé
  5560. Γöé                    Γöéprotect mode breakpoint                 Γöé
  5561. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5562. ΓöéVDHBeginUseVPMStack ΓöéBegin using the DOS session's protect   Γöé
  5563. Γöé                    Γöémode stack                              Γöé
  5564. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5565. ΓöéVDHEndUseVPMStack   ΓöéEnd the use of the DOS session's protectΓöé
  5566. Γöé                    Γöémode stack                              Γöé
  5567. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5568.  
  5569. (The "VPM" in many of the function names in this section stands for "Virtual 
  5570. Protect Mode"). 
  5571.  
  5572. GDT Selector Services 
  5573.  
  5574. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5575. ΓöéVDHCreatSel         ΓöéCreate a GDT selector to map to a linearΓöé
  5576. Γöé                    Γöérange                                   Γöé
  5577. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5578. ΓöéVDHDestroySel       ΓöéDestroy previously created GDT selector Γöé
  5579. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5580. ΓöéVDHQuerySel         ΓöéGet the selector for an address in the  Γöé
  5581. Γöé                    Γöévirtual device driver's data or on it's Γöé
  5582. Γöé                    Γöéstack                                   Γöé
  5583. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5584.  
  5585. Hook Management Services 
  5586.  
  5587. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5588. ΓöéVDHAllocHook        ΓöéAllocate thte hooks needed for interruptΓöé
  5589. Γöé                    Γöésimulation                              Γöé
  5590. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5591. ΓöéVDHArmBPHook        ΓöéObtain the address of a V86 breakpoint  Γöé
  5592. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5593. ΓöéVDHArmContextHook   ΓöéSet a local or global context hook      Γöé
  5594. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5595. ΓöéVDHArmReturnHook    ΓöéSet a handler to receive control when anΓöé
  5596. Γöé                    ΓöéIRET or RETF is executed in V86 mode    Γöé
  5597. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5598. ΓöéVDHArmSTIHook       ΓöéSet a handler to receive control when   Γöé
  5599. Γöé                    Γöéinterrupts are enabled in the current   Γöé
  5600. Γöé                    ΓöéDOS session                             Γöé
  5601. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5602. ΓöéVDHArmTimerHook     ΓöéSet a timer handler                     Γöé
  5603. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5604. ΓöéVDHFreeHook         ΓöéDisarm and free a hook                  Γöé
  5605. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5606. ΓöéVDHInstallIntHook   ΓöéSet a handler for a V86 interrupt       Γöé
  5607. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5608. ΓöéVDHInstallIOHook    ΓöéInstall I/O port hooks                  Γöé
  5609. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5610. ΓöéVDHUserHook         ΓöéInstall a handler for a DOS session     Γöé
  5611. Γöé                    Γöéevent                                   Γöé
  5612. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5613. ΓöéVDHQueryHookData    ΓöéReturns a pointer to a hook's reference Γöé
  5614. Γöé                    Γöédata (created during the call to        Γöé
  5615. Γöé                    ΓöéVDHAllocHook)                           Γöé
  5616. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5617. ΓöéVDHRemoveIOHook     ΓöéRemove I/O port hooks                   Γöé
  5618. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5619. ΓöéVDHSelIOHookState   ΓöéEnable/disable I/O port trapping        Γöé
  5620. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5621. ΓöéVDHRegisterAPI      ΓöéSet V86 or protect mode API handler     Γöé
  5622. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5623.  
  5624. DOS Application Management 
  5625.  
  5626. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5627. ΓöéVDHReportPeek       ΓöéReport DOS session polling activity for Γöé
  5628. Γöé                    Γöéthe purpose of idle detection           Γöé
  5629. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5630. ΓöéVDHWakeIdle         ΓöéWake up a DOS session that is doing     Γöé
  5631. Γöé                    Γöésleeping                                Γöé
  5632. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5633.  
  5634. These services allow virtual device drivers to tell OS/2 when a DOS application 
  5635. appears to be idle, and when there is some activity that could make the DOS 
  5636. application busy. 
  5637.  
  5638. Inter-Device Communication Services 
  5639.  
  5640. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5641. ΓöéVDHRegisterVDD      ΓöéRegister a virtual device driver's entryΓöé
  5642. Γöé                    Γöépoints                                  Γöé
  5643. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5644. ΓöéVDHOpenVDD          ΓöéOpen a virtual device driver previously Γöé
  5645. Γöé                    Γöéregistered with VDHRegisterVDD          Γöé
  5646. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5647. ΓöéVDHOpenPDD          ΓöéOpen a physical device driver for VDD - Γöé
  5648. Γöé                    ΓöéPDD communications                      Γöé
  5649. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5650. ΓöéVDHRequestVDD       ΓöéIssue a request for an operation of a   Γöé
  5651. Γöé                    Γöévirtual device driver                   Γöé
  5652. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5653. ΓöéVDHCloseVDD         ΓöéClose a virtual device driver opened    Γöé
  5654. Γöé                    Γöéwith VDHOpenVDD                         Γöé
  5655. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5656.  
  5657. Keyboard Services 
  5658.  
  5659. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5660. ΓöéVDHQueryKeyShift    ΓöéQuery the keyboard shift state          Γöé
  5661. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5662.  
  5663. Memory Management Services 
  5664.  
  5665. There are three subcategories of memory management virtual DevHlp services. The 
  5666. first two are based on the granularity of the memory allocation unit, the third 
  5667. category is for memory locking services. 
  5668.  
  5669. Byte Granular Memory Management Services 
  5670.  
  5671. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5672. ΓöéVDHAllocMem         ΓöéAllocate a small amount of memory       Γöé
  5673. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5674. ΓöéVDHFreeMem          ΓöéFree memory allocated with VDHAllocMem  Γöé
  5675. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5676. ΓöéVDHAllocDOSMem      ΓöéAllocate a block of memory from the DOS Γöé
  5677. Γöé                    Γöéarea                                    Γöé
  5678. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5679. ΓöéVDHCreateBlockPool  ΓöéCreate a memory block pool              Γöé
  5680. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5681. ΓöéVDHAllocBlock       ΓöéAllocate a block from a memory block    Γöé
  5682. Γöé                    Γöépool                                    Γöé
  5683. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5684. ΓöéVDHFreeBlock        ΓöéFree a previously allocated block of    Γöé
  5685. Γöé                    Γöémemory (return the block to a memory    Γöé
  5686. Γöé                    Γöéblock pool)                             Γöé
  5687. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5688. ΓöéVDHDestroyBlockPool ΓöéDestroy a memory block pool             Γöé
  5689. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5690. ΓöéVDHCopyMem          ΓöéCopy from one linear memory address to  Γöé
  5691. Γöé                    Γöéanother                                 Γöé
  5692. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5693. ΓöéVDHExchangeMem      ΓöéExchange the contents of two linear     Γöé
  5694. Γöé                    Γöémemory regions                          Γöé
  5695. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5696.  
  5697. Page Granular Memory Management Services 
  5698.  
  5699. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5700. ΓöéVDHAllocPages       ΓöéAllocate a page-aligned memory object   Γöé
  5701. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5702. ΓöéVDHReallocPages     ΓöéReallocates (re-sizes) a memory object  Γöé
  5703. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5704. ΓöéVDHFreePages        ΓöéFree a memory object                    Γöé
  5705. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5706. ΓöéVDHFindFreePages    ΓöéFind the largest available linear memoryΓöé
  5707. Γöé                    Γöéregion                                  Γöé
  5708. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5709. ΓöéVDHGetDirtyPagelnfo ΓöéReturns the status of the dirty bits forΓöé
  5710. Γöé                    Γöéa range of memory pages (resets the     Γöé
  5711. Γöé                    Γöébits)                                   Γöé
  5712. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5713. ΓöéVDHQueryFreePages   ΓöéReturns the total amount of free virtualΓöé
  5714. Γöé                    Γöémemory in bytes                         Γöé
  5715. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5716. ΓöéVDHReservePages     ΓöéReserve a range of linear addresses     Γöé
  5717. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5718. ΓöéVDHUnreservePages   ΓöéUnreserve a range of linear addresses   Γöé
  5719. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5720. ΓöéVDHMapPages         ΓöéMap a specified linear address          Γöé
  5721. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5722. ΓöéVDHInstallFaultHook ΓöéInstall your own page fault handler     Γöé
  5723. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5724. ΓöéVDHRemoveFaultHook  ΓöéRemove your page fault handler          Γöé
  5725. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5726.  
  5727. Memory Locking Memory Management Services 
  5728.  
  5729. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5730. ΓöéVDHLockMem          ΓöéVerify access to a region of memory,    Γöé
  5731. Γöé                    Γöéthen lock that memory                   Γöé
  5732. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5733. ΓöéVDHUnlockMem        ΓöéRelease a memory lock                   Γöé
  5734. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5735.  
  5736. These services allow virtual device drivers to allocate, free, reallocate, and 
  5737. lock memory for global and per-DOS session objects, page or byte granular 
  5738. objects, and with different options, such as fixed or swappable allocations. 
  5739.  
  5740. Four types of mapping are supported:  1. Mapping to a physical address.  2. 
  5741. Mapping to another linear address.  3. Mapping to black hole (don't care) 
  5742. pages.  4. Mapping to invalid pages, which means unmapped. 
  5743.  
  5744. Virtual device drivers can also request smaller memory allocations from the 
  5745. kernel heap, which is global and fixed. Small, fixed-size block services are 
  5746. available to speed up frequent allocations and the freeing of memory. For a 
  5747. particular block size, a pool of blocks are maintained, and the requirements 
  5748. are met by taking off a block from the block pool. 
  5749.  
  5750. Miscellaneous Virtual DevHlp Services 
  5751.  
  5752. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5753. ΓöéVDHSetFlags           ΓöéSet the DOS session's FLAGS register  Γöé
  5754. Γöé                      Γöéto a specified value                  Γöé
  5755. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5756. ΓöéVDHSetA20             ΓöéEnable or disable the A20 line for theΓöé
  5757. Γöé                      Γöécurrent DOS session                   Γöé
  5758. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5759. ΓöéVDHQueryA20           ΓöéQuery the current state of the A20    Γöé
  5760. Γöé                      Γöéline                                  Γöé
  5761. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5762. ΓöéVDHDevBeep            ΓöéDevice beep Virtual DevHlp service    Γöé
  5763. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5764. ΓöéVDHGetError           ΓöéGet the error code from the last      Γöé
  5765. Γöé                      ΓöéVirtual DevHlp service called         Γöé
  5766. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5767. ΓöéVDHSetError           ΓöéSet the error code for VDHGetError to Γöé
  5768. Γöé                      Γöéquery                                 Γöé
  5769. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5770. ΓöéVDHHandleFromSGID     ΓöéGet the DOS session handle from the   Γöé
  5771. Γöé                      Γöéscreen group ID                       Γöé
  5772. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5773. ΓöéVDHHandleFromPID      ΓöéGet the handle for a given process ID Γöé
  5774. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5775. ΓöéVDHEnumerateVDMs      ΓöéFor each DOS session in the system,   Γöé
  5776. Γöé                      Γöérun a worker function                 Γöé
  5777. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5778. ΓöéVDHQueryLin           ΓöéGet the linear address for a FAR16 (16Γöé
  5779. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5780. ΓöéVDHGetCodePageFont    ΓöéReturn information about the DOS      Γöé
  5781. Γöé                      Γöésession's code page font              Γöé
  5782. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5783. ΓöéVDHReleaseCodePageFontΓöéRelease code page font returned by    Γöé
  5784. Γöé                      ΓöéVDHGetCodePageFont                    Γöé
  5785. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5786. ΓöéVDHQuerySysValue      ΓöéQuery a system value                  Γöé
  5787. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5788. ΓöéVDHPutSysValue        ΓöéSet a system value                    Γöé
  5789. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5790. ΓöéVDHPopup              ΓöéDisplay a message                     Γöé
  5791. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5792. ΓöéVDHSetDosDevice       ΓöéRegister/Install a DOS device driver  Γöé
  5793. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5794.  
  5795. NPX (Numeric Coprocessor) Services 
  5796.  
  5797. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5798. ΓöéVDHReleaseNPX       ΓöéGive up ownership of NPX                Γöé
  5799. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5800. ΓöéVDHNPXReset         ΓöéReset port F1                           Γöé
  5801. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5802. ΓöéVDHNPXClearBusy     ΓöéClear busy latch                        Γöé
  5803. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5804. ΓöéVDHNPXRegisterVDD   ΓöéRegister virtual device driver entry    Γöé
  5805. Γöé                    Γöépoints                                  Γöé
  5806. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5807.  
  5808. Parallel Port and Printer Services 
  5809.  
  5810. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5811. ΓöéVDHPrintClose       ΓöéFlush and close all open printers for a Γöé
  5812. Γöé                    ΓöéDOS session                             Γöé
  5813. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5814.  
  5815. Semaphore Services 
  5816.  
  5817. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5818. ΓöéVDHCreateSem        ΓöéCreate an event or mutex semaphore      Γöé
  5819. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5820. ΓöéVDHDestroySem       ΓöéDestroy a semaphore                     Γöé
  5821. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5822. ΓöéVDHResetEventSem    ΓöéReset an event semaphore                Γöé
  5823. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5824. ΓöéVDHPostEventSem     ΓöéPost an event semaphore                 Γöé
  5825. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5826. ΓöéVDHWaitEventSem     ΓöéWait on an event semaphore              Γöé
  5827. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5828. ΓöéVDHRequestMutexSem  ΓöéRequest a mutex semaphore               Γöé
  5829. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5830. ΓöéVDHReleaseMutexSem  ΓöéRelease a mutex semaphore               Γöé
  5831. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5832. ΓöéVDHQuerySem         ΓöéQuery a semaphore's state               Γöé
  5833. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5834.  
  5835. These services are used for synchronizing with an OS/2 process. Virtual device 
  5836. drivers must be careful not to block (VDHRequestSem/VDHWaitSem) in the context 
  5837. of a DOS session task, or that task will receive no more simulated hardware 
  5838. interrupts until it becomes unblocked. 
  5839.  
  5840. Timer Services 
  5841.  
  5842. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5843. ΓöéVDHArmTimerHook     ΓöéSet a timer service handler             Γöé
  5844. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5845. ΓöéVDHDisarmTimerHook  ΓöéCancel a timer service before the       Γöé
  5846. Γöé                    Γöéhandler has been called                 Γöé
  5847. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5848.  
  5849. Virtual Interrupt Services 
  5850.  
  5851. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5852. ΓöéVDHOpenVIRQ         ΓöéRegister an IRQ handler for a virtual   Γöé
  5853. Γöé                    Γöédevice driver                           Γöé
  5854. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5855. ΓöéVDHCloseVIRQ        ΓöéDeregister an IRQ handler for a virtual Γöé
  5856. Γöé                    Γöédevice driver                           Γöé
  5857. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5858. ΓöéVDHSetVIRR          ΓöéSet the virtual Interrupt Request       Γöé
  5859. Γöé                    ΓöéRegister (IRR), causing an interrupt to Γöé
  5860. Γöé                    Γöébe simulated to the DOS session         Γöé
  5861. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5862. ΓöéVDHClearVIRR        ΓöéClear the virtual IRR, stopping the     Γöé
  5863. Γöé                    Γöésimulation of interrupts to the DOS     Γöé
  5864. Γöé                    Γöésession)                                Γöé
  5865. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5866. ΓöéVDHQueryVIRQ        ΓöéQuery the IRQ status in a DOS session   Γöé
  5867. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5868. ΓöéVDHWaitVIRRs        ΓöéWait until an interrupt is simulated    Γöé
  5869. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5870. ΓöéVDHWakeVIRRs        ΓöéWake up a DOS session that is waiting   Γöé
  5871. Γöé                    Γöéwith VDHWaitVIRRs                       Γöé
  5872. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5873. ΓöéVDHSendVEOI         ΓöéSend a virtual EOI (End-Of-Interrupt) toΓöé
  5874. Γöé                    Γöéthe VPIC                                Γöé
  5875. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5876.  
  5877. V8086 Stack Manipulation 
  5878.  
  5879. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5880. ΓöéVDHPushRegs         ΓöéPush a client DOS session's registers   Γöé
  5881. Γöé                    Γöéonto the client's stack                 Γöé
  5882. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5883. ΓöéVDHPopRegs          ΓöéPop a client DOS session's registers    Γöé
  5884. Γöé                    Γöéfrom the client's stack                 Γöé
  5885. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5886. ΓöéVDHPushFarCall      ΓöéSimulate a far call to V86 code         Γöé
  5887. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5888. ΓöéVDHPopStack         ΓöéPop data off client stack               Γöé
  5889. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5890. ΓöéVDHPushStack        ΓöéPush data onto a client's stack         Γöé
  5891. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5892. ΓöéVDHPushInt          ΓöéTransfer control to a V86 interrupt     Γöé
  5893. Γöé                    Γöéhandler when an interrupt is simulated  Γöé
  5894. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5895. ΓöéVDHPopInt           ΓöéRemove IRET frame from a client DOS     Γöé
  5896. Γöé                    Γöésession's stack                         Γöé
  5897. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5898.  
  5899. Many of the virtual DevHlp functions that are called with invalid parameters or 
  5900. other error conditions often cause a system halt. This is because virtual 
  5901. device drivers run at Ring 0; they have free access to everything in the 
  5902. system. If an invalid parameter is detected, it has probably done enough damage 
  5903. that the system has become unstable. The only thing to do at that point is to 
  5904. halt the system. 
  5905.  
  5906.  
  5907. ΓòÉΓòÉΓòÉ 12.14. DOS Session Interrupts ΓòÉΓòÉΓòÉ
  5908.  
  5909. Table 9-8 describes the DOS hardware interrupts virtualization supplied by the 
  5910. Virtual Device Drivers and the DOS emulation component of the VDM. 
  5911.  
  5912. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5913. ΓöéInterrupΓöéDescription    ΓöéNotes                         Γöé
  5914. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5915. ΓöéIRQ 0   ΓöéTimer (INT 08h)ΓöéDOS programs can hook this    Γöé
  5916. Γöé        Γöé               Γöéinterrupt with the INT 08h    Γöé
  5917. Γöé        Γöé               Γöécall. The INT 08h handler is  Γöé
  5918. Γöé        Γöé               Γöécalled for each tick of the   Γöé
  5919. Γöé        Γöé               Γöéchannel 0 system clock.       Γöé
  5920. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5921. ΓöéIRQ 1   ΓöéKeyboard (INT  ΓöéThe INT 09h handler is invokedΓöé
  5922. Γöé        Γöé09h)           Γöéfor every press and release ofΓöé
  5923. Γöé        Γöé               Γöéa keystroke.                  Γöé
  5924. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5925. ΓöéIRQ 2   ΓöéCascade        ΓöéUse for the support of        Γöé
  5926. Γöé        ΓöéInterrupt      Γöéinterrupts 8-15 to emulate theΓöé
  5927. Γöé        ΓöéController     Γöésecond PIC                    Γöé
  5928. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5929. ΓöéIRQ 3   ΓöéSerial Port    ΓöéSupported when VCOM.SYS and   Γöé
  5930. Γöé        Γöé(COM2, COM3)   ΓöéCOM.SYS are loaded.           Γöé
  5931. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5932. ΓöéIRQ 4   ΓöéSerial Port    ΓöéSupported when VCOM.SYS and   Γöé
  5933. Γöé        Γöé(COM1)         ΓöéCOM.SYS are loaded.           Γöé
  5934. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5935. ΓöéIRQ 5   ΓöéParallel Port  ΓöéNot supported                 Γöé
  5936. Γöé        Γöé(LPT2)         Γöé                              Γöé
  5937. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5938. ΓöéIRQ 6   ΓöéDiskette       ΓöéNot supported                 Γöé
  5939. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5940. ΓöéIRQ 7   ΓöéParallel Port  ΓöéNot supported                 Γöé
  5941. Γöé        Γöé(LPT1)         Γöé                              Γöé
  5942. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5943. ΓöéIRQ 8   ΓöéReal Time ClockΓöéNot supported                 Γöé
  5944. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5945. ΓöéIRQ 9   ΓöéRedirect       ΓöéNot supported                 Γöé
  5946. Γöé        Γöécascade        Γöé                              Γöé
  5947. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5948. ΓöéIRQ 10  Γöé               ΓöéNot supported                 Γöé
  5949. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5950. ΓöéIRQ 11  Γöé               ΓöéNot supported                 Γöé
  5951. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5952. ΓöéIRQ 12  ΓöéAux. device    ΓöéNot supported                 Γöé
  5953. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5954. ΓöéIRQ 13  ΓöéMath           ΓöéSupported                     Γöé
  5955. Γöé        ΓöéCoprocessor    Γöé                              Γöé
  5956. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5957. ΓöéIRQ 14  ΓöéFixed disk     ΓöéNot supported                 Γöé
  5958. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5959. ΓöéIRQ 15  Γöé               ΓöéNot supported                 Γöé
  5960. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  5961. Table 9-8. Virtualized DOS Interrupts 
  5962.  
  5963. Table 9-9 describes the DOS BIOS software interrupts supported in a VDM. 
  5964.  
  5965. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  5966. ΓöéInterrupΓöéDescription    ΓöéNotes                         Γöé
  5967. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5968. Γöé02h     ΓöéNMI            ΓöéNot supported                 Γöé
  5969. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5970. Γöé05h     ΓöéPrint screen   ΓöéSupported by the Virtual Line Γöé
  5971. Γöé        Γöé               ΓöéPrinter driver                Γöé
  5972. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5973. Γöé08h     ΓöéSystem timer   ΓöéSupported by the Virtual TimerΓöé
  5974. Γöé        Γöé               Γöédevice driver. Due to system  Γöé
  5975. Γöé        Γöé               Γöéoverhead, interrupts may come Γöé
  5976. Γöé        Γöé               Γöéin short bursts               Γöé
  5977. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5978. Γöé0eh     ΓöéDiskette       ΓöéNot supported                 Γöé
  5979. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5980. Γöé10h     ΓöéVideo          ΓöéFully supported               Γöé
  5981. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5982. Γöé13h     ΓöéDisk/diskette  ΓöéSupported by a subset of the  Γöé
  5983. Γöé        Γöé               ΓöéDOS INT 13h functions. The    Γöé
  5984. Γöé        Γöé               Γöésupported functions are: o 00hΓöé
  5985. Γöé        Γöé               Γöé- Reset diskette o 01h - Read Γöé
  5986. Γöé        Γöé               Γöéstatus o 02h - Read sector o  Γöé
  5987. Γöé        Γöé               Γöé03h - Write sectors (diskette Γöé
  5988. Γöé        Γöé               Γöéonly) o 04h - Verify sectors oΓöé
  5989. Γöé        Γöé               Γöé05h - Format track (diskette  Γöé
  5990. Γöé        Γöé               Γöéonly) o 08h - Get driver      Γöé
  5991. Γöé        Γöé               Γöéparameters o 0ah - Read long  Γöé
  5992. Γöé        Γöé               Γöé(fixed disk only) o 15h - ReadΓöé
  5993. Γöé        Γöé               ΓöéDASD type o 16h - Change      Γöé
  5994. Γöé        Γöé               Γöéstatus (diskette only) o 17h -Γöé
  5995. Γöé        Γöé               ΓöéSet disk type (diskette only) Γöé
  5996. Γöé        Γöé               Γöéo 18h - Set media type        Γöé
  5997. Γöé        Γöé               Γöé(diskette only)               Γöé
  5998. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  5999. Γöé14h     ΓöéSerial Port    ΓöéSupported by the Virtual COM  Γöé
  6000. Γöé        Γöé(Async)        Γöédriver                        Γöé
  6001. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6002. Γöé15h     ΓöéSystem servicesΓöéSupports the following system Γöé
  6003. Γöé        Γöé               Γöéservices: o 00h - Cassette    Γöé
  6004. Γöé        Γöé               Γöémotor on o 01h - Cassette     Γöé
  6005. Γöé        Γöé               Γöémotor off o 02h - Cassette    Γöé
  6006. Γöé        Γöé               Γöéread o 03h - Cassette write o Γöé
  6007. Γöé        Γöé               Γöé0fh - Format periodic int o   Γöé
  6008. Γöé        Γöé               Γöé4fh - Keyboard intercept o 80hΓöé
  6009. Γöé        Γöé               Γöé- Open device o 81h - Close   Γöé
  6010. Γöé        Γöé               Γöédevice o 82h - program        Γöé
  6011. Γöé        Γöé               Γöéterminate o 83h - Event wait oΓöé
  6012. Γöé        Γöé               Γöé84h - Joystick o 85h - SysReq Γöé
  6013. Γöé        Γöé               Γöékey o 86h - Wait o 87h - Move Γöé
  6014. Γöé        Γöé               Γöéblock o 88h - Get extended    Γöé
  6015. Γöé        Γöé               Γöémemory size o 89h - Switch to Γöé
  6016. Γöé        Γöé               Γöéprotect mode o 90h - Device   Γöé
  6017. Γöé        Γöé               Γöéwait o 91h - Device post o c0hΓöé
  6018. Γöé        Γöé               Γöé- Get system config parametersΓöé
  6019. Γöé        Γöé               Γöéo c1h - Get ABIOS data area o Γöé
  6020. Γöé        Γöé               Γöéc2h - PS/2 mouse functions o  Γöé
  6021. Γöé        Γöé               Γöéc3h - Watchdog timer o c4h -  Γöé
  6022. Γöé        Γöé               ΓöéProgrammable Option Select    Γöé
  6023. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6024. Γöé16h     ΓöéKeyboard       ΓöéFully supported               Γöé
  6025. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6026. Γöé17h     ΓöéPrinter        ΓöéFully supported by the VLPT   Γöé
  6027. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6028. Γöé19h     ΓöéReboot         Γöéif DOS_STARTUP_DRIVE is set,  Γöé
  6029. Γöé        Γöé               Γöéthe session is rebooted; if   Γöé
  6030. Γöé        Γöé               Γöénot, the session is           Γöé
  6031. Γöé        Γöé               Γöéterminated.                   Γöé
  6032. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6033. Γöé1ah     ΓöéTime of Day    ΓöéRead only access to Real Time Γöé
  6034. Γöé        Γöé               ΓöéClock is supported.           Γöé
  6035. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6036. Γöé1eh     ΓöéDiskette       ΓöéFully supported               Γöé
  6037. Γöé        Γöéparameters     Γöé                              Γöé
  6038. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6039. Γöé70h     ΓöéReal Time ClockΓöéNot supported                 Γöé
  6040. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  6041. Table 9-9. Virtualized BIOS Interrupts 
  6042.  
  6043. Table 9-10 describes the DOS software interrupts which are supported by the DOS 
  6044. emulation component. 
  6045.  
  6046. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  6047. ΓöéInterrupΓöéDescription    ΓöéNotes                         Γöé
  6048. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6049. Γöé20h     ΓöéProgram        ΓöéFully supported               Γöé
  6050. Γöé        Γöéterminate      Γöé                              Γöé
  6051. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6052. Γöé21h     ΓöéFunction       ΓöéFully supported, plus some    Γöé
  6053. Γöé        Γöérequest        Γöéundocumented functions. The   Γöé
  6054. Γöé        Γöé               Γöéfollowing calls are supported Γöé
  6055. Γöé        Γöé               Γöéwith restrictions: o 38h -    Γöé
  6056. Γöé        Γöé               ΓöéReturn country information o  Γöé
  6057. Γöé        Γöé               Γöé44h - Generic IOCtl o 66h -   Γöé
  6058. Γöé        Γöé               ΓöéGet/set code page o 67h - Set Γöé
  6059. Γöé        Γöé               Γöéhandle count                  Γöé
  6060. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6061. Γöé22h     ΓöéTerminate      ΓöéFully supported               Γöé
  6062. Γöé        Γöéaddress        Γöé                              Γöé
  6063. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6064. Γöé23h     ΓöéCntl-break exitΓöéFully supported               Γöé
  6065. Γöé        Γöéaddress        Γöé                              Γöé
  6066. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6067. Γöé24h     ΓöéCritical error ΓöéFully supported               Γöé
  6068. Γöé        Γöéhandler        Γöé                              Γöé
  6069. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6070. Γöé25h     ΓöéAbsolute disk  ΓöéFully supported               Γöé
  6071. Γöé        Γöéread           Γöé                              Γöé
  6072. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6073. Γöé26h     ΓöéAbsolute disk  ΓöéFully supported, but error    Γöé
  6074. Γöé        Γöéwrite          Γöégenerated for attempt on fixedΓöé
  6075. Γöé        Γöé               Γöédisk                          Γöé
  6076. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6077. Γöé27h     ΓöéTerminate/stay ΓöéFully supported               Γöé
  6078. Γöé        Γöéresident       Γöé                              Γöé
  6079. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6080. Γöé28h     ΓöéIdle loop      ΓöéFully supported               Γöé
  6081. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6082. Γöé2fh     ΓöéMultiplex      ΓöéWhen a DOS application issues Γöé
  6083. Γöé        Γöé               Γöéan INT 2fh with AX=1680h, it  Γöé
  6084. Γöé        Γöé               Γöéyields its time slice.        Γöé
  6085. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6086. Γöé33h     ΓöéMouse          ΓöéFully support, providing      Γöé
  6087. Γöé        Γöé               ΓöéVMOUSE.SYS driver is loaded   Γöé
  6088. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6089. Γöé67h     ΓöéLIM expanded   ΓöéSupported when Expanded MemoryΓöé
  6090. Γöé        Γöémemory manager ΓöéManager VDD is installed.     Γöé
  6091. Γöé        Γöé               ΓöéSupports LIM EMS V4.0         Γöé
  6092. Γöé        Γöé               Γöéfunctions.                    Γöé
  6093. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  6094. Table 9-10. Virtualized DOS Software Interrupts 
  6095.  
  6096.  
  6097. ΓòÉΓòÉΓòÉ 12.15. Sample Virtual Device Driver ΓòÉΓòÉΓòÉ
  6098.  
  6099. The following code represents a sample VDD designed to work with the simple 
  6100. parallel PDD outlined in Chapter 7. It is written using the IBM C Set/2 
  6101. compiler. This VDD traps I/O to the 8-bit ports from a DOS application running 
  6102. in a VDM. This VDD performs simple input and output to the dedicated parallel 
  6103. port adapter described in Chapter 7. 
  6104.  
  6105. Note that input and output for OS/2 printer ports is handled much differently 
  6106. than in the sample driver. For OS/2 printer I/O, the OS/2 virtual printer 
  6107. driver VLPT calls the OS/2 kernel, which formats the request into a standard 
  6108. OS/2 Request Packet. The kernel then sends the Request Packet to the PDD for 
  6109. disposition. 
  6110.  
  6111. The VDD can perform input and output in one of two ways. The VDD can ask the 
  6112. PDD to use the specific ports and, if permission is granted, can do the inputs 
  6113. and outputs directly from within the VDD. The VDD can also call the PDD and 
  6114. have the PDD perform the required I/O, and pass the results back to the VDD. If 
  6115. the adapter is dedicated to the VDM application, and no other programs will 
  6116. access it, the VDD need not call a PDD to perform the operation. If the adapter 
  6117. can be accessed by protect mode programs, the VDD must get permission to use 
  6118. the adapter by calling the PDD. The PDD will queue up any subsequent requests 
  6119. from other threads until the VDD is finished with the adapter. 
  6120.  
  6121. In most cases, writing a VDD will be unnecessary, as most of the required DOS 
  6122. virtualization is handled by the VDDs that come with OS/2 2.1. Writing a VDD is 
  6123. only necessary if the DOS application needs to support a custom adapter in a 
  6124. VDM which cannot be serviced by the existing VDD supplied with OS/2. This 
  6125. should be rare, as most new applications should be written for protect mode 
  6126. operation. 
  6127.  
  6128. In this sample VDD, the VDD traps I/O on a per-DOS-session basis, to ports 
  6129. 0x210, 0x211 and 0x212. When the hook is entered, the VDD checks to see that 
  6130. the current requester is the also the current owner of the port. If not, the 
  6131. VDM application attempting the access is terminated. If the requester is valid, 
  6132. port trapping is disabled, allowing subsequent I/O to go directly to the 
  6133. hardware for increased performance. When the DOS session is exited, the I/O 
  6134. hooks are removed and port trapping is reenabled. This VDD shows you how to 
  6135. call some basic VDH functions, such as VDHInstallIOHook, VDHRemoveIOHook, and 
  6136. VDHInstallUserHook. 
  6137.  
  6138. When a VDM is created, the PIOCreate routine is called, and when the VDM is 
  6139. closed, the PIOTerminate routine is called. PIOCreate is called with a handle 
  6140. to the VDM, which is actually the base linear address of the VDM. You may 
  6141. verify the operation of any of these funtions if you have the kernel debugger 
  6142. installed. Simply place a call to VdhInt3 in the source code, recompile and 
  6143. relink, then reboot. The VdhInt3 call will cause a break at the debugging 
  6144. terminal, and if you used the MAPSYM after the link, you can examine VDD 
  6145. variables. Do not insert the call to VdhInt3 if you do not have the kernel 
  6146. debugger installed, or have the debugging terminal connected. 
  6147.  
  6148. /*   file pioinit.c  */
  6149.  
  6150. /****************************************************************/
  6151. /*  sample parallel port VDD init section                       */
  6152. /****************************************************************/
  6153.  
  6154. #include "mvdm.h"                       /* VDH services, etc.   */
  6155. #include "pio.h"                        /* PIO  data defines    */
  6156.  
  6157. #pragma entry (_PIOInit)
  6158.  
  6159. #pragma data_seg(CSWAP_DATA)
  6160.  
  6161. extern  SZ szProplpt1timeout;
  6162.  
  6163. #pragma alloc_text(CINIT_TEXT,_PIOInit,PIO_PDDProc)
  6164.  
  6165. /* init entry point called by system at load time */
  6166.  
  6167. BOOL EXPENTRY _PIOInit(psz)             /* PIO VDDInit */
  6168. {
  6169.  
  6170.     /* Register a VDM termination handler entry point*/
  6171.  
  6172.     if ((VDHInstallUserHook((ULONG)VDM_TERMINATE,
  6173.                             (PUSERHOOK)PIOTerminate)) == 0)
  6174.        return 0;          /* return FALSE if VDH call failed */
  6175.  
  6176.     /* Register a VDM creation handler entry point */
  6177.  
  6178.     if ((VDHInstallUserHook((ULONG)VDM_CREATE,
  6179.                             (PUSERHOOK)PIOCreate)) == 0)
  6180.        return 0 ;         /* return FALSE if VDH call failed */
  6181.  
  6182.     /* Get the entry point to the PDD */
  6183.  
  6184.     PPIOPDDProc = VDHOpenPDD(PDD_NAME, PIO_PDDProc);
  6185.  
  6186.     return CTRUE;
  6187. }
  6188.  
  6189. /* entry point registered by VDHOpenPDD, called by the PDD            */
  6190.  
  6191. SBOOL VDDENTRY PIO_PDDProc(ulFunc,f16p1,f16p2)
  6192. ULONG ulFunc;
  6193. F16PVOID f16p1;
  6194. F16PVOID f16p2;
  6195. {
  6196.     return 0;
  6197. }
  6198.  
  6199. Example 9-1. VDD initialization section. 
  6200.  
  6201. /* piodata.c */
  6202.  
  6203. #include "mvdm.h"                       /* VDH services, etc.   */
  6204. #include "pio.h"                        /* PIO specific         */
  6205.  
  6206. #pragma data_seg(SWAPINSTDATA)
  6207.  
  6208. HVDM owner_VDM = 0;                     /*  actual VDM handle   */
  6209. HVDM current_VDM;
  6210. ULONG Resp = 0;
  6211.  
  6212. #pragma data_seg(CSWAP_DATA)
  6213.  
  6214. FPFNPDD PPIOPDDProc = (FPFNPDD)0;       /* addr of PDD entry pt */
  6215.  
  6216. Example 9-2. VDD data segment. 
  6217.  
  6218. /*  pioin.c */
  6219.  
  6220. #include "mvdm.h"                       /* VDH services, etc.   */
  6221. #include "pio.h"
  6222. #include "basemid.h"
  6223.  
  6224. /* PIO specific         */
  6225.  
  6226. #pragma alloc_text(CSWAP_TEXT,PIODataIn,RequestDirect)
  6227.  
  6228. extern IOH Ioh;
  6229.  
  6230. /* entry from data input trap in VDM */
  6231.  
  6232. BYTE HOOKENTRY PIODataIn(ULONG portaddr, PCRF pcrf)
  6233. {
  6234.     BYTE dataread;                     /* set up byte to return */
  6235.  
  6236.     RequestDirect();
  6237.  
  6238.     /* disable I/O trap */
  6239.  
  6240.     VDHSetIOHookState(current_VDM,DIGIO_BASE,3,&Ioh,0);
  6241.  
  6242.     dataread = inp(portaddr);
  6243.     return(dataread);                  /* return data read      */
  6244. }
  6245.  
  6246. BOOL HOOKENTRY RequestDirect(void)
  6247. {
  6248.    if (owner_VDM != current_VDM)
  6249.    {
  6250.       if (owner_VDM !=0)
  6251.       {
  6252.    VDHPopup(0,0,MSG_DEVICE_IN_USE,&Resp,ABORT,0);
  6253.    if (Resp != ABORT)
  6254.    {
  6255.       VDHKillVDM(current_VDM);
  6256.       owner_VDM = current_VDM;
  6257.    }
  6258.  }
  6259.  else
  6260.    owner_VDM = current_VDM;
  6261.    }
  6262. }
  6263.  
  6264. Example 9-3. VDD input handler. 
  6265.  
  6266. /* pioout.c */
  6267.  
  6268. #include "mvdm.h"                       /* VDH services, etc.   */
  6269. #include "pio.h"                        /* PIO specific         */
  6270.  
  6271. #pragma data_seg(CSWAP_DATA)
  6272.  
  6273. extern IOH Ioh;
  6274.  
  6275. #pragma alloc_text(CSWAP_TEXT,PIODataOut)
  6276.  
  6277. /* this routine is the data out trap entry point */
  6278.  
  6279. VOID HOOKENTRY PIODataOut(BYTE chartowrite,ULONG portaddr,PCRF pcrf)
  6280. {
  6281.     RequestDirect();
  6282.  
  6283.     /* disable port trapping */
  6284.  
  6285.     VDHSetIOHookState(current_VDM,DIGIO_BASE,3,&Ioh,0);
  6286.  
  6287.     outp(portaddr,chartowrite);         /*  write the char */
  6288.     return;
  6289. }
  6290.  
  6291. Example 9-4. VDD data port output handler. 
  6292.  
  6293. /*  file piouser.c */
  6294.  
  6295. #include "mvdm.h"                         /* VDH services, etc.   */
  6296. #include "pio.h"                          /* PIO specific         */
  6297. #include "basemid.h"
  6298.  
  6299. #pragma data_seg(CSWAP_DATA)
  6300.  
  6301. /* our routines are for 8-bit ports */
  6302.  
  6303. IOH Ioh = {PIODataIn,PIODataOut,0,0,0};
  6304.  
  6305. #pragma alloc_text(CSWAP_TEXT,PIOCreate,PIOTerminate)
  6306.  
  6307. /*----------------------------------------------------------------
  6308.  
  6309. PIOCreate, entered when the VDM is created
  6310.  
  6311. ----------------------------------------------------------------*/
  6312.  
  6313. BOOL HOOKENTRY PIOCreate(hvdm)
  6314. HVDM hvdm;
  6315. {
  6316.     current_VDM = hvdm;    /* save our vdm handle */
  6317.  
  6318.     /* install I/O hooks for our three 8-bit ports */
  6319.  
  6320.     if ((VDHInstallIOHook(hvdm,
  6321.                           DIGIO_BASE,
  6322.                           3,
  6323.                           (PIOH)&Ioh,
  6324.                           !VDH_ASM_HOOK)) == 0)
  6325.     {
  6326.         PIOTerminate(hvdm);
  6327.         return 0;             /* return FALSE               */
  6328.     }
  6329.  
  6330.     return CTRUE;
  6331. }
  6332.  
  6333. /*----------------------------------------------------------------
  6334.  
  6335. PIOTerminate, called when the VDM terminates. This code is
  6336. optional, as the User and IO hooks are removed automatically by
  6337. the system when the VDM terminates. It is shown for example.
  6338.  
  6339. ----------------------------------------------------------------*/
  6340.  
  6341. BOOL HOOKENTRY PIOTerminate(hvdm)
  6342. HVDM hvdm;
  6343. {
  6344.  
  6345.    owner_VDM = 0;
  6346.  
  6347.    VDHRemoveIOHook(hvdm,         /* remove the IO hooks        */
  6348.                    DIGIO_BASE,
  6349.                    3,
  6350.                    (PIOH)&Ioh);
  6351.  
  6352.    return CTRUE;
  6353. }
  6354.  
  6355. Example 9-5. VDD user routines. 
  6356.  
  6357. /*
  6358.  digio memory map for os/2 virtual device driver
  6359. */
  6360.  
  6361. #define  DIGIO_BASE   0x210        /* board address                */
  6362. #define  DIGIO_OUTPUT DIGIO_BASE   /* output port                  */
  6363. #define  DIGIO_INPUT  DIGIO_BASE+1 /* input port                   */
  6364. #define  DIGIO_CONFIG DIGIO_BASE+2 /* initialization port          */
  6365.  
  6366. #define  ABORT 0x02
  6367.  
  6368. /* name of the PDD */
  6369.  
  6370. #define PDD_NAME      "DIGIO$  \0"  /* string                      */
  6371.  
  6372. /* pioinit.c */
  6373.  
  6374. BOOL EXPENTRY  PIOInit(PSZ);
  6375. SBOOL VDDENTRY PIO_PDDProc(ULONG,F16PVOID,F16PVOID);
  6376.  
  6377. /* piouser.c */
  6378.  
  6379. BOOL HOOKENTRY PIOCreate(HVDM);
  6380. BOOL HOOKENTRY PIOTerminate(HVDM);
  6381.  
  6382. /* pioin.c */
  6383.  
  6384. BYTE HOOKENTRY PIODataIn(ULONG, PCRF);
  6385. BOOL HOOKENTRY RequestDirect(void);
  6386.  
  6387. /* pioout.c */
  6388.  
  6389. VOID HOOKENTRY PIODataOut(BYTE, ULONG, PCRF);
  6390. VOID HOOKENTRY PIOConfigOut(BYTE, ULONG, PCRF);
  6391.  
  6392. extern ULONG   MachineType;               /* Machine Type            */
  6393. extern FPFNPDD PPIOPDDProc;               /* addr of PDD entry point */
  6394. extern HVDM    owner_VDM;
  6395. extern HVDM    current_VDM;
  6396. extern ULONG   Resp;
  6397.  
  6398. /* ioseg */
  6399.  
  6400. USHORT _Far32 _Pascal inp(ULONG);
  6401. VOID   _Far32 _Pascal outp(ULONG,USHORT);
  6402.  
  6403. Example 9-6. VDD include file. 
  6404.  
  6405. vpio.sys: pioinit.obj piouser.obj pioin.obj pioout.obj piodata.obj \
  6406. ioseg.obj
  6407.  link386 /A:16 /M:FULL /NOL pioinit+piouser+pioin+pioout+\
  6408. piodata+ioseg,vpio.sys,vpio.map,vdh,pio.def
  6409.  mapsym vpio
  6410.  
  6411. pioinit.obj: pioinit.c mvdm.h pio.h
  6412.  icc /Sm /Ss /O /Q /W2 /Rn /Gr /C pioinit.c
  6413.  
  6414. pioin.obj: pioin.c pio.h mvdm.h
  6415.  icc /Sm /Ss /Q /O /W2 /Rn /Gr /C pioin.c
  6416.  
  6417. pioout.obj: pioout.c pio.h mvdm.h
  6418.  icc /Sm /Ss /Q /O /W2 /Rn /Gr /C pioout.c
  6419.  
  6420. piouser.obj: piouser.c pio.h mvdm.h
  6421.  icc /Sm /Ss /Q /O /W2 /Rn /Gr /C piouser.c
  6422.  
  6423. piodata.obj: piodata.c pio.h mvdm.h
  6424.  icc /Sm /Ss /Q /O /W2 /Rn /Gr /C piodata.c
  6425.  
  6426. ioseg.obj: ioseg.asm
  6427.         masm /Mx /x ioseg.asm;
  6428.  
  6429.  
  6430. VIRTUAL DEVICE VPIO
  6431. PROTMODE
  6432.  
  6433. STUB             'OS2STUB.EXE'
  6434. SEGMENTS
  6435.     CODE32       CLASS 'CODE'      SHARED    NONDISCARDABLE  RESIDENT
  6436.     _TEXT        CLASS 'CODE'      SHARED    NONDISCARDABLE  RESIDENT
  6437.     CINIT_TEXT   CLASS 'CODE'      SHARED    DISCARDABLE     RESIDENT
  6438.     CSWAP_TEXT   CLASS 'CODE'      SHARED    NONDISCARDABLE
  6439.     CINIT_DATA   CLASS 'CINITDATA' SHARED    DISCARDABLE     RESIDENT
  6440.     CSWAP_DATA   CLASS 'CSWAPDATA' SHARED    NONDISCARDABLE
  6441.     MVDMINSTDATA CLASS 'MIDATA'    NONSHARED NONDISCARDABLE  RESIDENT
  6442.     SWAPINSTDATA CLASS 'SIDATA'    NONSHARED NONDISCARDABLE
  6443.     DATA32       CLASS 'DATA'      SHARED    NONDISCARDABLE  RESIDENT
  6444.     _DATA        CLASS 'DATA'      SHARED    NONDISCARDABLE  RESIDENT
  6445.  
  6446. Example 9-7. VDD Make And DEF Files. 
  6447.  
  6448.  
  6449. ΓòÉΓòÉΓòÉ 12.16. Establishing a VDD-PDD Link ΓòÉΓòÉΓòÉ
  6450.  
  6451. Note that, in this VDD, the actual I/O was performed by the VDD routines 
  6452. PIODataIn and PIODataOut. The VDD could have called the PDD to perform the 
  6453. actual I/O. This would be necessary if the I/O involved interrupts, as device 
  6454. interrupts must be handled by a PDD. 
  6455.  
  6456. The PDD requires slight modifications to support VDD-PDD communications. The 
  6457. PDD must register its ability to provide VDD support by issuing a RegisterPDD 
  6458. DevHlp call in the Init section of the PDD. The RegisterPDD informs OS/2 of the 
  6459. name of the PDD and the 16:16 address of the PDD's communication function. Note 
  6460. that this is not the same entry point as defined by the IDC entry point in the 
  6461. PDD Device Header. The VDD can then establish communications with the PDD by 
  6462. calling the VDHOpenPDD Virtual Device Helper function. This is one of the 
  6463. reasons that OS/2 loads all of the PDDs before the VDDs during system boot. 
  6464. Note that this DevHlp function has no error return. A failure when registering 
  6465. the PDD will cause a system crash during boot. 
  6466.  
  6467. If the PDD fails initialization for another reason, such as a failed SetIRQ or 
  6468. SetTimer, the PDD must release the PDD-VDD registration by calling RegisterPDD, 
  6469. with the function pointer equal to 0:0. The PDD described in Chapter 7 would be 
  6470. modified as outlined in Example 9-8. 
  6471.  
  6472. Init code
  6473. .
  6474. .
  6475. RegisterPDD((FPUCHAR)devhdr.DHname,(FARPOINTER)DigioComm);
  6476. .
  6477. .
  6478.  
  6479. more Init code
  6480.  
  6481. main Strategy code section
  6482. .
  6483. *per.
  6484. DigioComm(ULONG Func, ULONG Parm1, ULONG Parm2)
  6485. {
  6486.  
  6487.    VDD-PDD comm code here
  6488. }
  6489. .
  6490. .
  6491.  
  6492. Example 9-8. Registering PDD for VDD-PDD communications. 
  6493.  
  6494. During initialization, the VDD calls VDHOpenPDD, passing it the ASCII-Z name of 
  6495. the PDD and the 16:32 entry point of the VDD's communication routine. Note the 
  6496. call to VDHOpenPDD in the pioinit.c routine above. If VDHOpenPDD (or any other 
  6497. VDH call) fails, it will return FALSE and the driver must call VDHGetError to 
  6498. retrieve the exact error. If the call succeeds, VDHOpenPDD returns a pointer to 
  6499. the PDD's communication routine, previously registered by the RegisterPDD call 
  6500. in the PDD Init section. 
  6501.  
  6502. The two drivers communicate by sending a structure back and forth. This 
  6503. structure is described in Example 9-9. The first parameter is a private 
  6504. function code, which the drivers pass back and forth to identify the operation 
  6505. to be performed.  The two parameters can be data or 16:16 pointers to input and 
  6506. output packets.  The VDD-PDD communication functions should return nonzero for 
  6507. success, and zero for failure. 
  6508.  
  6509. If the PDD allocates any resources on behalf of the VDD, the VDD must call the 
  6510. PDD to release those resources when the VDM is destroyed. 
  6511.  
  6512. typedef _DRVCOMM {
  6513.     ULONG     FunctionCode;
  6514.     ULONG     Parm1;
  6515.     ULONG     Parm2;
  6516.     }  DRVCOMM;
  6517.  
  6518. Example 9-9. VDD-PDD communications structure. 
  6519.  
  6520.  
  6521. ΓòÉΓòÉΓòÉ 13. Chapter 10 - Memory-Mapped Adapters and IOPL ΓòÉΓòÉΓòÉ
  6522.  
  6523. A large number of adapters provide on-board memory for communication between 
  6524. the adapter and the program or drivers. Generally, a program or driver maps the 
  6525. on-board memory to a physical memory address, and reads or writes board memory 
  6526. as if it were normal system RAM. These adapters are referred to as 
  6527. memory-mapped adapters. Memory-mapped adapters, when placed in a special 
  6528. hardware mode, appear to a device driver or application as normal RAM memory. 
  6529. An application that is allowed direct access to the adapter memory can transfer 
  6530. data much faster than if it were to call a device driver to perform the 
  6531. transfer. This type of operation, called memory-mapped I/O, can result in 
  6532. increased performance and is the preferred method for transferring large 
  6533. amounts of memory quickly. Memory-mapped adapters may also utilize interrupts 
  6534. or DMA. An example of a memory-mapped adapter would be a video adapter, such as 
  6535. a VGA card. 
  6536.  
  6537. Programs that perform transfers with memory-mapped adapters usually write data 
  6538. in a special format to an area of memory between the 640K and one megabyte, 
  6539. although some adapters can be mapped in the region above one megabyte. 
  6540.  
  6541. The most common example of a memory-mapped adapter is, of course, the standard 
  6542. VGA graphics adapter found in most IBM clones. Data to be displayed on the 
  6543. screen is written to the adapter's RAM memory. The video controller constantly 
  6544. reads this memory, converts it to electrical signals and presents these voltage 
  6545. levels to the actual display device. If you power down your display terminal 
  6546. and power it back up, the contents of the display is not lost because the 
  6547. display is actually kept in video memory, not in the display itself. 
  6548.  
  6549.  
  6550. ΓòÉΓòÉΓòÉ 13.1. High and Low Memory Maps ΓòÉΓòÉΓòÉ
  6551.  
  6552. Memory-mapped adapters come in two basic flavors. The first has a memory- 
  6553. mapped address that is selectable in the area between 640K and one megabyte. 
  6554. Some of the memory space between 640K and one megabyte is reserved for such 
  6555. things as BIOS shadow RAM and video memory. There is room, however, to map an 
  6556. adapter board in that space, providing no address conflicts exist. Most 
  6557. memory-mapped adapters were designed for personal computers running DOS, so 
  6558. there was no need to provide memory-mapped addresses greater than one megabyte. 
  6559. Recall that DOS runs in the real mode of the Intel microprocessor, which 
  6560. provides for only a 20-bit address. This limits the addressing capability of 
  6561. the CPU to one megabyte, so an adapter designed for the DOS environment that 
  6562. could be mapped to addresses greater than one megabyte would not be of much 
  6563. use. 
  6564.  
  6565. The second type has a memory-mapped address of greater than one megabyte. The 
  6566. 32-bit addressing mode of OS/2 2.1 allows adapters to be mapped above the one 
  6567. megabyte boundary and accessed directly. 
  6568.  
  6569. ISA bus memory-mapped adapters use small jumpers or switches to set their 
  6570. memory-mapped address, while Micro Channel adapters usually contain their 
  6571. memory-mapped address in the POS registers (see Chapter 3). Some recently- 
  6572. introduced adapters designed to run in 32-bit systems like OS/2 have been 
  6573. designed for memory-mapped addresses of greater than one megabyte. 
  6574.  
  6575.  
  6576. ΓòÉΓòÉΓòÉ 13.2. Application Program Access To Adapter Memory ΓòÉΓòÉΓòÉ
  6577.  
  6578. One of the most important features of OS/2 is its ability to protect programs 
  6579. from one another. With the aid of the protect mode circuitry in the CPU, the 
  6580. operating system can determine beforehand if a program is about to read from or 
  6581. write to another program's memory space. If the processor detects this kind of 
  6582. error, the system's error handler is called to display the error and the 
  6583. offending program is immediately terminated. How then does an application 
  6584. operating at Ring 3 gain access to the memory-mapped adapter address that is 
  6585. not within its own address space? 
  6586.  
  6587. Recall the discussion of the processor architecture in Chapter 3. As was 
  6588. outlined, a program's access to memory is controlled by selectors, which are 
  6589. indexes into the program's Local Descriptor Table. The descriptor contains a 
  6590. physical address and Requested Privilege Level, or RPL, of the memory object. 
  6591. When a program is executed, it get's its own list of selectors, or LDT, which 
  6592. defines its valid addressable memory areas and their access restrictions. When 
  6593. the program attempts to read or write memory, the CPU compares the target 
  6594. address and type of operation to a corresponding entry in the LDT. If the 
  6595. program does not have access to the target memory, a General Protect, or GP 
  6596. fault is generated, and the program is immediately terminated. If the address 
  6597. is valid, the CPU verifies that the memory has the correct permissions, such as 
  6598. read and write, and generates a fault if the permissions do not agree with the 
  6599. attempted operation. 
  6600.  
  6601. If the adapter's memory-mapped address could be placed in the application's 
  6602. LDT, the program would be free to access the adapter's memory. The 
  6603. application's LDT, however, is created at load time, and is not modifiable by 
  6604. the application. If that were permitted, applications would be free to select 
  6605. the memory addresses they wished to read and write, and crash OS/2. The only 
  6606. program that can grant an application access to memory is a device driver. The 
  6607. device driver, operating at Ring 0, is free to manipulate the application's 
  6608. environment, with some limitations. 
  6609.  
  6610. To allow the application to access the foreign memory, the application program 
  6611. opens up the device driver and passes it the physical address and size of the 
  6612. memory it wishes to access. For most adapters, the memory size is generally 4K, 
  6613. 8K, 16K, or 32K bytes. The driver should first verify that the memory address 
  6614. is within the valid range for the adapter. The driver can be hard-coded with 
  6615. the valid physical addresses, it can be sent the address via an IOCtl, or the 
  6616. valid address could be entered at driver load time in the "DEVICE=XXX.SYS" line 
  6617. in the CONFIG.SYS file (see Chapter 8). The driver then allocates an LDT 
  6618. selector for the new adapter address. Even though the LDT belongs to the 
  6619. application, the driver can access it freely. This is due to the fact that when 
  6620. the driver is called by the application, the driver and application share the 
  6621. same context. 
  6622.  
  6623. Next, the driver calls the OS/2 system DevHlp function PhysToUVirt (see Example 
  6624. 10-1), which maps the physical address to an LDT selector in the application's 
  6625. LDT.  The result is referred to as a fabricated address.  Using an IOCtl, the 
  6626. driver then passes back the new LDT selector:offset value to the application. 
  6627. The application makes a pointer from the selector using the MAKEP macro, and 
  6628. uses this pointer for direct access to adapter memory.  The LDT entry remains 
  6629. valid until the program is terminated. 
  6630.  
  6631. if ( PhysToUVirt(0xd8000, 0x8000, 1, &mem))
  6632.      return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  6633.  
  6634. Example 10-1. PhysToVirt call. 
  6635.  
  6636. The 0xd8000 is the physical adapter memory address. The 0x8000 is the requested 
  6637. size, the parameter 1 means get a virtual pointer and make the memory 
  6638. read-write, and &mem is the address of DS-relative storage for the returned 
  6639. virtual address. 
  6640.  
  6641.  
  6642. ΓòÉΓòÉΓòÉ 13.3. Access to Adapter Memory In the Interrupt Handler ΓòÉΓòÉΓòÉ
  6643.  
  6644. In some cases, such as upon receipt of an interrupt, the device driver may be 
  6645. required to access memory-mapped adapter inside the interrupt handler. If a 
  6646. driver is required to perform interrupt-time memory transfers, it should set up 
  6647. the references to the memory in the INIT section. Since the interrupt handler 
  6648. can be entered in any context, the LDT of the application may not be in the 
  6649. current context. The driver cannot use an LDT to address memory, but must use a 
  6650. GDT entry for memory access. The GDT entry will be valid in any context. 
  6651.  
  6652. If the device driver will be performing memory-mapped transfers inside an 
  6653. interrupt handler, it must allocate the required selector(s) by issuing the 
  6654. AllocGDTSelector DevHlp, then map the new selector(s) to the physical address 
  6655. with the PhysToGDTSelector DevHlp call. (see Example 10-2). The driver now has 
  6656. direct addressability to the adapter memory regardless of context, and can 
  6657. freely transfer data to and from the adapter memory at interrupt time. The 
  6658. device driver must allocate and map the GDT selector(s) during INIT. However, 
  6659. remember that the INIT code is run as a Ring 3 thread of the system, so the 
  6660. driver cannot access the memory mapped to the GDT selector at INIT time. 
  6661.  
  6662. A complete memory-mapped device driver and sample 16-bit and 32-bit application 
  6663. code is shown in the Listings section. 
  6664.  
  6665. // allocate space for a GDT selector during INIT
  6666.  
  6667.  if (AllocGDTSelector (1,sel_array))
  6668.        {                               // allocate a GDT sel
  6669.  DosPutMessage(1, 8, devhdr.DHname);
  6670.  DosPutMessage(1,strlen(GDTFailMsg),GDTFailMsg);
  6671.  break;
  6672.  }
  6673.  
  6674.  // now map the board memory address to the GDT selector
  6675.  
  6676.  if (PhysToGDTSelector (board_address,
  6677.                        (USHORT) MEMSIZE,
  6678.                        sel_array[0],
  6679.                        &err))
  6680.        {
  6681.  DosPutMessage(1, 8, devhdr.DHname);
  6682.  DosPutMessage(1,strlen(SELFailMsg),SELFailMsg);
  6683.  break;
  6684.  }
  6685.  
  6686.  fabricated_ptr = MAKEP(sel_array[0],0);
  6687.  
  6688. Example 10-2. Mapping a GDT selector during INIT. 
  6689.  
  6690.  
  6691. ΓòÉΓòÉΓòÉ 13.4. Input/Output Privilege Level (IOPL) ΓòÉΓòÉΓòÉ
  6692.  
  6693. OS/2 allows programs with I/O Privilege (IOPL) enabled to do direct register 
  6694. I/O to a device. If the device your application will be using is a parallel 
  6695. card or digital switch, an actual device driver may not be necessary. With 
  6696. IOPL, the application program can perform direct register I/O using IN and OUT 
  6697. instructions. If the device does not require interrupt or timer support, IOPL 
  6698. may be the ticket. 
  6699.  
  6700. Note, however, that IOPL is a processor-specific function, and thus is not 
  6701. portable across hardware platforms such as RISC. For instance, the port mapping 
  6702. of a MIPS processor is not the same as an Intel processor, so code written for 
  6703. one processor will not necessarily run on another processor. The current trend 
  6704. is to migrate operating systems onto other platforms such as RISC and SMP. For 
  6705. these reasons, you can only perform IOPL from a 16-bit segment, and cannot 
  6706. enable a 32-bit C Set/2 segment to perform IOPL. 16-bit segments are allowed to 
  6707. perform IOPL since the 16-bit segments themselves are processor-dependent, and 
  6708. can't be migrated to other processor platforms anyway. 
  6709.  
  6710. There are circumstances when it makes sense, for performance reasons, to allow 
  6711. the application to perform simple I/O. This could mean something as simple as 
  6712. controlling an external switch, or testing for a single bit from an I/O port. 
  6713. Calling a device driver to accomplish this is the preferred method, since its 
  6714. more likely to be portable. Under some circumstances, however, IOPL may be the 
  6715. best solution. 
  6716.  
  6717.  
  6718. ΓòÉΓòÉΓòÉ 13.5. The IOPL Segment ΓòÉΓòÉΓòÉ
  6719.  
  6720. To enable IOPL, the segment descriptors of the segment that contains the I/O 
  6721. code must be marked Descriptor Privilege Level, or DPL 2. OS/2 allows segments 
  6722. with properly marked descriptors to perform direct register I/O. There are two 
  6723. ways you can structure your IOPL routines. If you're using Microsoft C 6.0, the 
  6724. inp and outp functions are located in a separate segment called _IOSEG. You can 
  6725. indicate with your DEF file to mark _IOSEG as IOPL, and call the standard 
  6726. run-time library routines inp and outp. You can also write a simple function 
  6727. (See Example 10-3)  to perform the input and output. 
  6728.  
  6729. ; Sample IOPL segment
  6730.  
  6731.             PUBLIC  IN_PORT
  6732.             PUBLIC  OUT_PORT
  6733.  
  6734.             .model  large
  6735.             .286P
  6736.  
  6737. DGROUP      GROUP   _DATA
  6738. _DATA       SEGMENT WORD PUBLIC  'DATA'
  6739. _DATA       ENDS
  6740.  
  6741. _IOSEG      segment word use16 public 'CODE'
  6742.  
  6743.             assume  CS:_IOSEG,DS:DGROUP,SS:DGROUP
  6744.             .286P
  6745. ;
  6746. IN_PORT     proc far
  6747. ;
  6748.      push   bp        ;set up stack frame
  6749.      mov    bp,sp     ;save bp
  6750.      push   dx        ;save dx
  6751.      mov    dx,[bp+6] ;get port address
  6752.      in     ax,dx     ;do input
  6753.      pop    dx        ;restore regs
  6754.      pop    bp        ;return in ax
  6755.      ret    2         ;remove from IOPL stack
  6756. ;
  6757. IN_PORT     endp
  6758.  
  6759. OUT_PORT    proc far
  6760. ;
  6761.      push   bp          ;set up stack frame
  6762.      mov    bp,sp       ;save it
  6763.      push   ax          ;save ax
  6764.      push   dx          ;and dx
  6765.      mov    ax,[bp+6]   ;get data
  6766.      mov    dx,[bp+8]   ;get port
  6767.      out    dx,al       ;do output
  6768.      pop    dx          ;restore regs
  6769.      pop    ax
  6770.      pop    bp
  6771.      ret    4           ;remove off local stack
  6772. ;
  6773. OUT_PORT    endp
  6774.  
  6775. _IOSEG      ends
  6776.             end
  6777.  
  6778. Example 10-3. IOPL Segment. 
  6779.  
  6780. During the link operation, the linker is told to mark the special segment as 
  6781. IOPL. The linker must also know the names of the exported routines and the size 
  6782. of the parameters that will be passed to the routines by the Ring 3 
  6783. application. The number of words that the parameters will occupy on the stack 
  6784. is extremely important. Since the Ring 3 code (application) and the Ring 2 code 
  6785. (the IOPL code) do not share the same physical stack area, OS/2 must copy the 
  6786. contents of the Ring 3 stack to the Ring 2 stack. The linker informs OS/2 of 
  6787. the number of bytes to copy by the size parameter in the EXPORTS statement in 
  6788. the linker module definition file (see Example 10-4). 
  6789.  
  6790. NAME SAMPLE
  6791. STACKSIZE   8192
  6792. SEGMENTS
  6793.      _IOSEG IOPL
  6794. EXPORTS
  6795.      PORTIN 1
  6796.      PORTOUT 2
  6797. PROTMODE
  6798.  
  6799. Example 10.4 IOPL DEF file. 
  6800.  
  6801. When the application calls either the IN_PORT or OUT_PORT routine, OS/2 will 
  6802. perform a ring transition from Ring 3 to Ring 2, copy the caller's stack to the 
  6803. separate Ring 2 stack, call the I/O routine, and perform another ring 
  6804. transition back to the Ring 3 application. Because of the extra overhead in 
  6805. ring transitions and copying stacks, this method will not be as fast as the DOS 
  6806. equivalent, but will be much faster than calling the device driver for every 
  6807. port input or output. 
  6808.  
  6809. Remember that devices that generate interrupts, require asynchronous service, 
  6810. or operate in a time-critical environment must utilize a device driver. You may 
  6811. be able to get by using memory-mapping and IOPL, and I suggest using it if 
  6812. possible. Just keep in mind that eventually, OS/2 PDDs will eventually become 
  6813. 32-bit PDDs, and the handy shortcuts like memory-mapping and IOPL will most 
  6814. likely disappear. 
  6815.  
  6816.  
  6817. ΓòÉΓòÉΓòÉ 13.6. IOPL From 32-bit Applications ΓòÉΓòÉΓòÉ
  6818.  
  6819. IOPL is not permitted from 32-bit segments. To use IOPL from a 32-bit 
  6820. application, the application must call I/O routines located in a 16-bit 
  6821. segment. The easiest way to do this is to create a simple 16-bit DLL, then link 
  6822. it to the application with the IMPLIB utility. The same IOPL code can be used 
  6823. for 16- bit and 32-bit applications. A complete set of code for performing IOPL 
  6824. from 16-bit and 32-bit applications can be found in the Listings section. 
  6825.  
  6826.  
  6827. ΓòÉΓòÉΓòÉ 14. Chapter 11 - Direct Memory Access (DMA) ΓòÉΓòÉΓòÉ
  6828.  
  6829. DMA is the ability of a device to access the computer system's memory without 
  6830. going through the CPU. Since DMA reads and writes bypass the CPU, data can be 
  6831. transferred very quickly without affecting system performance. This feature is 
  6832. useful for devices that generate large amounts of data frequently, such as 
  6833. video frame grabbers or an Analog to Digital (A/D) converter. The  measure of a 
  6834. device's ability to transfer large amounts of data at a time is called its 
  6835. bandwidth. The larger the amount of data in a given time period, the higher the 
  6836. bandwidth. Devices that transfer large amounts of data frequently are therefore 
  6837. called high bandwidth devices. An example of a high bandwidth device would be a 
  6838. hard disk drive. The hard disk drive is capable of reading or writing large 
  6839. amounts of data very quickly. So quickly, in fact, that the CPU and device 
  6840. driver software cannot keep up with the disk drive's data transfer rate. If a 
  6841. read was requested from the disk driver using the CPU, the data from the disk 
  6842. would appear faster than the CPU could dispose of it, leading to overruns and 
  6843. data corruption. 
  6844.  
  6845.  
  6846. ΓòÉΓòÉΓòÉ 14.1. The DMA Controller ΓòÉΓòÉΓòÉ
  6847.  
  6848. Since memory is connected to the computer system's bus, the DMA controller must 
  6849. request that the CPU "give up" the bus for a short period of time. The DMA 
  6850. controller is a special set of circuitry responsible for performing the DMA 
  6851. transactions. Since memory is connected to the computer system's bus, the DMA 
  6852. controller must request that the CPU "give up" the bus for a short period of 
  6853. time. When the DMA controller needs to transfer data, it asks the CPU for 
  6854. control of the bus by issuing a HOLD request. When the CPU can release the bus, 
  6855. it grants the DMA controller use of the bus by raising a HOLD ACKNOWLEDGE or 
  6856. HLDA signal. When the DMA controller sees the HLDA signal, it begins 
  6857. transferring data to or from the adapter to the computer's memory. Memory 
  6858. transfers are very fast, much faster than if the CPU was involved. When the DMA 
  6859. controller finishes transferring the data, it drops the HOLD line, allowing the 
  6860. CPU to again use the system bus. 
  6861.  
  6862. DMA is also a time-saving feature, in that it "steals" machine cycles from the 
  6863. CPU. The net effect is that of no noticeable loss in system performance, even 
  6864. when transferring large amounts of data. During DMA operation, the CPU remains 
  6865. free to execute program threads without knowledge of any DMA activity, other 
  6866. than the occasional giving up of the system bus. 
  6867.  
  6868. Most IBM-compatibles and clones use a configuration of two 8237A-5 4- channel 
  6869. DMA controllers. Like the 8259 PIC, the 8237A-5 controllers are cascaded to 
  6870. provide additional functionality. One channel of the upper four DMA channels is 
  6871. used for the cascade to the lower DMA controller, so a total of seven DMA 
  6872. channels are available (see Table 11-1). The first DMA controller, called DMA 
  6873. controller 1, contains channels 0-3. Channels 0-3 support 8-bit transfers 
  6874. between adapters and memory. The largest block of memory that can be 
  6875. transferred is 64K bytes. Channels 5-7 support 16-bit transfers between 
  6876. adapters and memory, and the largest block that can be transferred is 128K 
  6877. bytes. 
  6878.  
  6879. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  6880. ΓöéController 1ΓöéDescription      ΓöéController 2ΓöéDescription      Γöé
  6881. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6882. ΓöéChannel 0   Γöé8-bit DMA channelΓöéChannel 4   ΓöéCascade for      Γöé
  6883. Γöé            Γöé                 Γöé            Γöécontroller1      Γöé
  6884. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6885. ΓöéChannel 1   ΓöéReserved for SDLCΓöéChannel 5   Γöé16-bit DMA       Γöé
  6886. Γöé            Γöé                 Γöé            Γöéchannel          Γöé
  6887. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6888. ΓöéChannel 2   ΓöéDiskette (IBM PC)ΓöéChannel 6   Γöé16-bit DMA       Γöé
  6889. Γöé            Γöé                 Γöé            Γöéchannel          Γöé
  6890. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6891. ΓöéChannel 3   Γöé8-bit DMA channelΓöéChannel 7   Γöé16-bit DMA       Γöé
  6892. Γöé            Γöé                 Γöé            Γöéchannel          Γöé
  6893. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  6894. Table 11-1. DMA Channel Assignments. 
  6895.  
  6896. Since the 8237 is a 16-bit DMA controller with an 8 bit page register, all DMA 
  6897. transfers must occur from an address between 0 and 16 MB. The DMA controller 
  6898. contains a 16-bit address register, which limits the memory addressing. The DMA 
  6899. controller also has a count register, which is 16 bits long, limiting the 
  6900. transfers to 64KB (65536*8) with an 8-bit DMA channel and 128KB (65536*16) with 
  6901. a 16-bit channel. When using the 16-bit mode, bytes must be transferred on 
  6902. even-word boundaries. 
  6903.  
  6904. Table 11-2 lists the DMA controller port assignments. 
  6905.  
  6906. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  6907. ΓöéPort addressΓöéDescription                             Γöé
  6908. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6909. Γöé0000h       Γöéchannel 0 base/current address          Γöé
  6910. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6911. Γöé0001h       Γöéchannel 0 base/current word count       Γöé
  6912. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6913. Γöé0002h       Γöéchannel 1 base/current address          Γöé
  6914. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6915. Γöé0003h       Γöéchannel 1 base/current word count       Γöé
  6916. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6917. Γöé0004h       Γöéchannel 2 base/current address          Γöé
  6918. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6919. Γöé0005h       Γöéchannel 2 base/current word count       Γöé
  6920. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6921. Γöé0006h       Γöéchannel 3 base/current address          Γöé
  6922. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6923. Γöé0007h       Γöéchannel 3 base/current word count       Γöé
  6924. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6925. Γöé0008h       Γöéchannel 0-3 status register             Γöé
  6926. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6927. Γöé000Ah       Γöéchannel 0-3 mask register (set/reset)   Γöé
  6928. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6929. Γöé000Bh       Γöéchannel 0-3 mode register (write)       Γöé
  6930. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6931. Γöé000Ch       Γöéclear byte pointer (write)              Γöé
  6932. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6933. Γöé000Dh       ΓöéDMA controller reset (write)            Γöé
  6934. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6935. Γöé000Eh       Γöéchannel 0-3 clear mask register (write) Γöé
  6936. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6937. Γöé000Fh       Γöéchannel 0-3 write mask register         Γöé
  6938. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6939. Γöé0018h       Γöéextended function register (write)      Γöé
  6940. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6941. Γöé001Ah       Γöéextended function execute               Γöé
  6942. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6943. Γöé0081h       Γöéchannel 2 page table register           Γöé
  6944. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6945. Γöé0082h       Γöéchannel 3 page table register           Γöé
  6946. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6947. Γöé0083h       Γöéchannel 1 page table register           Γöé
  6948. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6949. Γöé0087h       Γöéchannel 0 page table register           Γöé
  6950. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6951. Γöé0089h       Γöéchannel 6 page table register           Γöé
  6952. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6953. Γöé008Ah       Γöéchannel 7 page table register           Γöé
  6954. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6955. Γöé008Bh       Γöéchannel 5 page table register           Γöé
  6956. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6957. Γöé008F        Γöéchannel 4 page table register           Γöé
  6958. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6959. Γöé0C0h        Γöéchannel 4 base/current address          Γöé
  6960. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6961. Γöé0C2h        Γöéchannel 4 base/current word count       Γöé
  6962. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6963. Γöé0C4h        Γöéchannel 5 base/current address          Γöé
  6964. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6965. Γöé0C6h        Γöéchannel 5 base/current word count       Γöé
  6966. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6967. Γöé0C8h        Γöéchannel 6 base/current address          Γöé
  6968. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6969. Γöé0CAh        Γöéchannel 6 base/current count            Γöé
  6970. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6971. Γöé0CCh        Γöéchannel 7 base/current address          Γöé
  6972. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6973. Γöé0CEh        Γöéchannel 7 base/current count            Γöé
  6974. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6975. Γöé0D0h        Γöéchannel 4-7 read status/write command   Γöé
  6976. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6977. Γöé0D2h        Γöéchannel 4-7 write request register      Γöé
  6978. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6979. Γöé0D4h        Γöéchannel 4-7 write single mask register  Γöé
  6980. Γöé            Γöébit                                     Γöé
  6981. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6982. Γöé0D6h        Γöéchannel 4-7 write mode register         Γöé
  6983. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6984. Γöé0D8h        Γöéclear byte pointer flip-flop            Γöé
  6985. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6986. Γöé0DAh        Γöéread temporary register/write Master    Γöé
  6987. Γöé            ΓöéClear                                   Γöé
  6988. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6989. Γöé0DCh        Γöéchannel 4-7 clear mask register (write) Γöé
  6990. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  6991. Γöé0DEh        Γöéchannel 4-7 write mask register bits    Γöé
  6992. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  6993. Table 11-2. DMA controller port assignments. 
  6994.  
  6995. Addressing for the DMA controller is accomplished by loading the address and 
  6996. page registers defined in Tables 11-3A and 11-3B. 
  6997.  
  6998. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  6999. ΓöéSource    ΓöéDMA Page  ΓöéAddress   Γöé
  7000. Γöé          ΓöéRegister  ΓöéRegister  Γöé
  7001. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7002. ΓöéAddress   ΓöéA23 < - > ΓöéA15 < - > Γöé
  7003. Γöé          ΓöéA16       ΓöéA0        Γöé
  7004. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7005. Table 11-3A. DMA channel addressing for channels 0-3. 
  7006.  
  7007. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7008. ΓöéSource    ΓöéDMA Page  ΓöéAddress   Γöé
  7009. Γöé          ΓöéRegister  ΓöéRegister  Γöé
  7010. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7011. ΓöéAddress   ΓöéA23 < - > ΓöéA16< - >  Γöé
  7012. Γöé          ΓöéA17       ΓöéA1        Γöé
  7013. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7014. Table 11-3B. DMA channel addressing for channels 5-7. 
  7015.  
  7016. More detailed information on the  8237A DMA controller and support circuitry 
  7017. can be found in the Intel iAPX 86/88 User's Manual Hardware Reference. 
  7018.  
  7019.  
  7020. ΓòÉΓòÉΓòÉ 14.2. Using DMA ΓòÉΓòÉΓòÉ
  7021.  
  7022. To utilize DMA, the device adapter must support DMA transfers. When data has to 
  7023. be written, the appropriate DMA channel registers are loaded with the address 
  7024. of the data to be written, the length of the data, and the proper mode 
  7025. (read/write) by the device driver. The adapter circuitry, usually a UART or 
  7026. some type of controller, issues a write request based on a programmed operation 
  7027. initiated by the device driver. An on-board arbiter issues a DMA request, which 
  7028. causes the system bus HOLD line to be raised. When the bus becomes available, 
  7029. the DMA controller raises the hold acknowledge line, HLDA, to signal the 
  7030. adapter that access to the bus has been granted. The adapter controller then 
  7031. begins a read operation on the system bus until the number of requested bytes 
  7032. have been read from memory, and then outputs the data to the device. The 
  7033. adapter normally generates an interrupt when the transfer is complete, so that 
  7034. the device driver can check the status of the transfer. 
  7035.  
  7036. When data has to be read, the DMA channel registers are loaded with the address 
  7037. of the receive buffer, and the adapter controller programmed to start a read 
  7038. operation. The on-board arbiter requests a DMA operation, and the input data is 
  7039. transferred from the adapter controller directly to the memory buffer without 
  7040. using the CPU. When the required data has been read, or the adapter controller 
  7041. decides that the input should be terminated, it generates an interrupt so that 
  7042. the device driver can examine the received data. The DMA controller will give 
  7043. up the bus by releasing the HOLD line when the DMA channel transfer count goes 
  7044. to zero or the DMA channel is reset. In addition to the adapter initiating the 
  7045. DMA operation, the DMA controller can be programmed to start a DMA transfer 
  7046. using the 8237's request register. 
  7047.  
  7048. To start the DMA, the particular channel is first masked to prevent it from 
  7049. running. Normally, device drivers are free to utilize DMA channels 5, 6, and 7. 
  7050. The  mask register for DMA channels 4-7 is at I/O address 0xD4. The driver 
  7051. masks the DMA channel by setting the proper bits in the DMA mask register (see 
  7052. Table 11-4). 
  7053.  
  7054. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7055. ΓöéBit    ΓöéMeaning                       Γöé
  7056. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7057. Γöé0-1    Γöé00 = select channel 4 mask bitΓöé
  7058. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7059. Γöé       Γöé01 = select channel 5 mask bitΓöé
  7060. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7061. Γöé       Γöé10 = select channel 6 mask bitΓöé
  7062. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7063. Γöé       Γöé11 = select channel 7 mask bitΓöé
  7064. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7065. Γöé2      Γöé0   = clear mask bit          Γöé
  7066. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7067. Γöé       Γöé1   = set mask bit            Γöé
  7068. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7069. Γöé3-7    Γöédon't care                    Γöé
  7070. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7071. Table 11-4. DMA mask register. 
  7072.  
  7073. Next, the mode register for the selected channel is configured by setting the 
  7074. channel bit and the read/write bits (see Table 11-5). 
  7075.  
  7076. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7077. ΓöéBit    ΓöéMeaning                       Γöé
  7078. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7079. Γöé0-1    Γöé00 = channel 4 select         Γöé
  7080. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7081. Γöé       Γöé01 = channel 5 select         Γöé
  7082. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7083. Γöé       Γöé10 = channel 6 select         Γöé
  7084. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7085. Γöé       Γöé11 = channel 7 select         Γöé
  7086. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7087. Γöé2-3    Γöé00 = verify transfer          Γöé
  7088. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7089. Γöé       Γöé01 = write transfer           Γöé
  7090. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7091. Γöé       Γöé10 = read transfer            Γöé
  7092. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7093. Γöé       Γöé11 = illegal                  Γöé
  7094. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7095. Γöé       Γöéxx = don't care if bits 6-7 = Γöé
  7096. Γöé       Γöé11                            Γöé
  7097. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7098. Γöé4      Γöé0  = auto-initialize disable  Γöé
  7099. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7100. Γöé       Γöé1  = auto-initialize enable   Γöé
  7101. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7102. Γöé5      Γöé0  = address increment        Γöé
  7103. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7104. Γöé       Γöé1  = address decrement        Γöé
  7105. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7106. Γöé6-7    Γöé00 = demand mode select       Γöé
  7107. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7108. Γöé       Γöé01 = single mode select       Γöé
  7109. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7110. Γöé       Γöé10 = block mode select        Γöé
  7111. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7112. Γöé       Γöé11 = cascade mode select      Γöé
  7113. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7114. Table 11-5. DMA mode register. 
  7115.  
  7116. The DMA Command Registers are defined in Table 11-6. 
  7117.  
  7118. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7119. ΓöéBit    ΓöéMeaning                       Γöé
  7120. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7121. Γöé0      Γöé0 = memory to memory disable  Γöé
  7122. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7123. Γöé       Γöé1 = memory to memory enable   Γöé
  7124. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7125. Γöé1      Γöé0 = channel 4 address hold    Γöé
  7126. Γöé       Γöédisable                       Γöé
  7127. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7128. Γöé       Γöé1 = channel 4 address hold    Γöé
  7129. Γöé       Γöéenable                        Γöé
  7130. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7131. Γöé       Γöéx = don't care if bit 0 = 0   Γöé
  7132. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7133. Γöé2      Γöé0 = controller enable         Γöé
  7134. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7135. Γöé       Γöé1 = controller disable        Γöé
  7136. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7137. Γöé3      Γöé0 = normal timing             Γöé
  7138. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7139. Γöé       Γöé1 = compressed timing         Γöé
  7140. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7141. Γöé       Γöéx = don't care if bit 0 = 1   Γöé
  7142. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7143. Γöé4      Γöé0 = fixed priority            Γöé
  7144. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7145. Γöé       Γöé1 = rotating priority         Γöé
  7146. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7147. Γöé5      Γöé0 = late write selection      Γöé
  7148. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7149. Γöé       Γöé1 = extended write selection  Γöé
  7150. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7151. Γöé       Γöéx = don't care if bit 3 = 1   Γöé
  7152. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7153. Γöé6      Γöé0 = DREQ sense active high    Γöé
  7154. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7155. Γöé       Γöé1 = DREQ sense active low     Γöé
  7156. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7157. Γöé7      Γöé0 = DACK sense active low     Γöé
  7158. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7159. Γöé       Γöé1 = DACK sense active high    Γöé
  7160. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7161. Table 11-6. DMA command register. 
  7162.  
  7163. The channel is then programmed to transfer words or bytes by the loading of the 
  7164. page select, base address and count registers. To start the DMA operation, the 
  7165. channel is unmasked by writing the proper mask bits to the mask register. 
  7166.  
  7167. The code to initiate a DMA transfer is shown in Example 11-1. A complete 
  7168. listing of the code can be found in Appendix C. The DMACh structure is assumed 
  7169. to be initialized before the call to SetupDMA.  The DMA channel might be active 
  7170. at the time that it is needed, so the device driver should examine the status 
  7171. of the DMA channel to verify that it is available. This is done by examining 
  7172. the status word of the controller and checking the DMA channel busy bits. 
  7173.  
  7174. USHORT  SetupDMA(USHORT channel)
  7175.     {
  7176.     if(DMAChannelBusy(channel))
  7177.        return (DMA_CHANNEL_BUSY);
  7178.     MaskDMA(channel);
  7179.     SetDMAMode(channel,DMA_SINGLE | DMA_READ);
  7180.     InitDMA(channel,(UCHAR) DMACh.PageSelect,
  7181.           (USHORT) DMACh.BaseAddress,
  7182.           (USHORT) DMACh.WordCount);
  7183.     UnmaskDMA(channel);
  7184.     return (DMA_COMPLETE);
  7185.     }
  7186.  
  7187. Example 11-1. DMA setup routine. 
  7188.  
  7189.  
  7190. ΓòÉΓòÉΓòÉ 14.3. DMA and Micro Channel ΓòÉΓòÉΓòÉ
  7191.  
  7192. The Micro Channel bus permits adapters to be masters or slaves. During a memory 
  7193. or I/O transfer under DMA, the master owns the bus and transfers data to and 
  7194. from a slave. Adapters that need the bus compete for it using a centralized 
  7195. arbiter, called the Central Arbitration Control Point, or CACP. The CACP 
  7196. arbitrates DMA channel utilization based on a 4-bit arbitration bus, known as 
  7197. the ARBUS. The ARBUS and CACP work together to ensure that the highest priority 
  7198. master gets control of the bus when it needs it, and that other masters which 
  7199. are competing for the bus get a fair share of the available time. 
  7200.  
  7201. In a Micro Channel system, the DMA controller is a master, which assists in 
  7202. transfers between slaves during a DMA operation. The DMA controller cannot 
  7203. arbitrate the bus. Rather, a slave initiates the arbitration which is monitored 
  7204. by the DMA controller. The DMA controller then transfers the data between the 
  7205. slave and memory. In this capacity, the DMA controller acts as a "middle man", 
  7206. responsible for helping out with the transfer. Thus this arrangement is 
  7207. sometimes referred to as "third-party DMA". 
  7208.  
  7209. Micro Channel slave adapters capable of DMA operation are fitted with a second 
  7210. DMA controller, called a DMA arbiter. To perform DMA transfers, the device 
  7211. driver initializes the adapter with the source, destination, and count of the 
  7212. transfer. The on-board hardware DMA arbiter arbitrates for the use of the bus 
  7213. using its preassigned arbitration level, which is usually stored in the 
  7214. adapter's POS registers. Data transfers can also be performed to and from Micro 
  7215. Channel Bus Masters without using the system DMA controller. 
  7216.  
  7217.  
  7218. ΓòÉΓòÉΓòÉ 15. Chapter 12 - Extended Device Driver Interface ΓòÉΓòÉΓòÉ
  7219.  
  7220. The Extended Device Driver Interface, EDDI, is a new interface developed to 
  7221. take advantage of a new generation of intelligent disk controllers. These new 
  7222. disk controllers are capable of handling transfers to and from discontiguous 
  7223. memory areas. Although EDDI is intended for disk drivers, other types of device 
  7224. drivers can also utilize EDDI. 
  7225.  
  7226. EDDI improves performance by allowing multiple, prioritized requests to be 
  7227. submitted to the device driver at the same time. Instead of the standard 
  7228. synchronous Request Packet, the EDDI driver is sent a Request List of commands, 
  7229. which it can reorder to provide maximum performance. The Read and Write 
  7230. operations use scatter/gather descriptors (SGDs), which allow for data transfer 
  7231. to and from discontiguous data buffers. The driver does not need to block 
  7232. waiting for the request to complete, but returns immediately. The actual 
  7233. transfer is usually completed by the disk adapter hardware. 
  7234.  
  7235. The ability to handle transfers to and from discontiguous memory is more 
  7236. efficient in a system such as OS/2 2.1, which utilizes the 4KB paging 
  7237. functionality of the 80386 and 80486 processors. Data buffers to be written to 
  7238. or from the device driver are normally partitioned into 4K pages, and are not 
  7239. necessarily contiguous. EDDI requires that the device driver contain a second 
  7240. Strategy routine in addition to the normal Strategy routine in an OS/2 device 
  7241. driver. The new extended Strategy routine is also called the Strategy 2 or 
  7242. scatter/gather entry point. 
  7243.  
  7244.  
  7245. ΓòÉΓòÉΓòÉ 15.1. Device Driver Capabilities ΓòÉΓòÉΓòÉ
  7246.  
  7247. The OS/2 kernel issues a Get Driver Capabilities request to the device driver. 
  7248. If the device driver supports the scatter/gather interface, it returns to the 
  7249. kernel a structure containing two 16:16 pointers to special structures that are 
  7250. supported and maintained by the device driver. Contained in one of the 
  7251. structures is a 16:16 pointer to the second Strategy routine to handle 
  7252. synchronous I/O, along with several other parameters. See the Get Driver 
  7253. Capabilities command in Chapter 6. 
  7254.  
  7255. The first structure returned is the Driver Capabilities Structure, or DCS (see 
  7256. Example 12-1). The DCS can be changed only by the device driver. 
  7257.  
  7258. typedef struct _DRIVCAPSTRUCT
  7259. {
  7260.    USHORT     reserved;
  7261.    UCHAR      VerMajor;    // major version, should be 01
  7262.    UCHAR      VerMinor;    // minor version, should be 01
  7263.    ULONG      Capabilities;// capabilities bits
  7264.    PFUNCTION  Strategy2;   // 16:16 pointer to STRAT2
  7265.    PFUNCTION  SetFSDInfo;  // 16:16 pointer to SetFSDInfo
  7266.    PFUNCTION  ChgPriority; // 16:16 pointer to ChgPriority
  7267.    PFUNCTION  SetRestPos;  // 16:16 pointer to RestPos
  7268.    PFUNCTION  GetBoundary; // 16:16 pointer to GetBoundary
  7269. }  DRIVCAPSTRUCT;
  7270.  
  7271. Example 12-1. Driver Capabilities structure. 
  7272.  
  7273. The major and minor version number specifies the version of the EDDI interface 
  7274. that the driver supports. For OS/2 2.1, these should both be 1. 
  7275.  
  7276. The capabilities bits are described in Table 12-1. 
  7277.  
  7278. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7279. ΓöéBit(s)  ΓöéDescription                             Γöé
  7280. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7281. Γöé0-2     Γöéreserved, must be zero                  Γöé
  7282. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7283. Γöé3       Γöéif set, supports disk mirroring         Γöé
  7284. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7285. Γöé4       Γöéif set, supports disk multiplexing      Γöé
  7286. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7287. Γöé5       Γöéif set, driver does not block in STRAT2 Γöé
  7288. Γöé        Γöérequests. LAN Server and LAN Manager    Γöé
  7289. Γöé        Γöérequire this.                           Γöé
  7290. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7291. Γöé6-31    Γöéreserved, should be 0                   Γöé
  7292. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7293. Table 12-1. Capabilities bits. 
  7294.  
  7295. If the driver does not provide a particular service such as ChgPriority, it 
  7296. must return 0:0 as the pointer to the nonexistent function. 
  7297.  
  7298. The second pointer returned from the Get Driver Capabilities function is a 
  7299. pointer to the Volume Characteristics Structure, or VCS. The VCS structure 
  7300. appears in Example 12-2. 
  7301.  
  7302. typedef struct _VOLCHARSTRUCT
  7303. {
  7304.    USHORT VolDescriptor;
  7305.    USHORT AvgSeekTime;
  7306.    USHORT AvgLatency;
  7307.    USHORT TrackMinBlocks;
  7308.    USHORT TrackMaxBlocks;
  7309.    USHORT HeadsPerCylinder;
  7310.    USHORT VolCylinderCount;
  7311.    USHORT VolMedianBlock;
  7312.    USHORT MaxSGList;
  7313. } VOLCHARSTRUCT;
  7314.  
  7315. Example 12-2. Volume Characteristics Structure. 
  7316.  
  7317. The VolDescriptor is defined in Table 12-2. 
  7318.  
  7319. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7320. ΓöéBit(s)  ΓöéDescription                             Γöé
  7321. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7322. Γöé0       Γöéif set, volume resides on removable     Γöé
  7323. Γöé        Γöémedia                                   Γöé
  7324. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7325. Γöé1       Γöéif set, volume is read only             Γöé
  7326. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7327. Γöé2       Γöéif set, average seek time is independentΓöé
  7328. Γöé        Γöéof position, such as a RAM disk         Γöé
  7329. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7330. Γöé3       Γöéif set, outboard cache is supported     Γöé
  7331. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7332. Γöé4       Γöéif set, scatter/gather is supported by  Γöé
  7333. Γöé        Γöéthe adapter                             Γöé
  7334. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7335. Γöé5       Γöéif set, Read Prefetch is supported      Γöé
  7336. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7337. Γöé6-15    Γöéreserved, should be zero                Γöé
  7338. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7339. Table 12-2. Volume Descriptor word. 
  7340.  
  7341. The AvgSeekTime is the disk seek time specified in milliseconds. If unknown, 
  7342. the time should be set to FFFF. If the device is a RAM disk, the time should be 
  7343. 0. 
  7344.  
  7345. The AvgLatency is the average rotational latency in milliseconds. Like the 
  7346. average seek time, the latency should be set to FFFF when it is unknown, and 0 
  7347. when the device is a RAM disk. 
  7348.  
  7349. The TrackMinBlocks specifies the number of blocks available on the smallest 
  7350. capacity track. If this value is not known, it should be set to 1. 
  7351.  
  7352. The TrackMaxBlocks is the number of blocks available on the largest capacity 
  7353. track. If this value is not known, it should be set to 0. 
  7354.  
  7355. The Heads Per Cylinder is the number of heads per disk cylinder. If not known 
  7356. or applicable, this value should be set to 1. 
  7357.  
  7358. The VolCylinderCount is the number of cylinders in the volume. If not known, it 
  7359. should contain the number of sectors in the volume. 
  7360.  
  7361. The MaxSGList is the maximum number of scatter/gather list entries that can be 
  7362. submitted with one command. If the adapter does not directly support 
  7363. scatter/gather, this field should be set to 0. 
  7364.  
  7365.  
  7366. ΓòÉΓòÉΓòÉ 15.2. Request Lists and Request Control ΓòÉΓòÉΓòÉ
  7367.  
  7368. To enable the EDDI driver to be called with multiple requests at one time, a 
  7369. new request format was defined, and is referred to as a Request List. The 
  7370. Request List allows an EDDI device driver's Strategy entry point to be called 
  7371. with a list of requests. The device driver can reorder the requests to provide 
  7372. maximum performance. Only four types of requests have been defined. The four 
  7373. requests are Read, Write, Write Verify, and Read Prefetch. Other commands may 
  7374. be added in the future. The requests have Request Control flags associated with 
  7375. them which can be used to force sequential execution. 
  7376.  
  7377. The Request list consists of a 20-byte Request List Header shown in Example 
  7378. 12-3. 
  7379.  
  7380. typedef struct _REQUESTLISTHEADER
  7381. {
  7382.   USHORT     ReqListCount;
  7383.   USHORT     Reserved;
  7384.   FARPOINTER ListNotifyAddress;
  7385.   USHORT     ListRequestControl;
  7386.   UCHAR      BlkDevUnit;
  7387.   UCHAR      ListStatus;
  7388.   ULONG      Reserved1
  7389.   ULONG      Reserved2;
  7390. } REQUESTLISTHEADER;
  7391.  
  7392. Example 12-3. Request List Header structure. 
  7393.  
  7394. The ReqListCount is the number of requests in the Request List. 
  7395.  
  7396. The LstNotifyAddress is a 16:16 pointer to the notification routine to be 
  7397. called when all requests in the Request List have been completed, or when an 
  7398. unrecoverable error has occurred. The LstNotifyAddress is called with ES:BX 
  7399. pointing to the Request List Header, and the carry flag set (STC) if an error 
  7400. has occurred. The device driver must save all registers before making the call 
  7401. to the NotifyAddress, and restore them when the call is complete. This call 
  7402. should not be made if both bit 4 and bit 5 of the LstRequestControl word are 
  7403. clear (0). 
  7404.  
  7405. The LstRequestControl word is defined in Table 12-3. 
  7406.  
  7407. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7408. ΓöéBit(s)  ΓöéDescription                             Γöé
  7409. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7410. Γöé0       Γöéreserved                                Γöé
  7411. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7412. Γöé1       Γöéif set, only one request is in the list Γöé
  7413. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7414. Γöé2       Γöéif set, execute the requests            Γöé
  7415. Γöé        Γöésequentially (do not reorder)           Γöé
  7416. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7417. Γöé3       Γöéif set, abort on error, set all status, Γöé
  7418. Γöé        Γöéerror code and count (BlocksXferred)    Γöé
  7419. Γöé        Γöéfields                                  Γöé
  7420. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7421. Γöé4       Γöéif set, notify immediately (by calling  Γöé
  7422. Γöé        Γöéthe LstNotifyAddress) if an error is    Γöé
  7423. Γöé        Γöédetected                                Γöé
  7424. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7425. Γöé5       Γöéif set, call the LstNotifyAddress upon  Γöé
  7426. Γöé        Γöécompletion regardless of any errors     Γöé
  7427. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7428. Γöé6-15    Γöéreserved, set to 0                      Γöé
  7429. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7430. Table 12-3. LstRequestControl word bits. 
  7431.  
  7432. The BlockDevUnit is the logical unit number of the volume. 
  7433.  
  7434. The LstStatus contains the current status of the request list as it is being 
  7435. processed. The device driver should update the list as requests are being 
  7436. processed. The LstStatus byte is divided into two 4-byte nibbles. The lower 4 
  7437. bits indicate the completion status of the requests in the list and the upper 4 
  7438. bits indicate the error status of the requests in the list. The bits are 
  7439. defined in Tables 12-4 and 12-5. 
  7440.  
  7441. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7442. ΓöéValue   ΓöéMeaning                  Γöé
  7443. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7444. Γöé00h     Γöéno requests are queued   Γöé
  7445. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7446. Γöé01h     Γöéqueueing is in process   Γöé
  7447. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7448. Γöé02h     Γöéall requests queued      Γöé
  7449. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7450. Γöé04h     Γöéall requests completed   Γöé
  7451. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7452. Γöé08h     Γöéreserved                 Γöé
  7453. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7454. Table 12-4. LstStatus byte, lower nibble. 
  7455.  
  7456. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7457. ΓöéValue   ΓöéMeaning                  Γöé
  7458. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7459. Γöé00h     Γöéno error                 Γöé
  7460. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7461. Γöé01h     Γöérecoverable error        Γöé
  7462. Γöé        Γöéoccurred                 Γöé
  7463. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7464. Γöé02h     Γöéunrecoverable error      Γöé
  7465. Γöé        Γöéoccurred                 Γöé
  7466. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7467. Γöé03h     Γöéunrecoverable error with Γöé
  7468. Γöé        Γöéretry                    Γöé
  7469. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7470. Γöé04h     Γöéreserved                 Γöé
  7471. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7472. Γöé08h     Γöéreserved                 Γöé
  7473. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7474. Table 12-5. LstStatus byte, upper nibble. 
  7475.  
  7476.  
  7477. ΓòÉΓòÉΓòÉ 15.3. Request Format ΓòÉΓòÉΓòÉ
  7478.  
  7479. The valid requests are Read (1Eh), Write(1Fh), Write Verify(20h) and Read 
  7480. Prefetch(21h). Each extended request has a Request Header which is different 
  7481. from the Request List Header. The Request Header is 32 bytes long and is 
  7482. described in Example 12-4. 
  7483.  
  7484. typedef struct _REQUESTHEADER
  7485. {
  7486.    USHORT      ReqLength;
  7487.    UCHAR       CmdPrefix;
  7488.    UCHAR       CmdCode;
  7489.    ULONG       HeaderOffset;
  7490.    UCHAR       RequestCtl;
  7491.    UCHAR       Priority;
  7492.    UCHAR       Status;
  7493.    UCHAR       ErrorCode;
  7494.    FARPOINTER  NotifyAddress;
  7495.    FARPOINTER  HintPointer;
  7496.    ULONG       Reserved1;
  7497.    ULONG       Reserved2;
  7498.    ULONG       Reserved3;
  7499. } REQUESTHEADER;
  7500.  
  7501. Example 12-4. Request Header structure. 
  7502.  
  7503. The ReqLength is the offset to the next request. FFFF terminates the list. 
  7504.  
  7505. The CmdPrefix is always set to 0x1C to differentiate the request from a 
  7506. standard Request Packet. 
  7507.  
  7508. The CmdCode is one of the valid command codes, 1Eh, 1Fh, 20h, or 21h. 
  7509.  
  7510. The HeaderOffset is the offset from the beginning of the Request List Header to 
  7511. the header of this request, and is used as a quick access to the Request List 
  7512. Header. 
  7513.  
  7514. The RequestCtl field is defined in Table 12-6. 
  7515.  
  7516. The notify routines should not be called if bits 4 and 5 are both clear (0). 
  7517.  
  7518. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7519. ΓöéBit(s)  ΓöéDescription                             Γöé
  7520. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7521. Γöé0-3     Γöéreserved, must be 0                     Γöé
  7522. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7523. Γöé4       Γöéif set, notify on error only by calling Γöé
  7524. Γöé        Γöéthe NotifyAddress immediately           Γöé
  7525. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7526. Γöé5       Γöéif set, notify on completion by calling Γöé
  7527. Γöé        Γöéthe NotifyAddress                       Γöé
  7528. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7529. Γöé6-7     Γöéreserved, must be 0                     Γöé
  7530. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7531. Table 12-6. RequestCtl byte. 
  7532.  
  7533. The Request Priority defines the priority of the request, and is defined in 
  7534. Table 12-7. 
  7535.  
  7536. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7537. ΓöéValue   ΓöéMeaning                                 Γöé
  7538. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7539. Γöé00h     Γöéprefetch requests                       Γöé
  7540. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7541. Γöé01h     Γöélow-priority request                    Γöé
  7542. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7543. Γöé02h     Γöéread ahead, low-priority pager I/O      Γöé
  7544. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7545. Γöé04h     Γöébackground synchronous user I/O         Γöé
  7546. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7547. Γöé08h     Γöéforeground synchronous user I/O         Γöé
  7548. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7549. Γöé10h     Γöéhigh-priority pager I/O                 Γöé
  7550. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7551. Γöé80h     Γöéurgent request, should be handled       Γöé
  7552. Γöé        Γöéimmediately                             Γöé
  7553. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7554. Table 12-7. Request priority. 
  7555.  
  7556. The Status field contains the status of the current request and is defined in 
  7557. Tables 12-8 and 12-9. 
  7558.  
  7559. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7560. ΓöéValue   ΓöéMeaning                                 Γöé
  7561. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7562. Γöé00h     Γöénot queued yet                          Γöé
  7563. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7564. Γöé01h     Γöéqueued and waiting                      Γöé
  7565. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7566. Γöé02h     Γöéin process                              Γöé
  7567. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7568. Γöé04h     Γöédone                                    Γöé
  7569. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7570. Γöé08h     Γöéreserved                                Γöé
  7571. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7572. Table 12-8. Request Status, lower nibble (completion status) 
  7573.  
  7574. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7575. ΓöéValue   ΓöéMeaning                                 Γöé
  7576. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7577. Γöé00h     Γöéno error                                Γöé
  7578. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7579. Γöé01h     Γöérecoverable error occurred              Γöé
  7580. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7581. Γöé02h     Γöéunrecoverable error occurred            Γöé
  7582. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7583. Γöé03h     Γöéunrecoverable error occurred            Γöé
  7584. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7585. Γöé04h     Γöéthe request was aborted                 Γöé
  7586. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7587. Γöé08h     Γöéreserved                                Γöé
  7588. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7589. Table 12-9. Request Status, upper nibble (error status) 
  7590.  
  7591. ErrorCode contains one of the errors described in Tables 12-10 and 12-11 if the 
  7592. corresponding error bits are set in the Status field. 
  7593.  
  7594. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7595. ΓöéValue   ΓöéMeaning                                 Γöé
  7596. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7597. Γöé00h     Γöéwrite protect violation                 Γöé
  7598. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7599. Γöé01h     Γöéunknown unit                            Γöé
  7600. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7601. Γöé02h     Γöédevice not ready                        Γöé
  7602. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7603. Γöé03h     Γöéunknown command                         Γöé
  7604. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7605. Γöé04h     ΓöéCRC error                               Γöé
  7606. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7607. Γöé06h     Γöéseek error                              Γöé
  7608. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7609. Γöé07h     Γöéunknown media                           Γöé
  7610. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7611. Γöé08h     Γöéblock not found                         Γöé
  7612. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7613. Γöé0Ah     Γöéwrite fault                             Γöé
  7614. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7615. Γöé0Bh     Γöéread fault                              Γöé
  7616. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7617. Γöé0Ch     Γöégeneral failure                         Γöé
  7618. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7619. Γöé10h     Γöéuncertain media                         Γöé
  7620. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7621. Γöé13h     Γöéinvalid parameter                       Γöé
  7622. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7623. Table 12-10. Request unrecoverable error codes. 
  7624.  
  7625. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7626. ΓöéValue   ΓöéMeaning                                 Γöé
  7627. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7628. Γöé1Ah     Γöéverify error on write, recovered after 1Γöé
  7629. Γöé        Γöétry                                     Γöé
  7630. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7631. Γöé2Ah     Γöéwrite error, write to duplexed or       Γöé
  7632. Γöé        Γöémirrored driver succeeded               Γöé
  7633. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7634. Γöé3Ah     Γöéwrite error on mirrored or duplexed     Γöé
  7635. Γöé        Γöédrive, write to primary drive succeeded Γöé
  7636. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7637. Γöé1Bh     Γöéread error, corrected using ECC         Γöé
  7638. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7639. Γöé2Bh     Γöéread succeeded after retry              Γöé
  7640. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7641. Γöé3Bh     Γöéread error, recovered from mirrored or  Γöé
  7642. Γöé        Γöéduplexed driver                         Γöé
  7643. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7644. Table 12-11. Request recoverable error codes. 
  7645.  
  7646. The NotifyAddress contains a 16:16 pointer to the driver to call when the 
  7647. request has been completed or aborted. If bits 4 and 5 of the RequestCtl field 
  7648. are both clear (0), the Notify Address is not valid and should not be called. 
  7649. The device driver must save all registers before calling the notify routine, 
  7650. and restore them when the call returns. 
  7651.  
  7652. The HintPointer is a 16:16 pointer to a Request Packet in the Request List. The 
  7653. device driver can use this pointer to determine whether the current request can 
  7654. be grouped with another pending request, providing that the other request has 
  7655. not yet been completed. 
  7656.  
  7657.  
  7658. ΓòÉΓòÉΓòÉ 15.4. Read/Write/Write Verify Request ΓòÉΓòÉΓòÉ
  7659.  
  7660. The format of these requests is described in Examples 12-5 and 12-6. 
  7661.  
  7662. typedef struct _SGD {
  7663.    PHYSADDR BufferPtr;
  7664.    ULONG    BufferSize;
  7665.    } SGD;
  7666.  
  7667. Example 12-5. Scatter Gather Descriptor structure. 
  7668.  
  7669. typedef struct _READWRITE {
  7670.    REQUESTHEADER ReadWriteHeader;
  7671.    ULONG         StartBlock;
  7672.    ULONG         BlockCount;
  7673.    ULONG         BlocksXferred;
  7674.    USHORT        Flags;
  7675.    USHORT        SGDescrCount
  7676.    ULONG         Reserved;
  7677.    SGD           Sgd[SGDescrCount];
  7678.    } READWRITE;
  7679.  
  7680. Example 12-6. Read/Write Request structure. 
  7681.  
  7682. The StartBlock is the string disk block for the data transfer. A disk block is 
  7683. defined as a 512-byte logical disk sector. 
  7684.  
  7685. The BlockCount is the number of 512-byte blocks to be transferred. 
  7686.  
  7687. The BlocksXferred is the number of blocks that have been transferred at the 
  7688. time that the notification routine was called. 
  7689.  
  7690. The Flags field currently uses only the two least significant bits. All other 
  7691. bits are set to 0. If bit 0 is set, it specifies write-through, defeating any 
  7692. lazy write. If bit 1 is set, the data should be cached on the outboard 
  7693. controller cache. 
  7694.  
  7695. The SGDescrCount field contains the number of scatter/gather descriptors in the 
  7696. Sgd field. 
  7697.  
  7698. The Sgd field contains an array of scatter/gather descriptors. 
  7699.  
  7700. Read Prefetch Request 
  7701.  
  7702. The format of the Read Prefetch request is described in Example 12-7. 
  7703.  
  7704. typedef struct _READPREFETCH {
  7705.   REQUESTHEADER ReadPreHdr;
  7706.   ULONG         StartBlock;
  7707.   ULONG         BlockCount;
  7708.   ULONG         BlocksXferred;
  7709.   USHORT        Flags;
  7710.   USHORT        Reserved;
  7711.   } READPREFETCH;
  7712.  
  7713. Example 12-7. Read Prefetch Request structure. 
  7714.  
  7715. The StartBlock is the string disk block for the data transfer. A disk block is 
  7716. defined as a 512-byte logical disk sector. 
  7717.  
  7718. The BlockCount is the number of 512-byte blocks to be transferred. 
  7719.  
  7720. The BlocksXferred is the number of blocks that have been transferred at the 
  7721. time that the notification routine was called. 
  7722.  
  7723. The Flags field currently uses only the least significant bit. All other bits 
  7724. are set to 0. If bit 0 is set, it specifies that the driver should retain data 
  7725. in the controller prefetch buffers only until it has been read once. This 
  7726. prevents redundant caching in the controller. 
  7727.  
  7728.  
  7729. ΓòÉΓòÉΓòÉ 15.5. Request Control Functions ΓòÉΓòÉΓòÉ
  7730.  
  7731. The EDDI device driver may optionally provide other services to allow OS/2 to 
  7732. manage extended requests. The current implementation is OS/2 2.1 defines four 
  7733. functions that the device driver may support. The device driver exports these 
  7734. functions by placing a 16:16 pointer to the functions in the DCS returned from 
  7735. the Get Driver Capabilities call. If the pointer in the DCS structure is 0:0, 
  7736. the function is not supported by the device driver. Since the request control 
  7737. functions may be called at interrupt time, they must not block. Request control 
  7738. functions are called by the OS/2 File System Driver, or FSD. Request control 
  7739. functions must save and restore the segment registers, as the interrupt context 
  7740. may not be the same as the device driver. The four request control functions 
  7741. are summarized in Table 12-12. 
  7742.  
  7743. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7744. ΓöéRequest ControlΓöéDescription                   Γöé
  7745. ΓöéFunction       Γöé                              Γöé
  7746. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7747. ΓöéSetFSDInfo     ΓöéSend the device driver 16ds   Γöé
  7748. Γöé               Γöéwhen there are no requests    Γöé
  7749. Γöé               Γöépending                       Γöé
  7750. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7751. ΓöéGetBoundary    ΓöéThe device driver returns a   Γöé
  7752. Γöé               Γöéblock number greater than the Γöé
  7753. Γöé               Γöéblock number passed to the    Γöé
  7754. Γöé               Γöédevice driver                 Γöé
  7755. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7756. Table 12-2. Request control functions. 
  7757.  
  7758.  
  7759. ΓòÉΓòÉΓòÉ 15.6. SetFSDInfo ΓòÉΓòÉΓòÉ
  7760.  
  7761. This device driver function is called by the FSD with 16:16 pointers to the 
  7762. FSD's End of Interrupt and Access Validation routines. The driver is called 
  7763. with ES:BX pointing to a FSDInfo structure, described in Example 12-8. 
  7764.  
  7765. typedef struct _FSDInfo
  7766. {
  7767.   ULONG       Reserved1;   // reserved, must be 0
  7768.   FARPOINTER  EndOfInit;   // pointer to FSD's EOI
  7769.   ULONG       Reserved2;   // reserved, must be 0
  7770.   FARPOINTER  AccValidate; // pointer to FSD's AccValidate
  7771. } FSDInfo;
  7772.  
  7773. Example 12-8. SetFSDInfo structure. 
  7774.  
  7775. The device driver should allow this function to be called only once. If the 
  7776. call is the first call, the device driver should return with the carry flag set 
  7777. (STC). Subsequent calls should be ignored, and the device driver should return 
  7778. with the carry flag clear (CLC). 
  7779.  
  7780. If the EndOfInit pointer is 0, the FSD does not provide an End Of Interrupt 
  7781. routine. All registers are preserved during the call to EndOfInit. 
  7782.  
  7783. The device driver calls the FSD's AccValidate with the AL register set to 0 for 
  7784. a nondestructive operation, such as READ or VERIFY, and the AL register set to 
  7785. 1 for a destructive operation, such as WRITE or FORMAT TRACK. The FSD's 
  7786. AccValidate function returns with the carry flag clear if access is allowed, or 
  7787. the carry flag set if access is denied. The device driver should return a 
  7788. write-protect violation to the caller if access is denied. 
  7789.  
  7790.  
  7791. ΓòÉΓòÉΓòÉ 15.7. ChgPriority ΓòÉΓòÉΓòÉ
  7792.  
  7793. The device driver's ChgPriority routine is called with ES:BX pointing to the 
  7794. request, and the AL register containing the new priority. The pointer in ES:BX 
  7795. is always a valid pointer. The device driver should return with the carry flag 
  7796. set if the Request Packet was not found or was no longer in the device driver's 
  7797. internal queue. If the priority change was successful, the device driver should 
  7798. return with the carry flag clear. 
  7799.  
  7800.  
  7801. ΓòÉΓòÉΓòÉ 15.8. SetRestPos ΓòÉΓòÉΓòÉ
  7802.  
  7803. The device driver's SetRestPos routine is called with AX:BX containing the 
  7804. block to be used for the resting position. A value of FFFF:FFFF means rest at 
  7805. the block where the heads end up. The device driver should return with the 
  7806. carry flag set if the block number is out of the range for the volume, 
  7807. otherwise it should return with the carry flag clear. 
  7808.  
  7809.  
  7810. ΓòÉΓòÉΓòÉ 15.9. GetBoundary ΓòÉΓòÉΓòÉ
  7811.  
  7812. The device driver's GetBoundary routine is called with AX:BX containing the 
  7813. block number to be used as a reference to calculate the next block number. 
  7814. Using this information, the FSD can store files more optimally. If the next 
  7815. block cannot easily be calculated or is not known, the device driver can return 
  7816. the reference block'1. If the block number is out of the range, the device 
  7817. driver must return with the carry flag set, otherwise it should return with the 
  7818. carry flag clear. 
  7819.  
  7820.  
  7821. ΓòÉΓòÉΓòÉ 16. Chapter 13 - Debugging OS/2 Device Drivers ΓòÉΓòÉΓòÉ
  7822.  
  7823. The Kernel Debugger, or KDB, is generally used to debug device drivers as well 
  7824. as the system kernel code. The KDB kernel, OS2KRNLD, is actually a full 
  7825. function replacement OS/2 kernel, which contains the debugger and the debugger 
  7826. support functions. KDB communicates with a standard ASCII terminal through one 
  7827. of the COM ports. If the system contains only one COM port, COM1, KDB uses 
  7828. COM1. If the system has two COM ports, COM1 and COM2, KDB uses the second COM 
  7829. port, COM2. KDB defaults to 9600 baud, no parity, 8 data bits and one stop bit. 
  7830.  
  7831. The COM port is attached to an ASCII terminal via an RS-232 interface with data 
  7832. leads only in a null modem configuration (pin 2 and 3 switched). Before 
  7833. installing the debugger, the terminal link should first be verified by sending 
  7834. some text out to the terminal using the DIR > COMn command. If the baud rate of 
  7835. the COM port has not been previously initialized to 9600 baud, use the command 
  7836. MODE COM1(or COM2):96,n,8,1 <enter>. The text of the directory list should be 
  7837. displayed on the debugging terminal. You do not have to issue the MODE command 
  7838. when KDB is installed, as KDB will initialize the port on start-up to 
  7839. 9600,n,8,1. 
  7840.  
  7841. To install the kernel debugger, the system is rebooted using a DOS or OS/2 
  7842. installation diskette, and the attributes of the OS2KRNL file changed to make 
  7843. it visible. This can be done by using a utility such a chmod or one of the many 
  7844. available OS/2 utilities. The OS2KRNL file is renamed to OS2KRNL.OLD, and the 
  7845. debugging kernel, OS2KRNLD, copied to OS2KRNL. The OS2KRNL.OLD file is kept to 
  7846. allow reinstallation of the non-debug kernel when reinstalling OS/2. When the 
  7847. system is rebooted, the debugger should sign on at the debug terminal with the 
  7848. message "System Debugger 03/16/89 [80386]". 
  7849.  
  7850. The IBM OS/2 Toolkit contains an install utility for the kernel debugger which 
  7851. will perform the above steps automatically. 
  7852.  
  7853. KDB can be entered normally in several ways. Three special keys entered on the 
  7854. debugging terminal cause KDB to be entered prior to the complete boot of OS/2. 
  7855. The "r" key causes the debugger to be entered at the beginning of DOS 
  7856. initialization in real mode. The "p" key causes the debugger to be entered 
  7857. after OS/2 goes into the protect mode for the first time. The "<space-bar>" 
  7858. causes the debugger to be entered after most of DOS has been initialized. 
  7859. Symbols for DOS have been loaded at this time. 
  7860.  
  7861. After initialization is complete, the debugger can be entered at any time by 
  7862. typing <cntl-c> at the debug terminal. The debugger is entered when and where 
  7863. the next timer tick is taken after the key was pressed. 
  7864.  
  7865. When KDB is entered, it will execute the current default command, usually the 
  7866. "r" (register contents), and then display the debugger prompt, "##". The system 
  7867. will not run until the debugger is exited, usually by entering the GO command 
  7868. (g). KDB will also be entered when the system detects an "INT 3" instruction. A 
  7869. common debug technique is to insert INT 3 instructions in the driver source 
  7870. code while debugging, which will cause KDB to be entered. Once KDB has been 
  7871. entered, the KDB commands can be used to display the contents of variables, 
  7872. system information, or memory contents, and to run from or single- step from 
  7873. the breakpoint. 
  7874.  
  7875. After any symbols files are loaded, an initialization file, called KDB.INI, is 
  7876. read and executed.  Any debugger command or list of debugger commands can be in 
  7877. the KDB.INI file.  A "g" command should usually be at the end of the command 
  7878. list, unless the debugger is to remain stopped. 
  7879.  
  7880. At any time during the display of data on the debug terminal, the display can 
  7881. be stopped with a <cntl-s>, and restarted with a <cntl-q>. The GO command (g) 
  7882. always resumes execution at the instruction displayed in the CS:IP register. 
  7883.  
  7884. KDB displays information in machine code, and requires a thorough understanding 
  7885. of machine language and processor architecture to fully utilize its 
  7886. capabilities. 
  7887.  
  7888. A complete list of the valid KDB commands can be displayed by entering the "?" 
  7889. command at the KDB prompt for internal KDB commands, and ".?" for external 
  7890. commands. 
  7891.  
  7892. KDB obtains its symbolic debug information from a symbol file with the 
  7893. extension of .SYM. These files can be created with the MAPSYM utility, which 
  7894. creates a symbol file from the .MAP file created during the link operation. 
  7895. When loading a device driver during system boot, the debug kernel looks for a 
  7896. .SYM file with the same file name as the driver .SYS file, and in the same 
  7897. directory as the driver .SYS file. If the device driver "TEST.SYS" were being 
  7898. loaded, the debug kernel would look in the same directory as "TEST.SYS" for the 
  7899. file "TEST.SYM", and load the symbols. The symbol file is not necessary, and 
  7900. the driver will load without it, but variables will not be able to be accessed 
  7901. by name. Several drivers may be loaded, each with their own .SYM file. 
  7902.  
  7903. If the KDB was supplied with the operating system SYM files, these will also be 
  7904. loaded if they are placed on the root directory with the OS2KRNL file. The 
  7905. system symbol files will allow access to system variables and structures by 
  7906. name. Symbols are displayed using a KDB command such as display word (dw), 
  7907. display byte (db), or display double word (dd). They are referenced by the 
  7908. symbolic name preceded by the underscore ("_"), if the driver is written in C. 
  7909. For example, to display the 16-bit variable "bytecount", the command "dw 
  7910. _bytecount" would be entered. 
  7911.  
  7912.  
  7913. ΓòÉΓòÉΓòÉ 16.1. KDB Keywords ΓòÉΓòÉΓòÉ
  7914.  
  7915. KDB supports the keywords in Table 13-1 which return their value when used in 
  7916. expressions. 
  7917.  
  7918. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7919. Γöé[E]AX, [E]BX, [E]CX,Γöéregister values               Γöé
  7920. Γöé[E]DX, [E]SI, [E]DI,Γöé                              Γöé
  7921. Γöé[E]BP, DS, ES, SS,  Γöé                              Γöé
  7922. ΓöéCS, [E]SP, [E]IP    Γöé                              Γöé
  7923. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7924. ΓöéFLG                 Γöévalue of flags                Γöé
  7925. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7926. ΓöéGDTB                Γöévalue of GDT base physical    Γöé
  7927. Γöé                    Γöéaddress                       Γöé
  7928. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7929. ΓöéGDTL                Γöévalue of GDT limit            Γöé
  7930. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7931. ΓöéIDTB                Γöévalue of IDT base physical    Γöé
  7932. Γöé                    Γöéaddress                       Γöé
  7933. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7934. ΓöéIDTL                Γöévalue of IDT limit            Γöé
  7935. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7936. ΓöéTR, LDTR, MSW       Γöévalue of TR, LDTR, MSW        Γöé
  7937. Γöé                    Γöéregisters                     Γöé
  7938. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7939. ΓöéBR0, BR1..BR9       Γöévalue of breakpoint address   Γöé
  7940. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7941. ΓöéFS, GS              Γöésegment registers             Γöé
  7942. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7943. ΓöéEFLG                Γöévalue of extended flags       Γöé
  7944. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7945. ΓöéCR0, CR2, CR3       Γöévalue of control registers    Γöé
  7946. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7947. ΓöéDR0, DR1, DR2, DR3, Γöévalue of debug registers      Γöé
  7948. ΓöéDR4, DR5, DR6, DR7  Γöé                              Γöé
  7949. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7950. ΓöéTR6, TR7            Γöévalue of test registers       Γöé
  7951. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7952. Table 13-1. KDB keywords. 
  7953.  
  7954.  
  7955. ΓòÉΓòÉΓòÉ 16.2. KDB Operators ΓòÉΓòÉΓòÉ
  7956.  
  7957. KDB supports the binary operators described in Table 13-2. 
  7958.  
  7959. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7960. ΓöéOperator            ΓöéMeaning                       Γöé
  7961. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7962. Γöé()                  ΓöéParentheses                   Γöé
  7963. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7964. Γöé+                   ΓöéAddition                      Γöé
  7965. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7966. Γöé-                   ΓöéSubtraction                   Γöé
  7967. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7968. Γöé*                   ΓöéMultiplication                Γöé
  7969. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7970. Γöé/                   ΓöéDivision                      Γöé
  7971. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7972. ΓöéMOD                 ΓöéModulo                        Γöé
  7973. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7974. Γöé>                   ΓöéGreater than                  Γöé
  7975. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7976. Γöé<                   ΓöéLess than                     Γöé
  7977. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7978. Γöé>=                  ΓöéGreater than or equal to      Γöé
  7979. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7980. Γöé<=                  ΓöéLess than or equal to         Γöé
  7981. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7982. Γöé!=                  ΓöéNot equal to                  Γöé
  7983. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7984. Γöé==                  ΓöéEqual to                      Γöé
  7985. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7986. ΓöéAND                 ΓöéBoolean AND                   Γöé
  7987. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7988. ΓöéXOR                 ΓöéBoolean exclusive OR          Γöé
  7989. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7990. ΓöéOR                  ΓöéBoolean inclusive OR          Γöé
  7991. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7992. Γöé&&                  ΓöéLogical AND                   Γöé
  7993. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7994. Γöé||                  ΓöéLogical OR                    Γöé
  7995. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7996. Γöé:                   ΓöéAddress separator             Γöé
  7997. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7998. Table 13-2. KDB binary operators. 
  7999.  
  8000. KDB supports the unary operators described in Table 13-3. 
  8001.  
  8002. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  8003. ΓöéOperator            ΓöéMeaning                       Γöé
  8004. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8005. Γöé|                   ΓöéTask number/address operator  Γöé
  8006. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8007. Γöé&addr               ΓöéInterpret address using       Γöé
  8008. Γöé                    Γöésegment value                 Γöé
  8009. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8010. Γöé#addr               ΓöéInterpret address using       Γöé
  8011. Γöé                    Γöéselector                      Γöé
  8012. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8013. Γöé%addr               ΓöéInterpret address as 32-bit   Γöé
  8014. Γöé                    Γöélinear                        Γöé
  8015. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8016. Γöé%%addr              Γöé32-bit physical address       Γöé
  8017. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8018. Γöé-                   ΓöéTwo's complement              Γöé
  8019. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8020. Γöé!                   ΓöéLogical NOT                   Γöé
  8021. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8022. ΓöéNOT                 ΓöéOne's complement              Γöé
  8023. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8024. ΓöéSEG                 ΓöéSegment address               Γöé
  8025. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8026. ΓöéOFF                 ΓöéAddress offset                Γöé
  8027. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8028. ΓöéBY                  ΓöéLow byte of address           Γöé
  8029. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8030. ΓöéWO                  ΓöéLow word of address           Γöé
  8031. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8032. ΓöéDW                  ΓöéDoubleword from address       Γöé
  8033. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8034. ΓöéPOI                 ΓöéPointer from address          Γöé
  8035. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8036. ΓöéPORT                ΓöéOne byte from a port          Γöé
  8037. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8038. ΓöéWPORT               ΓöéWord from a port              Γöé
  8039. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  8040. Table 13-3. KDB unary operators. 
  8041.  
  8042. The operator precedence is as follows: 
  8043.  
  8044.   ()
  8045.  
  8046.   | :
  8047.  
  8048.   & # % %% - ! NOT SEG OFF BY WO DW POI PORT WPORT (unary operators)
  8049.  
  8050.   * / MOD
  8051.  
  8052.   ' -
  8053.  
  8054.   > < >= <=
  8055.  
  8056.   ==
  8057.  
  8058.   !=
  8059.  
  8060.   AND
  8061.  
  8062.   XOR
  8063.  
  8064.   OR
  8065.  
  8066.   &&
  8067.  
  8068.   ||
  8069.  
  8070.  
  8071. ΓòÉΓòÉΓòÉ 16.3. KDB Command Reference ΓòÉΓòÉΓòÉ
  8072.  
  8073. In the following command descriptions, the following rules apply: 
  8074.  
  8075. o brackets ([]) mean the parameter is optional
  8076.  
  8077. o the "or" sign (|) means either of the parameters is valid
  8078.  
  8079. o parameters surrounded by carets (<>) are mandatory
  8080.  
  8081. o parameters may be separated by a comma (,) or blank
  8082.  
  8083. o multiple commands on the same line are separated by a semicolon (;)
  8084.  
  8085. o all numeric entry is defaulted to hexidecimal
  8086.  
  8087. o (...) means repeats
  8088.  
  8089. Table 13-4 lists the KDB parameter types and their meaning. 
  8090.  
  8091. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  8092. ΓöéParameter             ΓöéDefinition                    Γöé
  8093. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8094. Γöé<expr>                Γöéevaluates to an 8, 16, or     Γöé
  8095. Γöé                      Γöé32-bit value                  Γöé
  8096. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8097. Γöé<number>              Γöéa number in decimal, octal,   Γöé
  8098. Γöé                      Γöéhex or binary                 Γöé
  8099. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8100. Γöé<string>              Γöéany number of characters      Γöé
  8101. Γöé                      Γöébetween " " or '  '           Γöé
  8102. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8103. Γöé<range>               Γöé<addr> [<word>] | [<addr>] [L Γöé
  8104. Γöé                      Γöé<word>]                       Γöé
  8105. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8106. Γöé<addr>                Γöé[& | #][<word>                Γöé
  8107. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8108. Γöé<list>                Γöé<byte>, <byte>, ... | "string"Γöé
  8109. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8110. Γöé<bp commands>         Γöéa list of debugger commands,  Γöé
  8111. Γöé                      Γöéseparated by ;                Γöé
  8112. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8113. Γöé<string>              Γöé"char" | 'char'               Γöé
  8114. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8115. Γöé<dword>,<word>,<byte> Γöéexpressions that evaluate to  Γöé
  8116. Γöé                      Γöéthe size in <>                Γöé
  8117. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  8118. Table 13-4. KDB parameter definitions. 
  8119.  
  8120. Expressions 
  8121.  
  8122. An expression (expr) is a combination of parameters and operators that evaluate 
  8123. to an 8, 16 or 32-bit value. 
  8124.  
  8125. Numbers 
  8126.  
  8127. A number (number) parameter can be any number with hex as the default. Numbers 
  8128. may be evaluated in a different radix by appending a special character to the 
  8129. number. These special characters are y for binary, o for octal, T for decimal 
  8130. and h for hex (default). 
  8131.  
  8132. Strings 
  8133.  
  8134. A string (string) parameter is any number of characters within double (" ") or 
  8135. single (' ') quotes. Double quotes within the string should be preceded by 
  8136. another double quote to be correctly evaluated. 
  8137.  
  8138. Ranges 
  8139.  
  8140. A range (range) parameter specifies an address followed by either a length or 
  8141. an end address. An additional parameter may also be used to specify the number 
  8142. of times to perform the operation. 
  8143.  
  8144. Addresses 
  8145.  
  8146. An address (addr) parameter indicates a memory address in one of four modes. 
  8147. The four modes are: real mode (&segment:offset), protect mode 
  8148. (#selector:offset), linear address (%dword), and physical address (%%dword). 
  8149. The operators preceding the address override the current address type. 
  8150.  
  8151. Lists 
  8152.  
  8153. A list is a list of two-character bytes separated by a space, or a string 
  8154. surrounded by double quotes. 
  8155.  
  8156. Commands 
  8157.  
  8158. Commands (bp cmds) are one or more debugger commands, separated by semicolons 
  8159. (;), to be executed when a condition is met, such as a breakpoint encountered. 
  8160.  
  8161. Strings 
  8162.  
  8163. A string is a list of characters bounded by single or double quotes. 
  8164.  
  8165. Dwords, words, bytes 
  8166.  
  8167. Expressions that evaluate to the specified size. 
  8168.  
  8169. Breakpoints 
  8170.  
  8171. There are two kinds of breakpoints in the kernel debugger. Temporary 
  8172. breakpoints are set as an option to the go (g) command, and disappear when the 
  8173. go command is executed again. Sticky breakpoints are set with a KDB set 
  8174. breakpoint command, and remain until cleared with a KDB command or the system 
  8175. is rebooted. Sticky breakpoints are numbered 0-9, inclusive. 
  8176.  
  8177. On a 386, the debug registers can be used in a sticky breakpoint (see the br 
  8178. command). 
  8179.  
  8180. When a breakpoint is encountered, the current default command is executed. This 
  8181. command is set to r, or the dump registers command. The default command may be 
  8182. changed by the zs command, and listed with the z command. 
  8183.  
  8184.  
  8185. ΓòÉΓòÉΓòÉ 16.4. Internal Commands ΓòÉΓòÉΓòÉ
  8186.  
  8187. Set Breakpoint 
  8188.  
  8189. bp[bp number] [<addr>] [<passcnt>] [<bp cmds>]
  8190.  
  8191. Set a new sticky breakpoint, or change an existing old breakpoint. The  number 
  8192. parameter is an optional breakpoint number, which selects a new breakpoint by 
  8193. the number or changes an existing breakpoint with the same number. The passcnt 
  8194. parameter specifies how many times the breakpoint will be passed by before it 
  8195. is executed. If passcnt is omitted or 0, the breakpoint will be executed the 
  8196. first time that it is encountered. 
  8197.  
  8198. The commands parameter is a list of KDB commands to be executed when the 
  8199. breakpoint is encountered. 
  8200.  
  8201. Set Register Breakpoint 
  8202.  
  8203. br[<bp number>] e|w|r|1|2|4 [<addr>] [<passcnt>] ["<bp cmds>"]
  8204.  
  8205. Sets a 386 debug register.  Debug registers can be used to break on data reads 
  8206. and writes, and on instruction execution. Up to four debug registers can be set 
  8207. and enabled at one time. Disabled br breakpoints don't occupy a debug register. 
  8208.  
  8209. The e parameter specifies a one-byte length (default) 
  8210.  
  8211. The w parameter specifies break on write operation. 
  8212.  
  8213. The r parameter specifies break on read operation 
  8214.  
  8215. The 1 parameter specifies a one-byte length. 
  8216.  
  8217. The 2 parameter specifies a word length. Word-length breakpoints must be on a 
  8218. word boundary. 
  8219.  
  8220. The 4 parameter specifies a doubleword length. 
  8221.  
  8222. Set Time Stamping Breakpoint 
  8223.  
  8224. bt[<bp number>] [<addr>]
  8225.  
  8226. Set a time stamping breakpoint. 
  8227.  
  8228. Show Timestamp Entries 
  8229.  
  8230. bs
  8231.  
  8232. Show the time stamp entries. 
  8233.  
  8234. List Breakpoint(s) 
  8235.  
  8236. bl
  8237.  
  8238. Lists the currently set breakpoints with current and original passcnt, and 
  8239. breakpoint commands (bp cmds) associated with them. 
  8240.  
  8241. An "e" after the breakpoint number means that the breakpoint is enabled; a "d" 
  8242. means that it is disabled. After either one, there may be an "i", which 
  8243. indicates that the address was invalid the last time the debugger tried to set 
  8244. or clear the breakpoint. 
  8245.  
  8246. Clear Breakpoint(s) 
  8247.  
  8248. bc[bp number],[bp number],...
  8249.  
  8250. Removes (clears) the list of breakpoint numbers from the debugger's breakpoint 
  8251. table. 
  8252.  
  8253. Enable Breakpoint 
  8254.  
  8255. be [bp number],[bp number],...
  8256.  
  8257. Enables the list of breakpoint numbers. 
  8258.  
  8259. Clear Breakpoint(s) 
  8260.  
  8261. bd[bp number],[bp number],...
  8262.  
  8263. Disables the list of breakpoint numbers. The breakpoint is not removed, but 
  8264. disabled so that it can be re-enabled later. 
  8265.  
  8266. Compare Bytes 
  8267.  
  8268. c <range> <addr>
  8269.  
  8270. Compares the bytes in the memory location specified by <range> with the 
  8271. corresponding bytes in the memory locations beginning at <addr>.  If all 
  8272. corresponding bytes match, the kernel debugger displays its prompt and waits 
  8273. for the next command. If one or more corresponding bytes do not match, each 
  8274. pair of mismatched bytes is displayed. 
  8275.  
  8276. Dump Memory 
  8277.  
  8278. d [<range>]
  8279.  
  8280. Dump memory in the last format selected (byte, word, doubleword). 
  8281.  
  8282. Dump Bytes 
  8283.  
  8284. db [<range>]
  8285.  
  8286. Dump memory in byte format and ASCII representation. 
  8287.  
  8288. Dump Words 
  8289.  
  8290. dw [<range>]
  8291.  
  8292. Dump memory in word format. 
  8293.  
  8294. Dump Doublewords 
  8295.  
  8296. dd [<range>]
  8297.  
  8298. Dump memory in doubleword format. 
  8299.  
  8300. Dump GDT Entries 
  8301.  
  8302. dg [a] [<range>]
  8303.  
  8304. Dump global descriptor table entries. 
  8305.  
  8306. The a parameter specifies a dump of all entries, not just valid entries. 
  8307.  
  8308. Without the a parameter, the dg command will display only the valid GDT 
  8309. entries. If the range is an LDT selector, KDB will display "LDT" and the 
  8310. associated entry. 
  8311.  
  8312. Dump IDT Entries 
  8313.  
  8314. di [a] [<range>]
  8315.  
  8316. Dumps the interrupt descriptor table. 
  8317.  
  8318. The a parameter specifies a dump of all of the IDT entries. 
  8319.  
  8320. The default is to display only the valid IDT entries. 
  8321.  
  8322. Dump LDT Entries 
  8323.  
  8324. dl [a|p|s|h] [<range>]
  8325.  
  8326. Dump local descriptor table entries. 
  8327.  
  8328. The a parameter specifies a dump of all of the LDT entries. 
  8329.  
  8330. The default is to display only the valid LDT entries. 
  8331.  
  8332. The p parameter specifies the private selectors only. 
  8333.  
  8334. The s parameter specifies the shared selectors only. 
  8335.  
  8336. The h parameter specifies the huge segment selectors only. 
  8337.  
  8338. Dump Page Directory/Page Table Entries 
  8339.  
  8340. dp [a|d] [<range>]
  8341.  
  8342. Dump the page directory and page tables. Page tables are skipped if the 
  8343. corresponding page directory entry is not present. Page directory entries with 
  8344. an asterisk next to the page frame should be ignored. 
  8345.  
  8346. The a parameter specifies a dump of all of the page directory and page table 
  8347. entries. 
  8348.  
  8349. The default is to skip entries that are zero. 
  8350.  
  8351. The d parameter specifies a dump of page directory entries only. 
  8352.  
  8353. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  8354. ΓöéDc                  ΓöéDirty/clean                   Γöé
  8355. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8356. ΓöéAu                  ΓöéAccessed/unaccessed           Γöé
  8357. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8358. ΓöéUs                  ΓöéUser/supervisor               Γöé
  8359. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8360. ΓöéWr                  ΓöéWritable/read-only            Γöé
  8361. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8362. ΓöéPn                  ΓöéPresent/not present           Γöé
  8363. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  8364. Table 13-5. Page bit definitions (bit set/clear) 
  8365.  
  8366. The pteframe field contains the contents of the high 20 bits in the pte. If the 
  8367. page is present, the value is the high 20 bits of the physical address that the 
  8368. page maps to. To find out information about the physical address, use the .mp 
  8369. command. If the page is not present, the pteframe field contains an index into 
  8370. the Virtual Page (VP) structure. The .mv command can dump information from the 
  8371. VP structure. A not-present page may still be cross-linked to a page of 
  8372. physical memory via the VP, and if so, that physical address is in the frame 
  8373. column. 
  8374.  
  8375. Note: uvirt pages in the state column represent a direct mapping of physical 
  8376. memory without any other page manager structures associated with them. 
  8377.  
  8378. Dump Task State Segment (TSS) 
  8379.  
  8380. dt [<addr>]
  8381.  
  8382. Dumps the TSS.  If no address is given, the dt command will dump the current 
  8383. TSS pointed to by the TR register, extracting the type (16- or 32-bit) from the 
  8384. descriptor access byte.  If an address is given, the type is determined by the 
  8385. 386env flag. 
  8386.  
  8387. Dump Loadall Buffer 
  8388.  
  8389. dx
  8390.  
  8391. Dump the 80286 loadall buffer. 
  8392.  
  8393. Enter Data 
  8394.  
  8395. e <addr> [<list>]
  8396.  
  8397. Enter one or more byte values into memory at the specified addr. 
  8398.  
  8399. The list parameter specifies a list of bytes to be stored at addr and each 
  8400. subsequent address, until all of the data in the list has been used. 
  8401.  
  8402. If the list is omitted, KDB prompts the operator for a byte . If an error 
  8403. occurs, the contents of memory are left unchanged. Each time the space bar is 
  8404. hit, the address is incremented by one byte. The minus key (-) decrements the 
  8405. address. The return key with no data terminates the entry and returns to the 
  8406. KDB prompt. 
  8407.  
  8408. Fill Memory With Pattern 
  8409.  
  8410. f <range> <list>
  8411.  
  8412. Block fills the addresses in the range with the values in the list. 
  8413.  
  8414. The list parameter specifies a pattern or list of bytes to be stored. 
  8415.  
  8416. If the range specifies more bytes than the number of values in the list, the 
  8417. pattern of bytes in the list is repeated until all bytes in the range are 
  8418. filled. If the list has more values than the number of bytes in the range, the 
  8419. extra bytes are ignored. 
  8420.  
  8421. Go 
  8422.  
  8423. g [s] [t] [=<start addr>][<break addr>],[<break addr>...]
  8424.  
  8425. Passes execution control to the code at the start addr.  Execution continues to 
  8426. the end of the code, or until the break addr or a breakpoint is encountered. 
  8427.  
  8428. If no start addr is given, the command passes execution to the address 
  8429. specified by the current CS:IP. 
  8430.  
  8431. The equal sign (=) parameter is used only when a start addr is given. 
  8432.  
  8433. The s parameter causes the number of timer ticks since the system was started 
  8434. to be displayed. 
  8435.  
  8436. The t parameter allows trapped exceptions to resume at the original trap 
  8437. handler address without having to unhook the exception. 
  8438.  
  8439. Up to 10 addresses may be used. Only the first address encountered during 
  8440. execution will cause a break. All others are ignored. If more than 10 
  8441. breakpoints are entered, an error message will be displayed. 
  8442.  
  8443. When the breakpoint is encountered, the default command is executed. 
  8444.  
  8445. Help/Print Expression 
  8446.  
  8447. ?[<expr>][|'string']
  8448.  
  8449. If no arguments are entered, KDB displays the command syntax help for the 
  8450. internal debugger commands. 
  8451.  
  8452. The expr parameter is an expression to be evaluated. The evaluated expression 
  8453. is displayed in hex, decimal, octal, and binary. 
  8454.  
  8455. The string parameter prints the ASCII string on the debugger terminal. 
  8456.  
  8457. Hex Arithmetic 
  8458.  
  8459. h <number 1> <number 2>
  8460.  
  8461. Perform hex arithmetic in two values. KDB adds number 1 to number 2, subtracts 
  8462. number 1 from number 2, multiplies number 1 by number 2, divides number 1 by 
  8463. number 2, and displays the results. 
  8464.  
  8465. Input Port 
  8466.  
  8467. i <port>
  8468.  
  8469. Reads and displays one byte from the specified port. 
  8470.  
  8471. List Near Symbols 
  8472.  
  8473. ln [<addr>]
  8474.  
  8475. Lists the nearest symbol both forward and back from addr. 
  8476.  
  8477. List Groups 
  8478.  
  8479. lg [<mapname>]
  8480.  
  8481. Lists the selector or segment and the name for each group in the active maps or 
  8482. the specified map mapname. 
  8483.  
  8484. List Maps 
  8485.  
  8486. lm
  8487.  
  8488. Lists all of the current symbol files loaded, and which ones are active. 
  8489.  
  8490. List Absolute Symbols 
  8491.  
  8492. la [<mapname>]
  8493.  
  8494. Lists all of the absolute symbols in the active maps or the specified map 
  8495. mapname. 
  8496.  
  8497. List Symbols 
  8498.  
  8499. ls <addr>
  8500.  
  8501. Lists all of the symbols in the group that the address addr is in. 
  8502.  
  8503. Add/Remove Active Map 
  8504.  
  8505. wa <mapname> | *
  8506. wr <mapname> | *
  8507.  
  8508. Adds (wa) or deletes (wr) a map to the active map list. The active maps are 
  8509. listed with the lm command. 
  8510.  
  8511. The mapname parameter is the name of a map file to make active or an active map 
  8512. to be removed. 
  8513.  
  8514. The * parameter adds or removes all map files. 
  8515.  
  8516. Conditional Execution 
  8517.  
  8518. j <expr> [<command list>]
  8519.  
  8520. Executes the command list if the expression evaluates to TRUE (nonzero). 
  8521. Otherwise, it continues to the next command in the command line, but not 
  8522. including the ones in the command list. The command list is one or more 
  8523. commands surrounded by single or double quotes. If more than one command 
  8524. appears in the command list, the commands must be separated by the semicolon 
  8525. (;) character. 
  8526.  
  8527. The j command is normally used to set a conditional breakpoint at a particular 
  8528. address. 
  8529.  
  8530. Stack Trace 
  8531.  
  8532. k [s|b] [<ss:bp addr>] [<cs:ip addr>]
  8533.  
  8534. Traces the bp chain on the stack and prints the address, 4 words/dwords of 
  8535. parameters, and any symbol found for the address. 
  8536.  
  8537. The s parameter specifies a 16-bit frame width.
  8538.  
  8539. The b parameter specifies a 32-bit frame width.
  8540.  
  8541. The ss:bp specifies a stack address other than the current ss:bp. 
  8542.  
  8543. The cs:ip parameter specifies an execution address other than the current cs:ip 
  8544. values. 
  8545.  
  8546. Move Memory 
  8547.  
  8548. m <range> <addr>
  8549.  
  8550. Moves the block of memory specified by a range to the location starting at 
  8551. addr. 
  8552.  
  8553. Ouput Byte 
  8554.  
  8555. o <port> <byte>
  8556.  
  8557. Sends the byte to the specified output port. 
  8558.  
  8559. Ptrace/Program Step 
  8560.  
  8561. p [n|t] [=<start-addr>] [<count>]
  8562.  
  8563. Executes the instruction at the start address, then executes the current 
  8564. default command. 
  8565.  
  8566. The n parameter causes the register to be suppressed if the default command is 
  8567. r. 
  8568.  
  8569. The t parameter allows the original trap handler address to be traced without 
  8570. having to unhook the exception. 
  8571.  
  8572. The start addr parameter is an optional address to start at, otherwise 
  8573. execution begins at the current cs:ip. 
  8574.  
  8575. The count parameter specifies the number of instructions to execute before 
  8576. stopping. 
  8577.  
  8578. The p command is different than the t command, in that the p command will allow 
  8579. a function call to complete before stopping again. A p command executed at a 
  8580. call instruction will stop only after the call has been completed. The t 
  8581. command will trace into the call and stop at every instruction. 
  8582.  
  8583. Register 
  8584.  
  8585. r [t][<register-name> [<value>]]
  8586.  
  8587. Displays the contents of CPU register and allows its contents to be changed. 
  8588.  
  8589. The t parameter toggles the terse register display flag. 
  8590.  
  8591. The register name is any one of the valid register names listed in Table 13-6. 
  8592.  
  8593. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  8594. ΓöéRegister name       ΓöéMeaning                       Γöé
  8595. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8596. ΓöéAX, BX, CX, DX, SI, Γöégeneral registers             Γöé
  8597. ΓöéDI, BP, SP, IP      Γöé                              Γöé
  8598. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8599. ΓöéDS, ES, SS, CS      Γöésegment registers             Γöé
  8600. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8601. ΓöéGDTB                ΓöéGDT base as a linear address  Γöé
  8602. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8603. ΓöéGDTL                ΓöéGDT limit                     Γöé
  8604. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8605. ΓöéIDTB                ΓöéIDT base as a linear address  Γöé
  8606. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8607. ΓöéIDTL                ΓöéIDT limit                     Γöé
  8608. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8609. ΓöéTR, LDTR            ΓöéTR, LDTR registers            Γöé
  8610. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8611. ΓöéIOPL                Γöéiopl portion of flag registersΓöé
  8612. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8613. ΓöéF                   Γöéflag register                 Γöé
  8614. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8615. ΓöéMSW                 ΓöéMachine status word           Γöé
  8616. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8617. ΓöéEAX, EBX, ECX, EDX, Γöéextended general registers    Γöé
  8618. ΓöéESI, EDI, EBP, ESP, Γöé                              Γöé
  8619. ΓöéEIP                 Γöé                              Γöé
  8620. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8621. ΓöéFS, GS              Γöésegment registers             Γöé
  8622. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8623. ΓöéEF                  Γöéextended flag register        Γöé
  8624. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8625. ΓöéCR0, CR2, CR3, CR4  Γöécontrol registers             Γöé
  8626. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8627. ΓöéDR0, DR1, DR2, DR3, Γöédebug registers               Γöé
  8628. ΓöéDR6, DR7            Γöé                              Γöé
  8629. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8630. ΓöéTR6, TR7            Γöétest registers                Γöé
  8631. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8632. ΓöéIP, PC              Γöéthe Instruction Pointer       Γöé
  8633. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8634. ΓöéF                   Γöéthe Flags register            Γöé
  8635. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  8636. Table 13-6. KDB register definitions. 
  8637.  
  8638. If no register name parameter is supplied, the r command displays all of the 
  8639. registers, flags, and the instruction at the current cs:ip. 
  8640.  
  8641. If a register name parameter is supplied, the current value of the register is 
  8642. displayed, and KDB prompts for a new value. If both the register name and value 
  8643. are given, the command changes the register name to the value. 
  8644.  
  8645. To change one of the flag values, supply the register name f when entering the 
  8646. Register command. The f register parameter will display the current value of 
  8647. each flag as a two-letter name. Table 13-7 contains a list of flag values by 
  8648. name. 
  8649.  
  8650. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  8651. ΓöéFlag name     ΓöéSet                 ΓöéClear               Γöé
  8652. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8653. ΓöéOverflow      ΓöéOV                  ΓöéNV                  Γöé
  8654. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8655. ΓöéDirection     ΓöéDN (Decrement)      ΓöéUP (Increment)      Γöé
  8656. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8657. ΓöéInterrupt     ΓöéEI (Enabled)        ΓöéDI (Disabled)       Γöé
  8658. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8659. ΓöéSign          ΓöéNG (Negative)       ΓöéPL (Plus)           Γöé
  8660. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8661. ΓöéZero          ΓöéZR                  ΓöéNZ                  Γöé
  8662. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8663. ΓöéAux Carry     ΓöéAC                  ΓöéNA                  Γöé
  8664. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8665. ΓöéParity        ΓöéPE (Even)           ΓöéPO (Odd)            Γöé
  8666. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8667. ΓöéCarry         ΓöéCY                  ΓöéNC                  Γöé
  8668. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8669. ΓöéNested Task   ΓöéNT                  Γöé(toggles)           Γöé
  8670. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  8671. Table 13-7. KDB flag register definitions. 
  8672.  
  8673. At the end of the list of values, the command displays a minus sign (-). The 
  8674. new values for the flags can now be entered in any order. To terminate the 
  8675. flags entry, press the return key. 
  8676.  
  8677. To change the MSW (Machine status word), use names outline in  Table 13-8. 
  8678.  
  8679. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  8680. ΓöéFlag                ΓöéSet       ΓöéClear       Γöé
  8681. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8682. ΓöéProtected Mode      ΓöéPM        Γöé(toggles)   Γöé
  8683. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8684. ΓöéMonitor Processor   ΓöéMP        Γöé(toggles)   Γöé
  8685. ΓöéExtension           Γöé          Γöé            Γöé
  8686. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8687. ΓöéEmulate Processor   ΓöéEM        Γöé(toggles)   Γöé
  8688. ΓöéExtension           Γöé          Γöé            Γöé
  8689. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8690. ΓöéTask Switched       ΓöéTS        Γöé(toggles)   Γöé
  8691. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  8692. Table 13-8. KDB machine status word.  Toggles means that if the flag is set, 
  8693. using the flag name will clear it. If the flag is clear, it will be reset. 
  8694.  
  8695. Search 
  8696.  
  8697. s <range> <list>
  8698.  
  8699. Searches the memory range for a pattern matching the list parameter. 
  8700.  
  8701. Trace 
  8702.  
  8703. t [a|c|n|s|t|x][=<start addr>][<count>][<addr>]
  8704.  
  8705. Executes the instruction at the start address or current cs:ip. 
  8706.  
  8707. The a parameter specifies an ending address for the trace. 
  8708.  
  8709. The c parameter suppresses all output and counts the instructions traced. 
  8710.  
  8711. The n parameter suppresses the register display. Only the assembly line is 
  8712. displayed. This option works only if the default command is r. 
  8713.  
  8714. The s parameter is a special trace that which causes the instruction and count 
  8715. for every call and return to be displayed. 
  8716.  
  8717. The t parameter allows the original trap handler address to be traced without 
  8718. unhooking the exception. 
  8719.  
  8720. The x parameter forces KDB to trace regions of code known to be untraceable. 
  8721.  
  8722. Unassemble 
  8723.  
  8724. u [<range>]
  8725.  
  8726. Display the instructions in a range in a mnemonic format. All of the 286 and 
  8727. 287 op-codes can be displayed. 
  8728.  
  8729. List Real/Protect Mode Exceptions 
  8730.  
  8731. vl[n | p | v | r | f]
  8732.  
  8733. Lists the real and protected mode exceptions that the debugger intercepts. 
  8734.  
  8735. The n option specifies the traps that beep when hit. 
  8736.  
  8737. The p option specifies only the protect mode vectors. 
  8738.  
  8739. The r option specifies only the real mode vectors. 
  8740.  
  8741. The v option specifies both real and protect mode vectors. 
  8742.  
  8743. The f option directs the kernel to route fatal faults to the debugger and not 
  8744. to display a pop-up message. 
  8745.  
  8746. Vectors  set with vt (as opposed to vs) will be printed with a star following 
  8747. the vector number. 
  8748.  
  8749. Add Interrupt/Trap Vector, All Rings 
  8750.  
  8751. vt[n | p | v | r | f] n[,n,..]
  8752.  
  8753. Adds a new intercept vector that the debugger intercepts. 
  8754.  
  8755. The r option will install a debugger handler in the real mode IDT. 
  8756.  
  8757. The p option will install a debugger handler in the protect mode IDT. 
  8758.  
  8759. The n option causes the intercepted traps to beep when hit. 
  8760.  
  8761. The f option directs the kernel to route fatal faults to the debugger and not 
  8762. to display a pop-up message. 
  8763.  
  8764. Intercept Trap Vector Except Ring 0 
  8765.  
  8766. vs[n | p | v | r | f] n[,n,..]
  8767.  
  8768. Identical to vt except that vs will not intercept ring 0 interrupts. 
  8769.  
  8770. vsv or vtv intercepts V86 mode exceptions or traps. 
  8771.  
  8772. For GP faults, vsf d is the same a vsp d. For page faults, vsp e would trap all 
  8773. ring 3/2 page faults, but vsf e would trap only the invalid page faults. 
  8774.  
  8775. Clear Interrupt/Trap Vectors 
  8776.  
  8777. vc[n | p | v | r | f] n,[n],..
  8778.  
  8779. Clears the vectors indicated, reinstalling whatever address was in the vector 
  8780. before the debugger grabbed the vector. 
  8781.  
  8782. The n option causes the trap(s) not to beep when hit. The trap remains intact. 
  8783.  
  8784. To intercept general protection faults before OS/2 does, use  vtp d before the 
  8785. fault is hit, examine the information about the fault, and do a vcp d and g, 
  8786. which will let the OS/2 GP handler get control (and kill the process, etc). 
  8787. Another option would be to enter a vcp d after hitting the fault and trace into 
  8788. the exception handler. The tt or gt commands perform this automatically. 
  8789.  
  8790. Debugger Options 
  8791.  
  8792. y[?] [386env|dislwr|regterse]
  8793.  
  8794. Toggles one of the debugger option flags. 
  8795.  
  8796.   386env     386 environment 
  8797.  
  8798.   dislwr     display lower case 
  8799.  
  8800.   regterse   terse register display flag 
  8801.  
  8802. The 386env flag controls the size of addresses, registers, and other 
  8803. information when displayed. When 386env is on, the display format is 32 bits. 
  8804. When off, the display format is 16 bits. 
  8805.  
  8806. The dislwr flag, when enabled, displays assembler code in lower case. When 
  8807. disabled, assembler code is shown in upper case. 
  8808.  
  8809. The regterse flag determines the number of registers displayed with the r 
  8810. command. If regterse is on, only the first three lines of registers are 
  8811. displayed. If regterse is off, all six lines of registers, plus the unassembled 
  8812. instruction, are displayed. 
  8813.  
  8814. The ? parameter displays the currently supported options. 
  8815.  
  8816. The y command without any parameters displays the current state of the option 
  8817. flags. 
  8818.  
  8819. Execute Default Command 
  8820.  
  8821. z
  8822.  
  8823. Executes the current default command.  The default command is a string of 
  8824. debugger commands that are executed any time that the debugger is entered and 
  8825. there is no breakpoint command attached to the entry. The r command is 
  8826. initialized as the default command when the system is rebooted. 
  8827.  
  8828. List Default Command 
  8829.  
  8830. zl
  8831.  
  8832. Lists the current default command. 
  8833.  
  8834. Change Default Command 
  8835.  
  8836. zs <string>
  8837.  
  8838. Changes the default command to a string. Any errors will cause the default 
  8839. command to be reset to r. 
  8840.  
  8841.  
  8842. ΓòÉΓòÉΓòÉ 16.5. External Commands ΓòÉΓòÉΓòÉ
  8843.  
  8844. Help 
  8845.  
  8846. .?
  8847.  
  8848. Prints the help menu for the external debugger commands. 
  8849.  
  8850. Baud Rate 
  8851.  
  8852. .b <baud rate> [<port addr>]
  8853.  
  8854. This command will set the baud rate of the debugging port. 
  8855.  
  8856. The legal baud rate values are 150t, 300t, 600t, 1200t, 2400t, 4800t, 9600t, 
  8857. and 19200t. 
  8858.  
  8859. The port addr parameter is 1 for COM1 and 2 for COM2. The default port addr is 
  8860. 2. 
  8861.  
  8862. Dump ABIOS Common Data Area 
  8863.  
  8864. .c
  8865.  
  8866. Dumps the ABIOS common data area. 
  8867.  
  8868. Display Data Structure 
  8869.  
  8870. .d <data struct name> [<addr>]
  8871.  
  8872. Displays an OS/2 data structure. The valid data structure names appear in Table 
  8873. 13-9. 
  8874.  
  8875. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  8876. ΓöéName          ΓöéDescription                   Γöé
  8877. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8878. ΓöéBPB           ΓöéBIOS Parameter Block          Γöé
  8879. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8880. ΓöéBUF           ΓöéFile system buffer            Γöé
  8881. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8882. ΓöéDEV           ΓöéDevice driver header          Γöé
  8883. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8884. ΓöéDPB           ΓöéDisk Parameter Block          Γöé
  8885. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8886. ΓöéMFT           ΓöéMaster File Table entry       Γöé
  8887. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8888. ΓöéREQ           ΓöéRequest Packet                Γöé
  8889. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8890. ΓöéSFT           ΓöéSystem File Table entry       Γöé
  8891. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8892. ΓöéCDS           ΓöéCurrent Directory Structure   Γöé
  8893. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8894. ΓöéSEM32         Γöé32-Bit Semaphore Structure    Γöé
  8895. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8896. ΓöéOPENQ         Γöé32-Bit Semaphore OPENQ chain  Γöé
  8897. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8898. ΓöéMUXQ          Γöé32-Bit Semaphore MUXQ chain   Γöé
  8899. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8900. ΓöéKSEM          Γöé32-Bit Kernel Semaphore       Γöé
  8901. Γöé              ΓöéStructure                     Γöé
  8902. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8903. ΓöéDT            ΓöéTask State Segment Structure  Γöé
  8904. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  8905. ΓöéVPB           ΓöéVolume Parameter Block        Γöé
  8906. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  8907. Table 13-9. KDB recognized structures. 
  8908.  
  8909. Swap In TSD or Page 
  8910.  
  8911. .i[d|b] [<addr>]
  8912. .it[d|b] [<slot>]
  8913.  
  8914. Swaps in a TSD or Page. 
  8915.  
  8916. The i command with an address will cause the page enclosing the address addr to 
  8917. be swapped in. The address may contain an optional task slot number override, 
  8918. such as %2|40000. 
  8919.  
  8920. The it command swaps in the corresponding task's TSD. 
  8921.  
  8922. The d option queues up a single swap-in request to be acted upon by the KDB 
  8923. daemon thread. 
  8924.  
  8925. The slot parameter is the task's slot number. 
  8926.  
  8927. Trace User Stack 
  8928.  
  8929. .k[s|b] [<ss:bp addr>] [<cs:ip addr>]
  8930.  
  8931. Traces the bp chain on the user stack and prints the address, 4 words/dwords of 
  8932. parameters, and any symbol found for the address. 
  8933.  
  8934. The s option specifies a 16-bit frame width. 
  8935.  
  8936. The b option specifies a 32-bit frame width. 
  8937.  
  8938. The ss:bp specifies a stack address other than the current ss:bp. 
  8939.  
  8940. The cs:ip parameter specifies an execution address other than the current cs:ip 
  8941. values. 
  8942.  
  8943. Display MTE Segment Table 
  8944.  
  8945. .lm[o][l|p|v|x] <hobmte|laddr|"module name"]
  8946.  
  8947. Prints module table entries and their associated object and segment table 
  8948. entries. 
  8949.  
  8950. The o option suppresses the object or segment table display.
  8951.  
  8952. The l option displays only library (.DLL) MTEs.
  8953.  
  8954. The p option displays only Physical Device Driver ( PDD) MTEs.
  8955.  
  8956. The v option displays only Virtual Device Driver (VDD) MTEs.
  8957.  
  8958. The x option displays only executable (.EXE) MTEs.
  8959.  
  8960. If a nonzero hobmte is supplied, only those MTEs with a matching  hobmte are 
  8961. printed.  If a nonzero linear address is given, only the MTE pointed to by the 
  8962. linear address is printed. If a quoted string is given, only those MTEs with a 
  8963. matching module name are printed. 
  8964.  
  8965. The module name for a:\bar.dll and c:\foo\bar.exe are both "bar". No drive, 
  8966. path, or extension information should be given. 
  8967.  
  8968. Dump Memory Arena Records 
  8969.  
  8970. .ma[a|b|c|f|h|l|m|r] [<har|laddr>] | [<har|laddr> L<number of entries>]
  8971.  
  8972. This command displays the virtual memory manager's arena records. If no handle 
  8973. or linear address is given, the entire table is displayed. If a linear address 
  8974. is given, it is taken to be a pointer to an arena record. One record or a range 
  8975. of records can be displayed. 
  8976.  
  8977. The a option displays all contexts. 
  8978.  
  8979. The b option displays only busy entries (default). 
  8980.  
  8981. The c option finds the corresponding object record, and displays the arena, 
  8982. object, alias, and context record chains. 
  8983.  
  8984. The h option walks hash links, displaying the entries. 
  8985.  
  8986. The l option walks forward links, displaying the entries. 
  8987.  
  8988. The r option walks reverse links, displaying the entries. 
  8989.  
  8990. The m option specifies the display of all arena records whose linear address 
  8991. encloses the supplied linear address to be displayed.  A linear address must 
  8992. also be supplied, and no count is allowed.  Context information is ignored, so 
  8993. if the linear address is valid in multiple contexts, multiple arena records 
  8994. will be displayed.  A physical address may be supplied instead of a linear 
  8995. address, to allow not-present linear addresses to get past the debugger's 
  8996. expression analyzer. If a selector address type is used, it must be converted 
  8997. to a linear address in the command line. 
  8998.  
  8999. To find out who owns a selector because of a GP fault in some unknown LDT or 
  9000. GDT segment or memory object, the following command is used: 
  9001.  
  9002. .m or .mamc cs:eip 
  9003.  
  9004. This will display the arena record and memory object record (and the owner) of 
  9005. the code segment. It will also walk the context record chains and display them. 
  9006. The cs can be substituted with any selector, and the eip with any offset.  This 
  9007. command converts the selector:offset into a linear address automatically, so 
  9008. the resulting address can be used to find and interpret the arena record(s) and 
  9009. memory object record(s). 
  9010.  
  9011. Dump Memory Context Record 
  9012.  
  9013. .mc[b|c|f] [<hco|laddr>] | [<hco|laddr> L<number of entries>]
  9014.  
  9015. Displays the virtual memory manager's context records. If no parameters are 
  9016. supplied, the entire table is displayed. If a linear address is given, it is 
  9017. taken to be a pointer to a context record. One record or a range of records can 
  9018. be displayed. 
  9019.  
  9020. The b option specifies only busy files. 
  9021.  
  9022. The f option displays only free entries. 
  9023.  
  9024. The c option walks context record chains and displays them. 
  9025.  
  9026. Dump Memory Alias Record 
  9027.  
  9028. .ml[b|c|f] [<hal|laddr>] | [<hal|laddr> L<number of entries>]
  9029.  
  9030. Displays the virtual memory manager's alias records. 
  9031.  
  9032. If no parameters are supplied, the entire table is displayed. 
  9033.  
  9034. If a linear address is supplied, it is taken to be a pointer to an alias 
  9035. record. One record or a range of records can be displayed. 
  9036.  
  9037. The b option displays only busy entries. 
  9038.  
  9039. The f option displays only free entries. 
  9040.  
  9041. The c option finds the corresponding object record, and displays the arena, 
  9042. object, alias, and context record chains. 
  9043.  
  9044. Dump Memory Object Record 
  9045.  
  9046. .mo[b|c|f|m|n|p|s|v] [<hob|laddr>] | [<hob|laddr> L<number of entries>]
  9047.  
  9048. Display the virtual memory manager's memory object records. If no handle or 
  9049. linear address is supplied, the entire table is displayed. If a linear address 
  9050. is given, it is taken to be a pointer to an object record.  One record or a 
  9051. range of records can be displayed. 
  9052.  
  9053. The b option causes busy object records to be displayed. 
  9054.  
  9055. The f option causes free object records to be displayed. 
  9056.  
  9057. The c option displays the arena, object, alias, and context record chains. 
  9058.  
  9059. The m option causes all pseudo-object records with an exactly matching linear 
  9060. address to be displayed.  A linear address must also be supplied, and no count 
  9061. is allowed.  If a selector address type is used, it must be converted to a 
  9062. linear address on the command line.  A physical address may be supplied instead 
  9063. of a linear address, to allow not-present linear addresses to get past the 
  9064. debugger's expression analyzer. 
  9065.  
  9066. The n option causes non-pseudo object records to be displayed. 
  9067.  
  9068. The p option causes pseudo-object records to be displayed. 
  9069.  
  9070. The s option causes object records with the semaphore busy or wanted to be 
  9071. displayed. 
  9072.  
  9073. The v option causes object record linear addresses to be displayed. It also 
  9074. disables the owner interpretation. This command attempts to display what 
  9075. process, MTE, or PTDA owns the segment. It will display the owner as a short 
  9076. ASCII string, when appropriate. It will display the PID of the process and, if 
  9077. possible, the name of the module that owns this segment. Code segments will 
  9078. normally have only a module name and no process ID. If the segment is an MTE, 
  9079. PTDA, or LDT, KDB will display the object name, process ID (if the segment is a 
  9080. PTDA), and the module name, if possible. 
  9081.  
  9082. Dump Memory Page Frame 
  9083.  
  9084. .mp[b|f|h|l|r|s] [<frame|laddr>] | [<frame|laddr> L<number of entries>]
  9085.  
  9086. Displays the page manager's page frame structures. If no handle or linear 
  9087. address is supplied, the entire table is displayed. If a linear address is 
  9088. given, it is taken to be a pointer to a page frame structure. One record or a 
  9089. range of records can be displayed. 
  9090.  
  9091. The b options displays only busy entries.
  9092.  
  9093. The f option displays only free entries.
  9094.  
  9095. The h option walks hash links, displaying entries.
  9096.  
  9097. The l option walks forward links, displaying entries.
  9098.  
  9099. The r options walks reverse links, displaying entries.
  9100.  
  9101. This data structure contains per-physical page information. To find out the 
  9102. owner of a particular physical page, use .mp FrameNumber where FrameNumber is 
  9103. the physical address shifted right by 12 (take off 3 zeros).  If the page isn't 
  9104. free, the pVP field contains a flat pointer to the virtual page structure.  Use 
  9105. .mv %pVP where pVP is the value from the .mp dump, to get the contents of the 
  9106. VP.  The Hob field of the VP is a handle to the Object Record.  Use .mo Hob to 
  9107. dump it. That will display a readable string for the owner on the right of the 
  9108. display.  ma of the Har field in the object record will give the base virtual 
  9109. address of the object containing the page (under va).  Use the HobPg field of 
  9110. the VP to get the page offset within the object. 
  9111.  
  9112. Dump Virtual Page Structure 
  9113.  
  9114. .mv[b|f|l|r] [<vpid|laddr>] | [<swapid|laddr> L<number of entries>]
  9115.  
  9116. Displays the swap manager's swap frame structures. If no handle or linear 
  9117. address is supplied, the entire table is displayed. If a linear address is 
  9118. given, it is taken to be a pointer to a swap frame structure. One record or a 
  9119. range of records can be displayed. 
  9120.  
  9121. The b option displays only busy entries. 
  9122.  
  9123. The f option displays only free entries. 
  9124.  
  9125. The l option walks forward links, displaying entries. 
  9126.  
  9127. The r option walks reverse links, displaying entries. 
  9128.  
  9129. Process Status 
  9130.  
  9131. .p[b|u] [<slot> | # | *]
  9132.  
  9133. Displays the current process and thread status.  An asterisk (*) by the slot 
  9134. number indicates the currently running task. A # by the slot number indicates 
  9135. what the debugger thinks the current task is. 
  9136.  
  9137. The .p command, with no options, displays the following information: 
  9138.  
  9139. o slot number
  9140.  
  9141. o PID of the current process
  9142.  
  9143. o PID of the parent process
  9144.  
  9145. o command subtree number
  9146.  
  9147. o thread number
  9148.  
  9149. o current state
  9150.  
  9151. o priority
  9152.  
  9153. o Block ID
  9154.  
  9155. o Per Task Data Area (PTDA)
  9156.  
  9157. o Task Control Block (TCB) offset
  9158.  
  9159. o dispatch sp register value
  9160.  
  9161. o screen group
  9162.  
  9163. o name of the process or thread
  9164.  
  9165. The pb command directs KDB to display detailed block information including the: 
  9166.  
  9167. o slot
  9168.  
  9169. o Block ID
  9170.  
  9171. o name
  9172.  
  9173. o address blocked at
  9174.  
  9175. o symbol blocked on
  9176.  
  9177. o semaphore type.
  9178.  
  9179. The pu command directs KDB to display user state information including: 
  9180.  
  9181. o cs:ip and ss:sp values at the time the kernel was entered
  9182.  
  9183. o number of arguments passed and their PTDA offset
  9184.  
  9185. o offset of the register stack frame
  9186.  
  9187. o thread number
  9188.  
  9189. o PTDA address
  9190.  
  9191. o name.
  9192.  
  9193. Display User Registers 
  9194.  
  9195. .r [<slot> | # | *]
  9196.  
  9197. Displays the contents of the user's CPU registers, flags, and the next 
  9198. instruction to be executed for a specified slot, at time of entry to the 
  9199. kernel. 
  9200.  
  9201. The slot parameter is the slot number to use. 
  9202.  
  9203. The # parameter specifies the use of the current slot. 
  9204.  
  9205. The * parameter specifies to use the currently scheduled slot or the last one 
  9206. blocked. 
  9207.  
  9208. Reboot 
  9209.  
  9210. .reboot
  9211.  
  9212. Warm-boot the machine. 
  9213.  
  9214. Change Task Context 
  9215.  
  9216. .s[s] [<slot> | *]
  9217.  
  9218. Changes what the debugger thinks the current task context is. If no slot number 
  9219. is passed, it will print the current task number. 
  9220.  
  9221. The s option changes the ss and sp to the new task's PTDA selector and dispatch 
  9222. sp value. The original ss and sp is restored when the debugger exits or when 
  9223. the ss command is used to switch back to the current task. 
  9224.  
  9225. The * parameter changes the current debugger's task number to the real OS/2 
  9226. task number. 
  9227.  
  9228. Dump RAS Trace Buffer 
  9229.  
  9230. .t [<count>] [maj=<xx> [min=<yy>]]
  9231.  
  9232. Dumps the RAS trace buffer, optionally dumping only events with the specified 
  9233. major and minor event codes. 
  9234.  
  9235.  
  9236. ΓòÉΓòÉΓòÉ 17. Chapter 14 - An Introduction To Presentation Device Drivers ΓòÉΓòÉΓòÉ
  9237.  
  9238. Presentation Device Drivers (PMDDs) for OS/2 provide support for graphics 
  9239. devices such as display terminals, printers, plotters, and scanners. 
  9240. Presentation drivers provide hardware independence for application programs 
  9241. that perform I/O to these devices. 
  9242.  
  9243. The presentation driver in OS/2 2.1 is a DLL, which runs at Ring 3, and has the 
  9244. filename extension DRV. When an application needs to perform I/O to a 
  9245. Presentation driver, it calls a system DLL, which in turn calls the 
  9246. Presentation Manager graphics engine. The Presentation Manager graphics engine 
  9247. is contained in PMGRE.DLL. 
  9248.  
  9249. When a presentation driver is loaded, the graphics engine allocates a dispatch 
  9250. table containing pointers to routines in the graphics engine. The first time 
  9251. that the presentation driver is called at its OS2_PM_DRV_ENABLE entry point, it 
  9252. replaces pointers in the dispatch table with pointers to functions supported by 
  9253. the presentation driver. Some of the pointer replacements are mandatory, and 
  9254. others are optional. The presentation driver is passed the pointer to the 
  9255. dispatch table by the graphics engine with the FillLogicalDeviceBlock routine 
  9256. function call. 
  9257.  
  9258. Presentation drivers are called using the C (_cdecl) calling convention. The 
  9259. first parameter passed is the function number and flags word. The function 
  9260. numbers are defined in PMDDIM.H, and represent ordinals for graphics engine 
  9261. (Gre...) calls. The flag bits are defined in Table 14-1. 
  9262.  
  9263. ΓöîΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9264. ΓöéBit Γöé#define        ΓöéDescription                   Γöé
  9265. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9266. Γöé0   ΓöéCOM_DRAW       Γöéif set, draw the output at theΓöé
  9267. Γöé    Γöé               Γöédevice, if clear, don't draw  Γöé
  9268. Γöé    Γöé               Γöéthe data but update the       Γöé
  9269. Γöé    Γöé               Γöéinternal data                 Γöé
  9270. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9271. Γöé1   ΓöéCOM_BOUND      Γöéif set, the driver calculates Γöé
  9272. Γöé    Γöé               Γöéthe bounding rectangle for theΓöé
  9273. Γöé    Γöé               Γöéoutput.  When done, the driverΓöé
  9274. Γöé    Γöé               Γöécalls its own                 Γöé
  9275. Γöé    Γöé               ΓöéGreAccumulateBounds to        Γöé
  9276. Γöé    Γöé               Γöéaccumulate the bounding       Γöé
  9277. Γöé    Γöé               Γöérectangle (GPI_BOUNDS).  All  Γöé
  9278. Γöé    Γöé               Γöépresentation drivers must     Γöé
  9279. Γöé    Γöé               Γöésupply this function.         Γöé
  9280. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9281. Γöé2   ΓöéCOM_CORR       Γöéfor display drivers only, if  Γöé
  9282. Γöé    Γöé               Γöéset, the presentation driver  Γöé
  9283. Γöé    Γöé               Γöémust determine if the output  Γöé
  9284. Γöé    Γöé               Γöéintersects a pick window, and Γöé
  9285. Γöé    Γöé               Γöéreturns TRUE or FALSE.        Γöé
  9286. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9287. Γöé3   ΓöéCOM_ALT_BOUND  Γöédirects a display driver to   Γöé
  9288. Γöé    Γöé               Γöéaccumulate USER_BOUNDS in     Γöé
  9289. Γöé    Γöé               Γöéscreen coordinates            Γöé
  9290. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9291. Γöé4   ΓöéCOM_AREA       Γöéif set, specifies that the    Γöé
  9292. Γöé    Γöé               Γöéfunction call is part of an   Γöé
  9293. Γöé    Γöé               Γöéarea.                         Γöé
  9294. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9295. Γöé5   ΓöéCOM_PATH       Γöéif set, the function is part  Γöé
  9296. Γöé    Γöé               Γöéof a path                     Γöé
  9297. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9298. Γöé6   ΓöéCOM_TRANSFORM  Γöéif set, the presentation      Γöé
  9299. Γöé    Γöé               Γöédriver must convert the       Γöé
  9300. Γöé    Γöé               Γöécoordinates for the specified Γöé
  9301. Γöé    Γöé               Γöéfunction from world to device Γöé
  9302. Γöé    Γöé               Γöécoordinates using GreConvert. Γöé
  9303. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9304. Γöé7   ΓöéCOM_RECORDING  Γöéthis bit should be ignored.   Γöé
  9305. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9306. Γöé8   ΓöéCOM_DEVICE     Γöéif set, the driver should     Γöé
  9307. Γöé    Γöé               Γöéhandle this function and not  Γöé
  9308. Γöé    Γöé               Γöépass it back to the graphics  Γöé
  9309. Γöé    Γöé               Γöéengine for disposition.       Γöé
  9310. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9311. Γöé9-15ΓöéN/A            Γöéignored.                      Γöé
  9312. ΓööΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9313. Table 14-1. Presentation driver flag bits. 
  9314.  
  9315.  
  9316. ΓòÉΓòÉΓòÉ 17.1. Device Context ΓòÉΓòÉΓòÉ
  9317.  
  9318. The presentation application usually makes a KDB, MOU, VIO, DEV, AVIO, GPI, or 
  9319. WIN call to perform I/O. These functions exist in Ring 3 DLLs, and they call 
  9320. the graphics engine in PMGRE.DLL. PMGRE.DLL, in turn, calls the display or 
  9321. printer driver. The display driver may then access the adapter hardware 
  9322. directly through memory-mapped I/O, or may call the OS/2 kernel via the 
  9323. standard driver interface mechanism to perform the I/O. 
  9324.  
  9325. The application program that needs to write to a Presentation Manager device 
  9326. first opens a Device Context (DC), using the DevOpenDC call. The application 
  9327. associates a presentation space with the DC and writes or draws in that space. 
  9328. Each time DevOpenDC is called, a new instance of a DC is created. This instance 
  9329. is destroyed when the application closes the Device Context with the DevCloseDC 
  9330. function call. Each instance of a DC has: 
  9331.  
  9332. o a device context type
  9333.  
  9334. o data type
  9335.  
  9336. o instance data
  9337.  
  9338. o stack
  9339.  
  9340. When the DC is enabled, the type of device that is being opened is passed to 
  9341. the presentation driver, using one of the context types described in Table 
  9342. 14-2. 
  9343.  
  9344. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9345. ΓöéType        Γöédescription                   Γöé
  9346. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9347. ΓöéOD_INFO     ΓöéThe context is for informationΓöé
  9348. Γöé            Γöéonly.  The driver does not    Γöé
  9349. Γöé            Γöégenerate output. All Gre......Γöé
  9350. Γöé            Γöéfunctions are processed by theΓöé
  9351. Γöé            Γöépresentation driver.          Γöé
  9352. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9353. ΓöéOD_MEMORY   ΓöéThe driver processes the      Γöé
  9354. Γöé            Γöéoutput for the device, but theΓöé
  9355. Γöé            Γöéoutput is written to a        Γöé
  9356. Γöé            Γöédevice-compatible bitmap.     Γöé
  9357. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9358. ΓöéOD_DIRECT   ΓöéThe presentation driver       Γöé
  9359. Γöé            Γöéprocesses the Gre...  routinesΓöé
  9360. Γöé            Γöéto generate device specific   Γöé
  9361. Γöé            Γöédata.  The data is passed to  Γöé
  9362. Γöé            Γöéthe adapter PDD via the kernelΓöé
  9363. Γöé            Γöé(hard-copy drivers only).     Γöé
  9364. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9365. ΓöéOD_QUEUED   ΓöéThe output is spooled using   Γöé
  9366. Γöé            Γöéthe Spl... interface          Γöé
  9367. Γöé            Γöé(hard-copy drivers only).     Γöé
  9368. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9369. Table 14-2. Device context types. 
  9370.  
  9371.  
  9372. ΓòÉΓòÉΓòÉ 17.2. Data Types ΓòÉΓòÉΓòÉ
  9373.  
  9374. Presentation drivers that write to a spool file (OD_QUEUED) must support the 
  9375. two data types described in Table 14-3. 
  9376.  
  9377. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9378. ΓöéData type   ΓöéDescription                   Γöé
  9379. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9380. ΓöéPM_Q_STD    Γöéthe driver uses the spooler toΓöé
  9381. Γöé            Γöécreate a device-independent   Γöé
  9382. Γöé            Γöéspool file using the SplStd...Γöé
  9383. Γöé            Γöéand SplQm...  functions       Γöé
  9384. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9385. ΓöéPM_Q_RAW    Γöéthe driver processes the      Γöé
  9386. Γöé            ΓöéGre...  functions to generate Γöé
  9387. Γöé            Γöédevice-specific output data,  Γöé
  9388. Γöé            Γöéwhich is written to a spool   Γöé
  9389. Γöé            Γöéfile using the SplQm...       Γöé
  9390. Γöé            Γöéfunctions.                    Γöé
  9391. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9392. Table 14-3. Data types for queued data. 
  9393.  
  9394.  
  9395. ΓòÉΓòÉΓòÉ 17.3. Instance Data ΓòÉΓòÉΓòÉ
  9396.  
  9397. Each instance of a DC contains a double word pointer to information about the 
  9398. current context. The pointer is returned to the system by the presentation 
  9399. driver when the driver context is enabled. The pointer is passed back to the 
  9400. driver as a parameter in every call through the dispatch table. 
  9401.  
  9402. Program Stack 
  9403.  
  9404. Presentation drivers get a 500-byte stack, but should allocate their own stack 
  9405. of about 4K bytes. 
  9406.  
  9407. DLL Functions 
  9408.  
  9409. The initialization section of the presentation driver must be compiled and 
  9410. linked to run in Ring 3, and must EXPORT the following functions: 
  9411.  
  9412. o MoveCursor ( display drivers only )
  9413.  
  9414. o MoveCursorForInterrupt ( display drivers only )
  9415.  
  9416. o OS2_PM_DRV_ENABLE ( all drivers )
  9417.  
  9418. o OS2_PM_DRV_DEVMODE ( hard-copy presentation drivers only )
  9419.  
  9420. o OS2_PM_DRV_DEVICENAMES ( hard-copy presentation drivers only )
  9421.  
  9422. Hard-copy presentation drivers should also export entry points for routines 
  9423. that handle user interaction. 
  9424.  
  9425. The graphics engine exports the entry points listed in  Table 14-4. 
  9426.  
  9427. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9428. ΓöéEntry Point    ΓöéDescription                   Γöé
  9429. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9430. ΓöéInnerGreEntry  Γöémain entry point for all      Γöé
  9431. Γöé               ΓöéGre... ordinals               Γöé
  9432. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9433. ΓöéGETDRIVERINFO  Γöéused by the presentation      Γöé
  9434. Γöé               Γöédriver to get the instance    Γöé
  9435. Γöé               Γöépointer for a device context  Γöé
  9436. Γöé               Γöéor pointer to a bitmap header Γöé
  9437. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9438. ΓöéSETDRIVERINFO  Γöéused by the presentation      Γöé
  9439. Γöé               Γöédriver to set a specific valueΓöé
  9440. Γöé               Γöéin the instance pointer of a  Γöé
  9441. Γöé               Γöédevice context                Γöé
  9442. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9443. Table 14-4. Graphics engine exports. 
  9444.  
  9445. To access the graphics engine, the module definition file would have most of 
  9446. the function references associated with the InnerGreEntry point by ordinal. 
  9447.  
  9448.  
  9449. ΓòÉΓòÉΓòÉ 17.4. Presentation Driver Design Considerations ΓòÉΓòÉΓòÉ
  9450.  
  9451. Presentation drivers must always return a 32-bit value. 
  9452.  
  9453. Coordinate values are normally passed as 32-bit world coordinates, and can be 
  9454. converted to other coordinate systems by calling the graphics engine function 
  9455. GreConvert. Screen coordinates are device coordinates to which the DC origin 
  9456. has been added. 
  9457.  
  9458. Transform Matrix values are signed values represented by a 16-bit integer and 
  9459. 16-bit fraction. This resolution is maintained by the graphics engine matrix 
  9460. functions. 
  9461.  
  9462. Angles are 32-bit signed values, where 0 represents a positive X-axis and 
  9463. FFFFFFFF represents 360 degrees. 
  9464.  
  9465. Application bounds (COM_BOUND) are accumulated in model space, and user bounds 
  9466. (COM_ALT_BOUND) are accumulated in device-coordinate space. 
  9467.  
  9468. If the presentation driver hooks all of the Gre... path and area functions, it 
  9469. is responsible for generating closures for figures within areas or paths. 
  9470. Otherwise, the graphics engine will generate the closures. 
  9471.  
  9472. The presentation driver must provide clipping for drawing and text functions 
  9473. except GreDrawLinesInPath and GrePolyShortLine. Clipping for these two 
  9474. functions is provided by the graphics engine. 
  9475.  
  9476.  
  9477. ΓòÉΓòÉΓòÉ 17.5. Presentation Driver Errors ΓòÉΓòÉΓòÉ
  9478.  
  9479. When an error occurs in a presentation driver, the driver should call the 
  9480. WinSetErrorInfo functions to log the error. The presentation driver must 
  9481. validate all symbol sets, fonts, bitmaps, and regions before calling the 
  9482. graphics engine. The presentation driver must also verify all passed parameters 
  9483. and log any errors detected. Four severity levels are provided for presentation 
  9484. driver errors. The error levels are defined in Table 14-5. 
  9485.  
  9486. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9487. ΓöéSeverity              ΓöéDescription                   Γöé
  9488. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9489. ΓöéWarning               ΓöéA problem was detected but a  Γöé
  9490. Γöé                      Γöéworkaround was found.         Γöé
  9491. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9492. ΓöéError                 ΓöéA problem was found, but no   Γöé
  9493. Γöé                      Γöéworkaround was available.  TheΓöé
  9494. Γöé                      Γöésystem state remains intact.  Γöé
  9495. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9496. ΓöéSevere Error          ΓöéA problem occurred and the    Γöé
  9497. Γöé                      Γöésystem cannot reestablish its Γöé
  9498. Γöé                      Γöéstate.                        Γöé
  9499. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9500. ΓöéIrrecoverable Error   ΓöéAn error occurred and it is   Γöé
  9501. Γöé                      Γöéimpossible for the system to  Γöé
  9502. Γöé                      Γöéreestablish its state.  It is Γöé
  9503. Γöé                      Γöéalso impossible for the       Γöé
  9504. Γöé                      Γöéapplication to restore the    Γöé
  9505. Γöé                      Γöésystem to a known state.      Γöé
  9506. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9507. Table 14-5. Presentation driver errors. 
  9508.  
  9509.  
  9510. ΓòÉΓòÉΓòÉ 17.6. Presentation Driver Error Codes ΓòÉΓòÉΓòÉ
  9511.  
  9512. The presentation driver must call WinSetErrorInfo with the severity of the 
  9513. error and error code. Some of the general error codes are defined in Table 
  9514. 14-6. Refer to the Gre... function call reference in the IBM OS/2 Presentation 
  9515. Driver Reference for error codes specific to each Gre... function. 
  9516.  
  9517. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9518. ΓöéError                         ΓöéLogged by           Γöé
  9519. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9520. ΓöéPMERR_COORDINATE_OVERFLOW     Γöéfunctions requiring Γöé
  9521. Γöé                              Γöématrix computations Γöé
  9522. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9523. ΓöéPMERR_INSUFFICIENT_MEMORY     Γöéfunctions that      Γöé
  9524. Γöé                              Γöéallocate memory     Γöé
  9525. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9526. ΓöéPMERR_INV_BITMAP              Γöéfunctions with hbm  Γöé
  9527. Γöé                              Γöéas a parameter      Γöé
  9528. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9529. ΓöéPMERR_INV_HRGN                Γöéfunctions with hrgn Γöé
  9530. Γöé                              Γöéas a parameter      Γöé
  9531. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9532. ΓöéPMERR_INV_COORDINATE          Γöéfunctions with      Γöé
  9533. Γöé                              Γöécoordinates as      Γöé
  9534. Γöé                              Γöéparameters          Γöé
  9535. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9536. ΓöéPMERR_INV_IN_AREA             Γöéfunctions valid     Γöé
  9537. Γöé                              Γöéinside an open area Γöé
  9538. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9539. ΓöéPMERR_BASE_ERROR              Γöéfunctions that call Γöé
  9540. Γöé                              ΓöéDOS routines        Γöé
  9541. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9542. ΓöéPMERR_DEV_FUNC_NOT_INSTALLED  Γöéfunctions not       Γöé
  9543. Γöé                              Γöésupported by the    Γöé
  9544. Γöé                              Γöépresentation driver Γöé
  9545. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9546. Table 14-6. Presentation driver error codes. 
  9547.  
  9548.  
  9549. ΓòÉΓòÉΓòÉ 17.7. Additional Presentation Driver Functions ΓòÉΓòÉΓòÉ
  9550.  
  9551. Presentation drivers must also provide correlation to identify whether an 
  9552. object picked with the mouse, for example, lies within the pick aperture, and 
  9553. must consider if the object is visible or invisible. Hard-copy presentation 
  9554. drivers may need to support banding for raster technology hard-copy devices. 
  9555. Banding is technique where the output page is broken up into one or more bands, 
  9556. recorded in memory as a bitmap and sent to the device or the spooler. 
  9557.  
  9558. Hard-copy presentation drivers must work with back-level and forward-level 
  9559. drivers across a network. Hard-copy presentation drivers can also support 
  9560. output to a file. They must also provide the user with the following push 
  9561. buttons: 
  9562.  
  9563. o Retry (default position)
  9564.  
  9565. o Abort
  9566.  
  9567. o Ignore
  9568.  
  9569. The hard-copy presentation driver should respond as described in Table 14-7 to 
  9570. each of the returns. 
  9571.  
  9572. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9573. ΓöéReturn      ΓöéWhat the hard copy driver should do Γöé
  9574. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9575. ΓöéMBID_RETRY  Γöécontinue sending data to the output Γöé
  9576. Γöé            Γöébuffer                              Γöé
  9577. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9578. ΓöéMBID_ABORT  Γöéissue a PrtAbort to notify the      Γöé
  9579. Γöé            Γöéspooler to delete the current job.  Γöé
  9580. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9581. ΓöéMBID_IGNORE Γöécontinue sending data to the output Γöé
  9582. Γöé            Γöébuffer                              Γöé
  9583. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9584. Table 14-7. Job error returns. 
  9585.  
  9586. Examples of presentation drivers can be found in the sample code included with 
  9587. the IBM OS/2 2.1 Toolkit. Refer to the OS/2 2.1 Presentation Device Driver 
  9588. Reference and the toolkit documentation for more information on writing 
  9589. presentation drivers. 
  9590.  
  9591.  
  9592. ΓòÉΓòÉΓòÉ 18. Chapter 15 - Working With Pointers ΓòÉΓòÉΓòÉ
  9593.  
  9594. OS/2 2.1 exploits the flat memory model of the Intel 80x86 processors. This 
  9595. permits applications to be written using a 32-bit compiler and/or a 32-bit 
  9596. assembler. When the 32-bit application references a variable or function by 
  9597. reference, it uses a 32-bit linear or flat address. Applications written for 
  9598. OS/2 2.1 can be as large as 512MB, so it is likely that data items such as 
  9599. buffers and structures will cross 64KB tiled boundaries. This represents 
  9600. somewhat of a problem for driver writers, as the PDD is still operating in a 
  9601. 16-bit mode. Fortunately, OS/2 2.1 provides the necessary DevHlp routines to 
  9602. make it easier for the device driver to deal with these 32-bit applications. 
  9603.  
  9604.  
  9605. ΓòÉΓòÉΓòÉ 18.1. C Set/2 ΓòÉΓòÉΓòÉ
  9606.  
  9607. The C Set/2 compiler is a 32-bit flat model C compiler from IBM. The C Set/2 
  9608. compiler utilizes full 32-bit linear addressing and pointer manipulation. If 
  9609. the application that uses your 16-bit device driver is written in a 32-bit 
  9610. compiler such as C Set/2, there are some special considerations you should take 
  9611. into account. You should also know if your driver will be called by a 16-bit 
  9612. C/2 or Microsoft C 5.1/6.0 application. If you're not sure, you should assume 
  9613. the application is a 16-bit application, and design your driver to work with 
  9614. either 16-bit or 32-bit applications. However, if the application will be 
  9615. written in a 32- bit compiler such as C Set/2, the device driver can optimize 
  9616. performance by using 32-bit pointers. 
  9617.  
  9618. Applications written in MS C5.1/6.0 or IBM C/2 will require no changes when 
  9619. they are run on OS/2 2.1 and access your 16-bit PDD. Application pointers are 
  9620. 16-bit virtual addresses which can be used directly by the device drivers. 
  9621. However, a C Set/2 application is a 32-bit process, and pointers within the 
  9622. application are 32-bit linear addresses in the process address space. Linear 
  9623. addresses are special addresses which are decoded by special page decoding 
  9624. hardware to produce a 32-bit physical address. Your PDD, however, is a 16-bit 
  9625. program which must deal with the 32-bit addresses generated by the 32-bit 
  9626. compiler. 
  9627.  
  9628. When a 32-bit application calls the OS/2 kernel via a standard device driver 
  9629. request, the kernel converts the addresses contained in the request packet to 
  9630. 16:16 addresses. Thus, the PDD sees only 16:16 addresses, and has no direct 
  9631. knowledge if the application is a 16-bit or 32-bit process. The process of 
  9632. converting the pointers and/or addresses from 32-bit to 16-bit is called 
  9633. thunking. Conversely, pointers may be also converted from 16-bit to 32-bit by 
  9634. thunking. Thunking is accomplished by invoking the DosSelToFlat and 
  9635. DosFlatToSel macros. There is a performance penalty when you use thunks, 
  9636. however, so it is best to avoid thunking whenever possible. 
  9637.  
  9638. When your device driver receives a request packet for a DosRead or DosWrite, 
  9639. the caller's buffer address in the request packet is the 32-bit physical 
  9640. address of the caller's buffer. The conversion necessary to convert the 
  9641. caller's 32-bit linear address to a valid physical address has already been 
  9642. performed by the kernel. When your device driver is called via an IOCtl request 
  9643. from a 32-bit process, the caller's data and parameter buffer pointers are also 
  9644. converted from linear addresses to 16:16 virtual addresses. This is done 
  9645. automatically for you by the OS/2 kernel. 
  9646.  
  9647. If, however, you use the private IOCtl data or parameter buffers to pass the 
  9648. linear address from the process to the driver, the address is not thunked. This 
  9649. is because the data and parameter buffers in an IOCtl packet are private data 
  9650. areas shared by the process and the driver, so the kernel has no way to 
  9651. differentiate the address from a 32-bit data item. Before using linear 
  9652. addresses passed in this fashion, you must convert them to an address which the 
  9653. device driver can use. 
  9654.  
  9655. A 32-bit linear address, such as the address of a variable in a process, is 
  9656. said to be in the process address space, or mapped into the local descriptor 
  9657. table (LDT) of the process. Addresses within the process address space may be 
  9658. used freely by the application, providing it has the proper access rights. 
  9659. However, the address is not valid for a device driver. Since the device driver 
  9660. is operating in ring 0, it needs an address which is global, or mapped to a 
  9661. global descriptor table (GDT) entry. Pointers which are valid for the device 
  9662. driver are said to be in the global address space because they utilize a GDT 
  9663. selector for access. 
  9664.  
  9665. Sharing the pointers between the process and the device driver is easy. A 
  9666. linear address in the process address space can be made valid for the device 
  9667. driver by a call to the VMProcessToGlobal DevHlp function. Conversely, a linear 
  9668. address in the global address space can be made valid for the process by 
  9669. calling the VMGlobalToProcess DevHlp function. Thus, processes and device 
  9670. drivers can share each other's common memory areas. An example of this is shown 
  9671. in Example 15-1. 
  9672.  
  9673. // convert driver-relative address to a process address
  9674.  
  9675. if (VMGlobalToProcess(linaddr,0x1000,0x01,(FARPOINTER) &new_linaddr))
  9676.     return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  9677.  
  9678.  
  9679. // convert an application address to a global 32-bit address
  9680.  
  9681. if (VMProcessToGlobal(linaddr,0x1000,0x01,(FARPOINTER) &new_linaddr))
  9682.     return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  9683.  
  9684. Example 15-1. VMGlobalToProcess and VMProcessToGlobal 
  9685.  
  9686. Your driver may also allocate virtual memory with the VMAlloc DevHlp (see 
  9687. Example 15-2). VMAlloc will return a 32-bit linear address to the allocated 
  9688. memory. Depending on the flags parameter passed the VMAlloc, the 32-bit linear 
  9689. address returned will be in the process address range or the global address 
  9690. range.  Thus, a device driver may allocate a buffer and pass a 32-bit pointer 
  9691. to that buffer to the 32-bit process.  VMAlloc parameters can also specify that 
  9692. the memory to be allocated is above or below the 16MB line, and whether or not 
  9693. the memory is contiguous.  This is especially helpful for DMA buffers which for 
  9694. most clones, must be in the memory area under 16MB. 
  9695.  
  9696. // use VMAlloc to map the adapter address to a linear address in the
  9697. // global address space
  9698.  
  9699. ULONG   MapAddress  = 0xd8000;
  9700. LINADDR LinAddress  = 0;       // linear address to MapAddress
  9701. LINADDR dev_linaddr = 0;       // for global linear address
  9702.  
  9703. // VMalloc requires a linear address to the physical map address
  9704.  
  9705. VirtToLin((FARPOINTER)&MapAddress,(PLINADDR)&LinAddress);
  9706.  
  9707. if (VMAlloc(LinAddress,0x1000,0x30,(PLINADDR)&dev_linaddr))
  9708. {
  9709.   DosPutMessage(1, 2, CrLf);
  9710.   DosPutMessage(1, strlen(AllocFailMessage), AllocFailMessage);
  9711. }
  9712. else
  9713. {
  9714.   DosPutMessage(1, 2, CrLf);
  9715.   DosPutMessage(1, strlen(AllocPassMessage), AllocPassMessage);
  9716. }
  9717.  
  9718. Example 15-2. Using VMAlloc 
  9719.  
  9720.  
  9721. ΓòÉΓòÉΓòÉ 18.2. Virtual Addresses ΓòÉΓòÉΓòÉ
  9722.  
  9723. A 16:16 virtual address which has be mapped to a 32-bit linear address is 
  9724. called a tiled virtual address. It represents a selector/offset of the same 
  9725. physical address as defined by the 32-bit linear address. The normal addresses 
  9726. used in your device driver are 16:16 virtual addresses. Several DevHlp calls, 
  9727. such as VMLock and LinToPageList, require the addresses of parameters to be 
  9728. 32-bit linear addresses. If these data items or parameters exist in the 
  9729. driver's data segment, passing the pointer to these items will cause these 
  9730. DevHlps to fail. You must first convert the 16:16 virtual addresses to linear 
  9731. by calling VirtToLin, and then call the DevHlp function as shown in Example 
  9732. 15-3. 
  9733.  
  9734. Flags = 0x1a;
  9735.  
  9736. // first convert address arguements to linear
  9737.  
  9738. if (VirtToLin((FARPOINTER)PageList,(PLINADDR) &lPageList));
  9739.  
  9740. if (VirtToLin((FARPOINTER)LockHandle,(PLINADDR)&lLockHandle));
  9741.  
  9742. if (VMLock(linaddr,100,lPageList,lLockhandle,
  9743.     Flags,(FARPOINTER) &Elements))
  9744. {
  9745.    DosPutMessage(1, 2, CrLf);
  9746.    DosPutMessage(1, strlen(LockFailMessage), LockFailMessage);
  9747. }
  9748. else
  9749. {
  9750.   DosPutMessage(1, 2, CrLf);
  9751.   DosPutMessage(1, strlen(LockPassMessage), LockPassMessage);
  9752. }
  9753.  
  9754. Example 15-3. Calling VMLock 
  9755.  
  9756.  
  9757. ΓòÉΓòÉΓòÉ 18.3. Pointers In A VDM ΓòÉΓòÉΓòÉ
  9758.  
  9759. DOS applications running in a VDM utilize real mode addressing. A 20-bit real 
  9760. mode address in the segment:offset form can refer to a physical address within 
  9761. the VDM's one megabyte address space. If the VDM makes an IOCtl call to your 
  9762. device driver with pointers in the private data and/or parameter buffers, the 
  9763. driver must take an extra step to ensure the pointers are converted correctly. 
  9764. The driver checks the TypeProcess variable in the local info seg structure to 
  9765. determine of the application is a VDM application (bit 1 = 1). 
  9766.  
  9767. If it is a DOS application, the driver allocates a GDT selector and convert the 
  9768. segment:offset address to a VDM-relative physical address by shifting the 
  9769. segment left 4 bits and adding in the offset. This is the same way the physical 
  9770. address is calculated in real mode for a real-mode application. The driver then 
  9771. calls LinToGDTSelector with the 20-bit physical address of the VDM 
  9772. application's buffer and/or parameter address. This call maps the 20-bit 
  9773. physical address to the caller's address using a GDT selector which can be 
  9774. accessed at kernel or interrupt time. The selector should be released by a call 
  9775. to FreeGDTSelector when the driver is finished with it. It is important to note 
  9776. that normally, LinToGDTSelector requires a 32-bit linear address and not a 
  9777. 20-bit physical address. This is possible only because LinToGDTSelector can 
  9778. determine that the current process making the call is in a VDM. If 
  9779. LinToGDTSelector determines that the caller is a VDM application, it converts 
  9780. the 20-bit real address to a valid 32-bit linear address before mapping it to 
  9781. the GDT selector. 
  9782.  
  9783.  
  9784. ΓòÉΓòÉΓòÉ 19. Chapter 16 - PCMCIA Device Drivers ΓòÉΓòÉΓòÉ
  9785.  
  9786. The latest technology to affect OS/2 device drivers is called the Personal 
  9787. Computer Memory Card Interface Association, or PCMCIA, architecture. The PCMCIA 
  9788. is an organization of hardware and software vendors who are developing a set of 
  9789. standards for small, credit-card size adapters, dubbed PCMCIA cards. The PCMCIA 
  9790. has attempted to define both the hardware and software standards for the PCMCIA 
  9791. adapters, and the standards are still emerging. In order to support this new 
  9792. emerging technology, OS/2 2.1 has introduced support for the current PCMCIA 
  9793. standards. 
  9794.  
  9795. The information supplied here either exists or is planned, and is therefore 
  9796. subject to change. Since the PCMCIA specifications are still evolving, it is 
  9797. possible that some of the information presented in this chapter may not be 
  9798. accurate at the time of publication. In addition, OS/2 2.1 does not support, 
  9799. nor is it planned to support, the full implementation of the PCMCIA 2.00 
  9800. services. Future versions of OS/2 2.x may provide additonal support for PCMCIA 
  9801. services. Please refer to the latest publications from IBM for the most 
  9802. accurate description of the OS/2 2.1 PCMCIA support. 
  9803.  
  9804. At the time of this writing, the hardware specification outlines three 
  9805. different size PCMCIA adapters, although more may be added. The different 
  9806. sizes, or form factors, specify the thickness of the adapter. The current sizes 
  9807. defined by the PCMCIA specification are 3.3, 5, and 10 millimeters. The 
  9808. adapters are inserted into a PCMCIA slot (called a socket) with the power on. 
  9809. The adapter hardware must therefore accommodate inrush currents associated with 
  9810. power- on insertion. Although the PCMCIA adapter is usually inserted into a 
  9811. slot without latches or hardware restraints, the PCMCIA specification does not 
  9812. preclude such additional hardware. Up to 256 PCMCIA adapters can be installed 
  9813. on a system, and each adapter can have up to 16 sockets. PCMCIA adapters can be 
  9814. such things as RAM, flash RAM, hard disks, modems, LAN adapters, or any other 
  9815. device which can fit within the PCMCIA form factor. Whatever the size or type 
  9816. device, OS/2 regards the PCMCIA device as just another device, and is not aware 
  9817. of the PCMCIA architecture. 
  9818.  
  9819.  
  9820. ΓòÉΓòÉΓòÉ 19.1. The PCMCIA Software Trilogy ΓòÉΓòÉΓòÉ
  9821.  
  9822. The software specification outlines three major software components. The OS/2 
  9823. PDD that deals with the specific device characteristics is called the client. 
  9824. There must be a client for each adapter type, but the driver may handle 
  9825. multiple instances of the same adapter type. This is analogous to a device 
  9826. driver for a multiport serial adapter, which can handle each port with the same 
  9827. driver. The client driver is usually supplied by the PCMCIA card vendor, 
  9828. although its possible that generalized OS/2 PCMCIA drivers will be available 
  9829. from other sources. The client driver may also have a VDD counterpart for 
  9830. operation in a VDM. 
  9831.  
  9832. The second part of the PCMCIA software architecture is called card services. 
  9833. Card services is responsible for providing the client an interface to the 
  9834. operating system In OS/2 2.1, card services is implemented as a ring 0 PDD, 
  9835. called PCMCIA$. The PCMCIA client performs an AttachDD DevHlp to PCMCIA$, which 
  9836. yields a 16:16 pointer to the PCMCIA$ device driver's IDC entry point. 
  9837. Subsequent calls to card services are performed by setting up the proper 
  9838. registers and calling the IDC entry point from the client. Since card services 
  9839. needs hooks into OS/2, card services is supplied by IBM. 
  9840.  
  9841. Card services, like the DevHlp routines, are register-based, so in order to 
  9842. write your PCMCIA driver in C, you'll need to provide a library of C callable 
  9843. functions similar to the DevHlp library. The optional PDD driver library (see 
  9844. order form at the end of this book) contains the C callable routines for the 
  9845. PCMCIA card services, allowing you to write your PCMCIA drivers in C. 
  9846.  
  9847. The third component of the PCMCIA software is socket services. Socket services 
  9848. is a hardware-specific layer of software which isolates the socket specific 
  9849. architecture from the other the software components. It is expected that the 
  9850. supplier of the system will supply this driver in software form or in the BIOS. 
  9851. The simplified architecture is shown in Example 16-1. It should be noted, 
  9852. however, that the PCMCIA specification allows the client to perform direct I/O 
  9853. and memory-mapped operation with the adapter, avoiding the card services or 
  9854. socket services layer. 
  9855.  
  9856. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  9857. ΓöéClient PDD          Γöé
  9858. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9859. ΓöéCard Services       Γöé
  9860. ΓöéPCMCIA$             Γöé
  9861. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9862. ΓöéSocket Services PDD Γöé
  9863. Γöéor BIOS             Γöé
  9864. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  9865. ΓöéPCMCIA Adapter      Γöé
  9866. ΓöéHardware            Γöé
  9867. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  9868.  
  9869. Example 16-1. PCMCIA software architecture. 
  9870.  
  9871.  
  9872. ΓòÉΓòÉΓòÉ 19.2. OS/2 2.1 PCMCIA Initialization ΓòÉΓòÉΓòÉ
  9873.  
  9874. The first component loaded in CONFIG.SYS is the card services PDD. The card 
  9875. services PDD assumes that the following system resources are available: 
  9876.  
  9877. o Non-system memory from C0000h to DFFFFh
  9878.  
  9879. o IRQ 2-15
  9880.  
  9881. o I/O ports 0x108-0xffff, except 0x3b4, 0x3b5, 0x3bah, ox3bbh, 3c0-3dfh,
  9882.  and  3f0-3f7h.
  9883.  
  9884. These are the default resources that card services expects to be available. To 
  9885. determine what is actually available, another PDD, called the Resource Map 
  9886. Utility or RMU, is loaded from CONFIG.SYS. When the RMU receives the 
  9887. CMDInitComplete strategy command, the RMU pokes around the system and verifies 
  9888. the actual resources available, opens the card services driver PCMCIA$, and 
  9889. calls the card services driver with the AdjustResourceInfo function. The card 
  9890. services PDD then adjusts the information on the available resources so it can 
  9891. more intelligently respond to a subsequent client request for those resources. 
  9892. It is important to note that the RMU driver has the special bit (bit 4) in the 
  9893. capabilities bit strip word set, informing the kernel to call it with the 
  9894. InitComplete strategy command. It is also important to note that if no RMU is 
  9895. loaded, or the RMU fails to call the card services driver, that the card 
  9896. services driver will assume that all the default resources are available. 
  9897.  
  9898. Next, the socket services driver is loaded, and when processing the 
  9899. InitComplete strategy command, the socket services driver calls DevHlp AttachDD 
  9900. with PCMCIA$, which returns a 16:16 pointer to the PCMCIA$ driver's IDC entry 
  9901. point. It then calls the card services AddSocketServices to establish 
  9902. bidirectional communications with card services. When card services receives 
  9903. the socket services AddSocketServices request, it must: 
  9904.  
  9905. o identify the socket services resources required by calling socket services
  9906.  GetSetSSAddr, GetSSInfo, InquireAdapter, GetAdapter, InquireSocket and
  9907.  GetSocket. The socket services are provided by the socket service PDD when
  9908.  the card services driver calls the socket service driver's IDC entry point.
  9909.  
  9910. o allocate resources, if necessary, from the current resource map.
  9911.  
  9912. o install any necessary client interrupt handlers by calling DevHlp SetIRQ.
  9913.  
  9914. o program socket service hardware with SetAdapter and SetSocket socket
  9915.  services.
  9916.  
  9917. Next, the client PDD is loaded to support the particular adapter. The client 
  9918. establishes communications with card services by calling the AttachDD DevHlp 
  9919. during InitComplete processing. It is possible that the AttachDD call might 
  9920. fail in the case that the card services driver is not yet loaded (out of proper 
  9921. sequence in CONFIG.SYS). In this case, the client driver should enter a dormant 
  9922. state, waiting for the card services driver to be loaded. When the client 
  9923. driver detects that the card services driver is loaded, it issues a 
  9924. RegisterClient request and commences normal operation. 
  9925.  
  9926. Note that the sequence these drivers appear in CONFIG.SYS will determine if 
  9927. processing occurs normally. Therefore, each driver should be sensitive to that 
  9928. fact and execute accordingly. The card services driver must be loaded first, 
  9929. but the other drivers may appear out of sequence. Note also that the 
  9930. CMDInitComplete strategy command is issued in the reverse order of the way they 
  9931. appear in CONFIG.SYS. 
  9932.  
  9933.  
  9934. ΓòÉΓòÉΓòÉ 19.3. Client Device Driver Architecture ΓòÉΓòÉΓòÉ
  9935.  
  9936. The client driver is a normal OS/2 PDD, but contains additional resource 
  9937. allocation logic not usually found in a PDD. First, since the client driver 
  9938. exports its entry points, those entry points must never move or be relocated. 
  9939. This means all of the exported entry points must exist in the first 64KB code 
  9940. segment. This segment must also contain the strategy, interrupt, timer, and IDC 
  9941. entry points. Second, although a normal PDD allocates resources using the 
  9942. device helper routines, the client PDD allocates its resources by calling the 
  9943. card services driver. Since the client driver is activated only be an inserted 
  9944. card or insertion event, it should not allocate extra memory or resources until 
  9945. the card is actually detected. 
  9946.  
  9947. When the user inserts a card into a PCMCIA slot, the card services interrupt 
  9948. handler is called to signal the insertion. The card services driver 
  9949. acknowledges the card insertion interrupt by calling the socket services driver 
  9950. with the AcknowledgeInterrupt function, which returns the identification of the 
  9951. socket that caused the interrupt. The card services driver sets up a timer 
  9952. handler to handle the card insertion event. 
  9953.  
  9954. The timer handler calls the socket services driver's GetStatus, GetSocket, and 
  9955. SetSocket functions to determine the cause of the interrupt. The timer handler 
  9956. then calls each client that has previously registered for a card insertion 
  9957. event for that particular socket. 
  9958.  
  9959. The client processes the card insertion event by calling the card services 
  9960. function GetConfigurationInfo to determine if the card was previously claimed 
  9961. by another client driver. The client may get more detailed information from the 
  9962. card by calling the card service tuple functions GetFirstTuple, GetNextTuple, 
  9963. and GetTupleData. If the card cannot be supported by the client, the client 
  9964. just returns. If the card can be supported, the client calls the card services 
  9965. functions RequestIO and RequestConfiguration to allocate the resources. The 
  9966. card services driver then calls the socket services SetSocket function to 
  9967. program the card for the proper configuration. The client then calls the SetIRQ 
  9968. DevHlp routine to hook its interrupt handler like a normal PDD. 
  9969.  
  9970. Under normal operation, the client driver processes requests like any other 
  9971. PDD. 
  9972.  
  9973. When the PCMCIA card is removed, the card causes a status change interrupt to 
  9974. the card services driver. Card services calls the socket services driver's 
  9975. AcknowledgeInterrupt function to get the socket that generated the interrupt. 
  9976. The card services driver then sets up a timer handler like it did in the card 
  9977. insertion event. 
  9978.  
  9979. When the timer handler is entered, it processes the interrupt by calling the 
  9980. socket service GetStatus, GetSocket, and SetSocket function to determine the 
  9981. cause of the interrupt. The timer handler then calls all the clients that have 
  9982. registered for the particular socket. 
  9983.  
  9984. The client drivers process the event by calling the card services 
  9985. ReleaseConfiguration, ReleaseIO, and ReleaseIRQ functions. When the card 
  9986. services driver receives the ReleaseConfiguration command, it calls socket 
  9987. services to reprogram the card to stop generating interrupts or other events. 
  9988.  
  9989. If the client previously claimed a system interrupt with a SetIRQ call, the 
  9990. must call UnSetIRQ to give back to interrupt to OS/2. 
  9991.  
  9992. OS/2 2.1 Restrictions 
  9993.  
  9994. The OS/2 2.1 card services driver contains the following restrictions: 
  9995.  
  9996. o a maximum of 4 adapters
  9997.  
  9998. o a maximum of 8 sockets
  9999.  
  10000. o a maximum of 16 clients
  10001.  
  10002. o a maximum of 4 socket services drivers
  10003.  
  10004. o a maximum of 16 Memory Technology Drivers (MTDs)
  10005.  
  10006. o a maximum of 16 memory handles
  10007.  
  10008. o a maximum of 16 erase queues
  10009.  
  10010. o a maximum of 16 memory regions
  10011.  
  10012. o a maximum of 16 disk partitions
  10013.  
  10014. o a maximum of 7 memory windows (5 memory and 2 I/O)
  10015.  
  10016. In addition, card services provides no power management support or write 
  10017. protection. For PCMCIA disk drivers, the following restrictions apply: 
  10018.  
  10019. o the client must claim all the logical drives it supports, even if the DASD
  10020. card  is not currently inserted
  10021.  
  10022. o disks with multiple partitions must have a driver letter assigned to each
  10023.  partition
  10024.  
  10025. o PCMCIA disk cards do not support HPFS or disk caching
  10026.  
  10027. Card Services Functions 
  10028.  
  10029. Card services provides for the following client services: 
  10030.  
  10031. o function
  10032.  
  10033. o callbacks
  10034.  
  10035. o events
  10036.  
  10037. o MTD helpers
  10038.  
  10039. o media access routines
  10040.  
  10041. o return code information
  10042.  
  10043. The OS/2 PCMCIA implementation also has reserved IOCtl category 13 for a PCMCIA 
  10044. application interface. OS/2 2.1 supports or is planned to support the card 
  10045. services functions shown in Table 16-1. 
  10046.  
  10047. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  10048. ΓöéFunction                      ΓöéCode      Γöé
  10049. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10050. ΓöéCloseMemory                   Γöé0x01      Γöé
  10051. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10052. ΓöéDeregisterClient              Γöé0x02      Γöé
  10053. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10054. ΓöéGetClientInfo                 Γöé0x03      Γöé
  10055. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10056. ΓöéGetConfigurationInfo          Γöé0x04      Γöé
  10057. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10058. ΓöéGetFirstPartition             Γöé0x05      Γöé
  10059. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10060. ΓöéGetFirstRegion                Γöé0x06      Γöé
  10061. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10062. ΓöéGetFirstTuple                 Γöé0x07      Γöé
  10063. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10064. ΓöéGetNextPartition              Γöé0x08      Γöé
  10065. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10066. ΓöéGetNextRegion                 Γöé0x09      Γöé
  10067. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10068. ΓöéGetNextTuple                  Γöé0x0a      Γöé
  10069. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10070. ΓöéGetCardServicesInfo           Γöé0x0b      Γöé
  10071. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10072. ΓöéGetStatus                     Γöé0x0c      Γöé
  10073. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10074. ΓöéGetTupleData                  Γöé0c0d      Γöé
  10075. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10076. ΓöéGetFirstClient                Γöé0x0e      Γöé
  10077. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10078. ΓöéRegisterEraseQueue            Γöé0x0f      Γöé
  10079. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10080. ΓöéRegisterClient                Γöé0x10      Γöé
  10081. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10082. ΓöéResetCard                     Γöé0x11      Γöé
  10083. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10084. ΓöéMapLogSocket                  Γöé0x12      Γöé
  10085. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10086. ΓöéMapLogWindow                  Γöé0x13      Γöé
  10087. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10088. ΓöéMapMemPage                    Γöé0x14      Γöé
  10089. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10090. ΓöéMapPhySocket                  Γöé0x15      Γöé
  10091. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10092. ΓöéMapPhyWindow                  Γöé0x16      Γöé
  10093. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10094. ΓöéModifyWindow                  Γöé0x17      Γöé
  10095. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10096. ΓöéOpenMemory                    Γöé0x18      Γöé
  10097. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10098. ΓöéReadMemory                    Γöé0x19      Γöé
  10099. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10100. ΓöéRegisterMTD                   Γöé0x1a      Γöé
  10101. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10102. ΓöéReleaseIO                     Γöé0x1b      Γöé
  10103. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10104. ΓöéReleaseIRQ                    Γöé0x1c      Γöé
  10105. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10106. ΓöéReleaseWindow                 Γöé0x1d      Γöé
  10107. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10108. ΓöéReleaseConfiguration          Γöé0x1e      Γöé
  10109. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10110. ΓöéRequestIO                     Γöé0x1f      Γöé
  10111. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10112. ΓöéRequestIRQ                    Γöé0x20      Γöé
  10113. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10114. ΓöéRequestWindow                 Γöé0x21      Γöé
  10115. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10116. ΓöéRequestSocketMask             Γöé0x22      Γöé
  10117. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10118. ΓöéReturnSSEntry                 Γöé0x23      Γöé
  10119. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10120. ΓöéWriteMemory                   Γöé0x24      Γöé
  10121. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10122. ΓöéCheckEraseQueue               Γöé0x26      Γöé
  10123. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10124. ΓöéModifyConfiguration           Γöé0x27      Γöé
  10125. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10126. ΓöéSetRegion                     Γöé0x29      Γöé
  10127. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10128. ΓöéGetNextClient                 Γöé0x2a      Γöé
  10129. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10130. ΓöéValidateCIS                   Γöé0x2b      Γöé
  10131. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10132. ΓöéRequestExclusive              Γöé0x2c      Γöé
  10133. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10134. ΓöéReleaseExclusive              Γöé0x2d      Γöé
  10135. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10136. ΓöéGetEventMask                  Γöé0x2e      Γöé
  10137. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10138. ΓöéReleaseSocketMask             Γöé0x2f      Γöé
  10139. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10140. ΓöéRequestConfiguration          Γöé0x30      Γöé
  10141. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10142. ΓöéSetEventMask                  Γöé0x31      Γöé
  10143. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10144. ΓöéAddSocketServices             Γöé0x32      Γöé
  10145. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10146. ΓöéReplaceSocketServices         Γöé0x33      Γöé
  10147. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10148. ΓöéAdjustResourceInfo            Γöé0x35      Γöé
  10149. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  10150. Table 16-1. OS/2 PCMCIA Card Services. 
  10151.  
  10152.  
  10153. ΓòÉΓòÉΓòÉ 19.4. Calling Card Services ΓòÉΓòÉΓòÉ
  10154.  
  10155. Card services, like the OS/2 DevHlps, are register-based. The current registers 
  10156. assigned to these functions under OS/2 2.1 are shown in Tables 16-2 and 16-3. 
  10157.  
  10158. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  10159. ΓöéRegister    ΓöéContents                      Γöé
  10160. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10161. ΓöéAL          Γöéfunction number               Γöé
  10162. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10163. ΓöéAH          Γöéset to AFh                    Γöé
  10164. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10165. ΓöéDX          Γöéhandle                        Γöé
  10166. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10167. ΓöéDI          Γöépointer                       Γöé
  10168. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10169. ΓöéES          Γöéarg pointer                   Γöé
  10170. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10171. ΓöéCX          Γöéarg length                    Γöé
  10172. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  10173. Table 16-2. Card Services register interface (input). 
  10174.  
  10175. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  10176. ΓöéRegister    ΓöéContents                      Γöé
  10177. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10178. ΓöéAX          Γöéstatus argument               Γöé
  10179. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10180. ΓöéCF          Γöépass/fail carry flag          Γöé
  10181. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  10182. Table 16-3. Card Services register interface (output). 
  10183.  
  10184. All addresses must be in 16:16 form, and the caller must set DS to the DS value 
  10185. returned from the AttachDD call before calling card services. Card services are 
  10186. not reentrant, so a function request may be returned BUSY. 
  10187.  
  10188.  
  10189. ΓòÉΓòÉΓòÉ 19.5. Callbacks ΓòÉΓòÉΓòÉ
  10190.  
  10191. Client device drivers can be called by card services when certain events occur. 
  10192. The action of calling the client device driver from card services is called a 
  10193. callback. The callbacks that are supported or planned to be supported by OS/2 
  10194. 2.1 are described in Table 16-4. 
  10195.  
  10196. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  10197. ΓöéFunction                      ΓöéFunction  Γöé
  10198. Γöé                              ΓöéCode      Γöé
  10199. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10200. ΓöéBATTERY_DEAD                  Γöé0x01      Γöé
  10201. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10202. ΓöéBATTERY_LOW                   Γöé0x02      Γöé
  10203. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10204. ΓöéCARD_LOCK                     Γöé0x03      Γöé
  10205. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10206. ΓöéCARD_READY                    Γöé0x04      Γöé
  10207. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10208. ΓöéCARD_REMOVAL                  Γöé0x05      Γöé
  10209. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10210. ΓöéCARD_UNLOCK                   Γöé0x06      Γöé
  10211. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10212. ΓöéEJECTION_COMPLETE             Γöé0x07      Γöé
  10213. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10214. ΓöéEJECTION_REQUEST              Γöé0x08      Γöé
  10215. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10216. ΓöéINSERTION_COMPLETE            Γöé0x09      Γöé
  10217. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10218. ΓöéINSERTION_REQUEST             Γöé0x0a      Γöé
  10219. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10220. ΓöéEXCLUSIVE_COMPLETE            Γöé0x0d      Γöé
  10221. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10222. ΓöéEXCLUSIVE_REQUEST             Γöé0x0e      Γöé
  10223. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10224. ΓöéRESET_PHYSICAL                Γöé0x0f      Γöé
  10225. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10226. ΓöéRESET_REQUEST                 Γöé0x10      Γöé
  10227. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10228. ΓöéCARD_RESET                    Γöé0x11      Γöé
  10229. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10230. ΓöéMTD_REQUEST                   Γöé0x12      Γöé
  10231. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10232. ΓöéCLIENT_INFO                   Γöé0x14      Γöé
  10233. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10234. ΓöéSS_UPDATED                    Γöé0x16      Γöé
  10235. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10236. ΓöéCARD_INSERTION                Γöé0x40      Γöé
  10237. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10238. ΓöéRESET_COMPLETE                Γöé0x80      Γöé
  10239. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10240. ΓöéERASE_COMPLETE                Γöé0x81      Γöé
  10241. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10242. ΓöéREGISTRATION_COMPLETE         Γöé0x82      Γöé
  10243. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  10244. Table 16-4. OS/2 callbacks. 
  10245.  
  10246. The callback interface is described in Tables 16-5 and 16-6. The ClientData 
  10247. structure is shown in Example 16-2. 
  10248.  
  10249. #typedef struct _ClientData
  10250. {
  10251.   USHORT  ClientVal; // client specific data value
  10252.   USHORT  ClientDS;  // clients DS value
  10253.   USHORT  ClientOff  // client's callback offset
  10254.   USHORT  Reserved   // for future use
  10255. } ClientData;
  10256.  
  10257. Example 16-2. ClientData structure. 
  10258.  
  10259.  
  10260. ΓòÉΓòÉΓòÉ 20. Chapter 17 - Tips and Techniques ΓòÉΓòÉΓòÉ
  10261.  
  10262. I get a large number of questions from driver writers on how to perform certain 
  10263. driver-related tasks. This chapter outlines some of the things you might want 
  10264. to do in your device driver. Some of these may seem apparent, but to my 
  10265. knowledge, this information does not appear anywhere else. 
  10266.  
  10267. Q. I have an application that allocates a local buffer which is semaphore 
  10268. protected for access by several threads.  I want the driver to send data to 
  10269. this buffer from my interrupt handler, but I don't want to keep calling the 
  10270. device driver.  How can I do this? 
  10271.  
  10272. A. The application sends the device driver, via an IOCtl, the address of the 
  10273. buffer.  The device driver calls VMProcessToGlobal to get a pointer to the 
  10274. buffer, and VMLock to lock the buffer.  The driver then calls LinToGDTSelector 
  10275. to gain GDT access to the buffer.  The device driver calls VMLock to prevent 
  10276. the buffer from being paged.  The driver then transfers data freely from the 
  10277. interrupt handler. 
  10278.  
  10279. Q. How can I get control of the floppy disk controller registers to support an 
  10280. add-on tape drive that uses the floppy disk controller? 
  10281.  
  10282. A. Call IOCtl Category 8, function 0x5d.  This function toggles the floppy disk 
  10283. driver and Sets/UnSets the floppy IRQ. 
  10284.  
  10285. Q. My company sells ISA bus adapters which can be jumpered to one of several 
  10286. memory-mapped addresses.  I only want to supply one device driver.  How can I 
  10287. dynamically configure the device driver for the particular system? 
  10288.  
  10289. A. Place the configuration information on the same line as the DEVICE= 
  10290. statement in the CONFIG.SYS file.  During initialization, the kernel sends the 
  10291. driver a 16:16 virtual address of the DEVICE= command buffer. The driver can 
  10292. use this pointer to parse driver-specific information and use it to configure 
  10293. the device driver.  For instance, the CONFIG.SYS file entry might contain 
  10294. DEVICE=MYDRIVER.SYS d8000 3e8 5, where d8000 is the memory- mapped address, 3e8 
  10295. is the base port address, and 5 is the IRQ. 
  10296.  
  10297. Q. My company supplies an ISA and Micro Channel version of the same adapter. 
  10298. How can I tell if the machine contains an ISA bus or Micro Channel bus, and can 
  10299. I use the same device driver for both systems? 
  10300.  
  10301. A. Using the same driver for ISA and Micro Channel machines is a common 
  10302. occurrence.  The first thing your device driver should do is determine the bus 
  10303. type.  You can do this by calling GetLIDEntry, requesting a POS LID. If the 
  10304. call fails, its not a Micro Channel machine.  If the call succeeds, the system 
  10305. is Micro Channel-based.  You can then take the appropriate action.  For Micro 
  10306. Channel, scan the planar for your target adapter ID, and call SetIRQ with the 
  10307. share flag to verify your interrupt level.  For ISA bus systems, call SetIRQ 
  10308. with the no- share flag. 
  10309.  
  10310. Q. How can I reboot my machine from the command line? 
  10311.  
  10312. A. Write a simple device driver that calls the SendEvent DevHlp with the 
  10313. parameter to reboot for IOCtl function 1. Then write an application that calls 
  10314. the IOCtl. 
  10315.  
  10316. Q. My driver needs to identify the caller and determine its PID.  How can I do 
  10317. this? 
  10318.  
  10319. A. From your driver, call GetDOSVar, which returns a pointer to the 
  10320. application's local infoseg.  Using that pointer, you can extract the necessary 
  10321. information. 
  10322.  
  10323. Q. My Micro Channel initialization section is setting up the wrong memory- 
  10324. mapped address from the POS registers.  How can I check the value of the POS 
  10325. registers while debugging? 
  10326.  
  10327. A. First, you must know what slot the particular adapter is in. The slots are 
  10328. number 0-7, with 0 being the motherboard, and 1-7 the 8 slots on the 
  10329. motherboard.  Slot 1 is the slot closest to the power supply.  Once the slot 
  10330. number is known, turn on the -CD SETUP line for that slot using the debugger, 
  10331. by issuing the command o 96,slot'1.  If the adapter was located in slot 2, the 
  10332. command would be o 96,3.  Once enabled, the adapter POS register contents can 
  10333. be read by an input of address 0x100, 0x101, 0x102, etc.  The adapter ID is 
  10334. located in POS register 0 and 1, located at 0x100 and 0x101, in the low-high 
  10335. format.  To make the POS registers invisible again and bring the system back to 
  10336. normal, issue the o 96,0 command. 
  10337.  
  10338. Q. I need to change the contents of the adapter POS registers while my driver 
  10339. is running.  How can I read or write the Micro Channel POS registers "on the 
  10340. fly" with my device driver? 
  10341.  
  10342. A. Call GetLIDEntry to get a POS LID.  Next, get the size of the LID Request 
  10343. Block by calling ABIOSCall.  Initialize the Request Block for the request and 
  10344. call ABIOSCall.  The ABIOS routines will fill in the Request Block with the POS 
  10345. register data.  Change the data and Request Block command field and call 
  10346. ABIOScall again to write the data.  Remember that the POS register information 
  10347. is kept in two places.  The first is the adapter itself, and the second is the 
  10348. motherboard's NVRAM.  When the POST is run on power-up, the system compares the 
  10349. NVRAM configuration with the actual POS register configuration to determine if 
  10350. an adapter was reconsidered or removed.  If you're going to make the POS 
  10351. register change permanent, be sure to write to both places. 
  10352.  
  10353. Q. My adapter requires a program be downloaded to it during Init.  How can I 
  10354. get access to my adapter's memory during Init, and how can I download the 
  10355. program to the adapter? 
  10356.  
  10357. A. To access the adapter during Init, you'll need to create LDT access, since 
  10358. Init is a ring 3 thread.  Call PhysToUVirt to get a selector to the adapter 
  10359. memory.  Then call DosOpen and DosRead to read the adapter's program from a 
  10360. binary file, and move it to the adapter using the pointer from the PhysToUVirt 
  10361. call. 
  10362.  
  10363. Q. I need to delay for 5 seconds during the Init of my driver so my adapter can 
  10364. get set up.  I can't call DosSleep, so how can I do this? 
  10365.  
  10366. A. Call the Beep DevHlp with a duration of 5 seconds, and a frequency out of 
  10367. the audible range. 
  10368.  
  10369. Q. How can I return specific errors from my driver? 
  10370.  
  10371. A. If you return an error via one of the standard driver calls, the system adds 
  10372. a hex 13 to the value.  If you use an IOCtl, the lower 8 bits are your's to set 
  10373. as you please.  The system will not touch the value.  The error code returned 
  10374. to your program will have 0xff in the upper 8 bits.  Thus, returning a 0x14 
  10375. from an IOCtl will yield a 0xff14 at the application level. 
  10376.  
  10377. Q. When my driver times out, I get a coffin on my screen. How can I suppress 
  10378. this? 
  10379.  
  10380. A. Be sure to set the OPEN_FLAGS_FAIL_ON_ERROR bit in the DosOpen call. 
  10381.  
  10382.  
  10383. ΓòÉΓòÉΓòÉ 21. Appendix A - Device Helper Reference ΓòÉΓòÉΓòÉ
  10384.  
  10385. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  10386. ΓöéDevHlp Function     ΓöéCode      ΓöéDescription                 Γöé
  10387. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10388. ΓöéSchedClockAddr      Γöé00        ΓöéGet system clock routine    Γöé
  10389. Γöé                    Γöé          Γöéaddress                     Γöé
  10390. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10391. ΓöéDevDone             Γöé01        ΓöéDevice I/O complete         Γöé
  10392. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10393. ΓöéYield               Γöé02        ΓöéYield the CPU               Γöé
  10394. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10395. ΓöéTCYield             Γöé03        ΓöéYield the CPU to a          Γöé
  10396. Γöé                    Γöé          Γöétime-critical thread        Γöé
  10397. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10398. ΓöéBlock               Γöé04        ΓöéBlock thread on event       Γöé
  10399. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10400. ΓöéRun                 Γöé05        ΓöéUnBlock a previously BlockedΓöé
  10401. Γöé                    Γöé          Γöéthread                      Γöé
  10402. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10403. ΓöéSemRequest          Γöé06        ΓöéClaim a semaphore           Γöé
  10404. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10405. ΓöéSemClear            Γöé07        ΓöéRelease a semaphore         Γöé
  10406. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10407. ΓöéSemHandle           Γöé08        ΓöéGet a semaphore handle      Γöé
  10408. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10409. ΓöéPushReqPacket       Γöé09        ΓöéAdd a Request Packet to listΓöé
  10410. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10411. ΓöéPullReqPacket       Γöé0a        ΓöéRemove a Request Packet fromΓöé
  10412. Γöé                    Γöé          Γöélist                        Γöé
  10413. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10414. ΓöéPullParticular      Γöé0b        ΓöéRemove a specific Request   Γöé
  10415. Γöé                    Γöé          ΓöéPacket from list            Γöé
  10416. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10417. ΓöéSortReqPacket       Γöé0c        ΓöéSort Request Packets        Γöé
  10418. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10419. ΓöéAllocReqPacket      Γöé0d        ΓöéAllocate a Request Packet   Γöé
  10420. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10421. ΓöéFreeReqPacket       Γöé0e        ΓöéFree a Request Packet       Γöé
  10422. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10423. ΓöéQueueInit           Γöé0f        ΓöéInitialize a character queueΓöé
  10424. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10425. ΓöéQueueFlush          Γöé10        ΓöéClear a character queue     Γöé
  10426. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10427. ΓöéQueueWrite          Γöé11        ΓöéPut a character in the queueΓöé
  10428. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10429. ΓöéQueueRead           Γöé12        ΓöéGet a character from the    Γöé
  10430. Γöé                    Γöé          Γöéqueue                       Γöé
  10431. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10432. ΓöéLock                Γöé13        ΓöéLock segment                Γöé
  10433. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10434. ΓöéUnlock              Γöé14        ΓöéUnlock segment              Γöé
  10435. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10436. ΓöéPhysToVirt          Γöé15        ΓöéMap physical to virtual     Γöé
  10437. Γöé                    Γöé          Γöéaddress                     Γöé
  10438. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10439. ΓöéVirtToPhys          Γöé16        ΓöéMap virtual to physical     Γöé
  10440. Γöé                    Γöé          Γöéaddress                     Γöé
  10441. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10442. ΓöéPhysToUVirt         Γöé17        ΓöéMap physical address to userΓöé
  10443. Γöé                    Γöé          Γöévirtual address             Γöé
  10444. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10445. ΓöéAllocPhys           Γöé18        ΓöéAllocate physical memory    Γöé
  10446. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10447. ΓöéFreePhys            Γöé19        ΓöéFree physical memory        Γöé
  10448. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10449. ΓöéSetIRQ              Γöé1b        ΓöéAttach a hardware interrupt Γöé
  10450. Γöé                    Γöé          Γöéhandler                     Γöé
  10451. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10452. ΓöéUnSetIRQ            Γöé1c        ΓöéDetach a hardware interrupt Γöé
  10453. Γöé                    Γöé          Γöéhandler                     Γöé
  10454. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10455. ΓöéSetTimer            Γöé1d        ΓöéAttach a timer handler      Γöé
  10456. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10457. ΓöéResetTimer          Γöé1e        ΓöéDetach a timer handler      Γöé
  10458. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10459. ΓöéMonitorCreate       Γöé1f        ΓöéCreate a device monitor     Γöé
  10460. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10461. ΓöéRegister            Γöé20        ΓöéInstall a device monitor    Γöé
  10462. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10463. ΓöéDeRegister          Γöé21        ΓöéRemove a device monitor     Γöé
  10464. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10465. ΓöéMonWrite            Γöé22        ΓöéPass data records to a      Γöé
  10466. Γöé                    Γöé          Γöédevice monitor              Γöé
  10467. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10468. ΓöéMonFlush            Γöé23        ΓöéRemove all data from device Γöé
  10469. Γöé                    Γöé          Γöémonitor stream              Γöé
  10470. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10471. ΓöéGetDOSVar           Γöé24        ΓöéReturn a pointer to DOS     Γöé
  10472. Γöé                    Γöé          Γöévariable                    Γöé
  10473. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10474. ΓöéSendEvent           Γöé25        ΓöéIndicate an event           Γöé
  10475. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10476. ΓöéVerifyAccess        Γöé27        ΓöéVerify Memory Access        Γöé
  10477. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10478. ΓöéABIOSGetParms       Γöé29        ΓöéGet ABIOS parameters for LIDΓöé
  10479. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10480. ΓöéAttachDD            Γöé2a        ΓöéEstablish communications    Γöé
  10481. Γöé                    Γöé          Γöéwith another Physical DeviceΓöé
  10482. Γöé                    Γöé          ΓöéDriver                      Γöé
  10483. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10484. ΓöéInternalError       Γöé2a        ΓöéSignal an internal error    Γöé
  10485. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10486. ΓöéAllocGDTSelector    Γöé2d        ΓöéAllocate GDT Descriptors    Γöé
  10487. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10488. ΓöéPhysToGDTSelector   Γöé2e        ΓöéMap physical address to GDT Γöé
  10489. Γöé                    Γöé          Γöévirtual                     Γöé
  10490. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10491. ΓöéEOI                 Γöé31        ΓöéIssue an end-of-interrupt toΓöé
  10492. Γöé                    Γöé          Γöéthe PIC                     Γöé
  10493. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10494. ΓöéUnPhysToVirt        Γöé32        ΓöéMark physical to virtual    Γöé
  10495. Γöé                    Γöé          Γöécomplete                    Γöé
  10496. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10497. ΓöéTickCount           Γöé33        ΓöéModify/Create timer setting Γöé
  10498. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10499. ΓöéGetLIDEntry         Γöé34        ΓöéGet a Logical ID  (PS/2     Γöé
  10500. Γöé                    Γöé          Γöéonly)                       Γöé
  10501. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10502. ΓöéFreeLIDEntry        Γöé35        ΓöéRelease a Logical ID  (PS/2 Γöé
  10503. Γöé                    Γöé          Γöéonly)                       Γöé
  10504. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10505. ΓöéABIOSCall           Γöé36        ΓöéInvoke an ABIOS function    Γöé
  10506. Γöé                    Γöé          Γöé(PS/2 only)                 Γöé
  10507. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10508. ΓöéABIOSCommonEntry    Γöé37        ΓöéInvoke an ABIOS Common EntryΓöé
  10509. Γöé                    Γöé          ΓöéPoint (PS/2 only)           Γöé
  10510. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10511. ΓöéGetDeviceBlock      Γöé38        ΓöéGet ABIOS Device Block (PS/2Γöé
  10512. Γöé                    Γöé          Γöéonly)                       Γöé
  10513. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10514. ΓöéRegisterStackUsage  Γöé3a        ΓöéIndicate Stack Usage        Γöé
  10515. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10516. ΓöéVideoPause          Γöé3c        ΓöéSuspend/resume video active Γöé
  10517. Γöé                    Γöé          Γöéthreads                     Γöé
  10518. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10519. ΓöéSaveMsg             Γöé3d        ΓöéDisplay a message (base     Γöé
  10520. Γöé                    Γöé          Γöédrivers)                    Γöé
  10521. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10522. ΓöéRegisterDeviceClass Γöé43        ΓöéRegister an ADD device classΓöé
  10523. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10524. ΓöéRegisterPDD         Γöé50        ΓöéRegister a 16:16 drv for    Γöé
  10525. Γöé                    Γöé          ΓöéPDD-VDD comm.               Γöé
  10526. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10527. ΓöéRegisterBeep        Γöé51        ΓöéRegister a PDDs Beep Entry  Γöé
  10528. Γöé                    Γöé          ΓöéPoint                       Γöé
  10529. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10530. ΓöéBeep                Γöé52        ΓöéCreate a Beep               Γöé
  10531. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10532. ΓöéFreeGDTSelector     Γöé53        ΓöéFree allocated GDT selector Γöé
  10533. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10534. ΓöéPhysToGDTSel        Γöé54        ΓöéMap physical address to GDT Γöé
  10535. Γöé                    Γöé          Γöéselector                    Γöé
  10536. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10537. ΓöéVMLock              Γöé55        ΓöéLock linear address range inΓöé
  10538. Γöé                    Γöé          Γöésegment                     Γöé
  10539. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10540. ΓöéVMUnlock            Γöé56        ΓöéUnlock linear address range Γöé
  10541. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10542. ΓöéVMAlloc             Γöé57        ΓöéAllocate a block of physicalΓöé
  10543. Γöé                    Γöé          Γöémemory                      Γöé
  10544. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10545. ΓöéVMFree              Γöé58        ΓöéFree memory or mapping      Γöé
  10546. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10547. ΓöéVMProcessToGlobal   Γöé59        ΓöéMap process address space   Γöé
  10548. Γöé                    Γöé          Γöéinto global                 Γöé
  10549. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10550. ΓöéVMGlobalToProcess   Γöé5a        ΓöéMap global address into     Γöé
  10551. Γöé                    Γöé          Γöéprocess address             Γöé
  10552. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10553. ΓöéVirtToLin           Γöé5b        ΓöéConvert sel                 Γöé
  10554. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10555. ΓöéLinToGDTSelector    Γöé5c        ΓöéConvert linear address to   Γöé
  10556. Γöé                    Γöé          Γöévirtual address             Γöé
  10557. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10558. ΓöéGetDescInfo         Γöé5d        ΓöéGet descriptor info         Γöé
  10559. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10560. ΓöéLinToPageList       Γöé5e        ΓöéGet physical pages mapped toΓöé
  10561. Γöé                    Γöé          Γöéthe linear address          Γöé
  10562. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10563. ΓöéPageListToLin       Γöé5f        ΓöéMap physical pages to linearΓöé
  10564. Γöé                    Γöé          Γöéaddress                     Γöé
  10565. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10566. ΓöéPageListToGDTSelectoΓöé60        ΓöéMap physical address to a   Γöé
  10567. Γöé                    Γöé          Γöéselector                    Γöé
  10568. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10569. ΓöéRegisterTmrDD       Γöé61        ΓöéGet kernel address of the   Γöé
  10570. Γöé                    Γöé          ΓöéTmr value                   Γöé
  10571. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10572. ΓöéAllocateCtxHook     Γöé63        ΓöéAllocate a context hook     Γöé
  10573. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10574. ΓöéFreeCtxHook         Γöé64        ΓöéFree a context hook         Γöé
  10575. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10576. ΓöéArmCtxHook          Γöé65        ΓöéArm a context hook          Γöé
  10577. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10578. ΓöéVMSetMem            Γöé66        ΓöéCommit/decommit physical    Γöé
  10579. Γöé                    Γöé          Γöémemory                      Γöé
  10580. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10581. ΓöéOpenEventSem        Γöé67        ΓöéOpen a 32-bit shared event  Γöé
  10582. Γöé                    Γöé          Γöésemaphore                   Γöé
  10583. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10584. ΓöéCloseEventSem       Γöé68        ΓöéClose a 32-bit shared event Γöé
  10585. Γöé                    Γöé          Γöésemaphore                   Γöé
  10586. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10587. ΓöéPostEventSem        Γöé69        ΓöéPost a 32-bit shared event  Γöé
  10588. Γöé                    Γöé          Γöésemaphore                   Γöé
  10589. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10590. ΓöéResetEventSem       Γöé6a        ΓöéReset a 32-bit shared event Γöé
  10591. Γöé                    Γöé          Γöésemaphore                   Γöé
  10592. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10593. ΓöéRegisterFreq        Γöé6b        ΓöéRegister PTD freq service   Γöé
  10594. Γöé                    Γöé          Γöéwith kernel                 Γöé
  10595. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10596. ΓöéDynamicAPI          Γöé6c        ΓöéCreate a ring 0 callgate to Γöé
  10597. Γöé                    Γöé          Γöéa worker                    Γöé
  10598. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  10599. Table A-1. Device Helper functions 
  10600.  
  10601.  
  10602. ΓòÉΓòÉΓòÉ 21.1. DevHlp Services and Device Contexts ΓòÉΓòÉΓòÉ
  10603.  
  10604. OS/2 device drivers may run in one of three modes or contexts. These three 
  10605. contexts are: 
  10606.  
  10607.  1. Kernel mode - the context in which the device driver Strategy section runs. 
  10608.     This is sometimes referred to as "Strategy time" or "task time". 
  10609.  2. Interrupt mode - the context in which the driver's interrupt handler runs 
  10610.     while servicing hardware interrupts. 
  10611.  3. INIT mode - the context in which the device driver runs when called by the 
  10612.     kernel to INIT the driver. This is a special mode at Ring 3 with I/O 
  10613.     privileges. 
  10614.  
  10615. Not all DevHlp services are available in each mode. Table A-2 describes which 
  10616. DevHlp functions are available in the various modes. 
  10617.  
  10618. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  10619. ΓöéDevHlp Function     ΓöéCode  ΓöéKernel    ΓöéInterrupt   ΓöéINIT      Γöé
  10620. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10621. ΓöéSchedClockAddr      Γöé00h   ΓöéX         Γöé            ΓöéX         Γöé
  10622. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10623. ΓöéDevDone             Γöé01h   ΓöéX         ΓöéX           Γöé          Γöé
  10624. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10625. ΓöéYield               Γöé02h   ΓöéX         Γöé            Γöé          Γöé
  10626. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10627. ΓöéTCYield             Γöé03h   ΓöéX         Γöé            Γöé          Γöé
  10628. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10629. ΓöéBlock               Γöé04h   ΓöéX         Γöé            Γöé          Γöé
  10630. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10631. ΓöéRun                 Γöé05h   ΓöéX         ΓöéX           Γöé          Γöé
  10632. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10633. ΓöéSemRequest          Γöé06h   ΓöéX         Γöé            Γöé          Γöé
  10634. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10635. ΓöéSemClear            Γöé07h   ΓöéX         ΓöéX           Γöé          Γöé
  10636. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10637. ΓöéSemHandle           Γöé08h   ΓöéX         ΓöéX           Γöé          Γöé
  10638. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10639. ΓöéPushReqPacket       Γöé09h   ΓöéX         Γöé            Γöé          Γöé
  10640. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10641. ΓöéPullReqPacket       Γöé0Ah   ΓöéX         ΓöéX           Γöé          Γöé
  10642. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10643. ΓöéPullParticular      Γöé0Bh   ΓöéX         ΓöéX           Γöé          Γöé
  10644. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10645. ΓöéSortReqPacket       Γöé0Ch   ΓöéX         Γöé            Γöé          Γöé
  10646. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10647. ΓöéAllocReqPacket      Γöé0Dh   ΓöéX         Γöé            Γöé          Γöé
  10648. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10649. ΓöéFreeReqPacket       Γöé0Eh   ΓöéX         Γöé            Γöé          Γöé
  10650. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10651. ΓöéQueueInit           Γöé0Fh   ΓöéX         ΓöéX           ΓöéX         Γöé
  10652. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10653. ΓöéQueueFlush          Γöé10h   ΓöéX         ΓöéX           Γöé          Γöé
  10654. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10655. ΓöéQueueWrite          Γöé11h   ΓöéX         ΓöéX           Γöé          Γöé
  10656. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10657. ΓöéQueueRead           Γöé12h   ΓöéX         ΓöéX           Γöé          Γöé
  10658. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10659. ΓöéLockSeg             Γöé13h   ΓöéX         Γöé            ΓöéX         Γöé
  10660. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10661. ΓöéUnlockSeg           Γöé14h   ΓöéX         Γöé            ΓöéX         Γöé
  10662. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10663. ΓöéPhysToVirt          Γöé15h   ΓöéX         ΓöéX           ΓöéX         Γöé
  10664. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10665. ΓöéVirtToPhys          Γöé16h   ΓöéX         Γöé            ΓöéX         Γöé
  10666. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10667. ΓöéPhysToUVirt         Γöé17h   ΓöéX         Γöé            ΓöéX         Γöé
  10668. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10669. ΓöéAllocPhys           Γöé18h   ΓöéX         Γöé            ΓöéX         Γöé
  10670. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10671. ΓöéFreePhys            Γöé19h   ΓöéX         Γöé            ΓöéX         Γöé
  10672. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10673. ΓöéSetIRQ              Γöé1Bh   ΓöéX         Γöé            ΓöéX         Γöé
  10674. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10675. ΓöéUnSetIRQ            Γöé1Ch   ΓöéX         ΓöéX           ΓöéX         Γöé
  10676. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10677. ΓöéSetTimer            Γöé1Dh   ΓöéX         Γöé            ΓöéX         Γöé
  10678. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10679. ΓöéResetTimer          Γöé1Eh   ΓöéX         ΓöéX           ΓöéX         Γöé
  10680. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10681. ΓöéMonCreate           Γöé1Fh   ΓöéX         Γöé            ΓöéX         Γöé
  10682. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10683. ΓöéDeRegister          Γöé21h   ΓöéX         Γöé            Γöé          Γöé
  10684. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10685. ΓöéMonWrite            Γöé22h   ΓöéX         ΓöéX           Γöé          Γöé
  10686. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10687. ΓöéMonFlush            Γöé23h   ΓöéX         Γöé            Γöé          Γöé
  10688. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10689. ΓöéGetDOSVar           Γöé24h   ΓöéX         Γöé            ΓöéX         Γöé
  10690. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10691. ΓöéSendEvent           Γöé25h   ΓöéX         ΓöéX           Γöé          Γöé
  10692. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10693. ΓöéVerifyAccess        Γöé27h   ΓöéX         Γöé            Γöé          Γöé
  10694. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10695. ΓöéABIOSGetParms       Γöé29h   ΓöéX         ΓöéX           ΓöéX         Γöé
  10696. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10697. ΓöéAttachDD            Γöé2Ah   ΓöéX         Γöé            ΓöéX         Γöé
  10698. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10699. ΓöéInternalError       Γöé2Bh   ΓöéX         ΓöéX           ΓöéX         Γöé
  10700. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10701. ΓöéAllocGDTSelector    Γöé2Dh   Γöé          Γöé            ΓöéX         Γöé
  10702. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10703. ΓöéPhysToGDTSelector   Γöé2Eh   ΓöéX         ΓöéX           ΓöéX         Γöé
  10704. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10705. ΓöéEOI                 Γöé31h   Γöé          ΓöéX           ΓöéX         Γöé
  10706. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10707. ΓöéUnPhysToVirt        Γöé32h   ΓöéX         ΓöéX           ΓöéX         Γöé
  10708. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10709. ΓöéTickCount           Γöé33h   ΓöéX         ΓöéX           ΓöéX         Γöé
  10710. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10711. ΓöéGetLIDEntry         Γöé34h   ΓöéX         Γöé            ΓöéX         Γöé
  10712. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10713. ΓöéFreeLIDEntry        Γöé35h   ΓöéX         Γöé            ΓöéX         Γöé
  10714. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10715. ΓöéABIOSCall           Γöé36h   ΓöéX         ΓöéX           ΓöéX         Γöé
  10716. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10717. ΓöéABIOSCommonEntry    Γöé37h   ΓöéX         ΓöéX           ΓöéX         Γöé
  10718. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10719. ΓöéGetDeviceBlock      Γöé38h   Γöé          Γöé            ΓöéX         Γöé
  10720. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10721. ΓöéRegisterStackUsage  Γöé3Ah   Γöé          Γöé            ΓöéX         Γöé
  10722. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10723. ΓöéVideoPause          Γöé3Ch   ΓöéX         ΓöéX           ΓöéX         Γöé
  10724. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10725. ΓöéSaveMsg             Γöé3Dh   Γöé          Γöé            ΓöéX         Γöé
  10726. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10727. ΓöéRegisterDeviceClass Γöé43h   ΓöéX*        Γöé            Γöé          Γöé
  10728. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10729. ΓöéRegisterPDD         Γöé50h   ΓöéX         Γöé            ΓöéX         Γöé
  10730. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10731. ΓöéRegisterBeep        Γöé51h   ΓöéX         Γöé            ΓöéX         Γöé
  10732. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10733. ΓöéBeep                Γöé52h   ΓöéX         ΓöéX           ΓöéX         Γöé
  10734. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10735. ΓöéFreeGDTSelector     Γöé53h   ΓöéX         Γöé            ΓöéX         Γöé
  10736. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10737. ΓöéPhysToGDTSel        Γöé54h   ΓöéX         ΓöéX           ΓöéX         Γöé
  10738. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10739. ΓöéVMLock              Γöé55h   ΓöéX         Γöé            ΓöéX         Γöé
  10740. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10741. ΓöéVMUnlock            Γöé56h   ΓöéX         Γöé            ΓöéX         Γöé
  10742. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10743. ΓöéVMAlloc             Γöé57h   ΓöéX         Γöé            ΓöéX         Γöé
  10744. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10745. ΓöéVMFree              Γöé58h   ΓöéX         Γöé            ΓöéX         Γöé
  10746. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10747. ΓöéVirtToLin           Γöé5Bh   ΓöéX         ΓöéX           ΓöéX         Γöé
  10748. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10749. ΓöéLinToGDTSelector    Γöé5Ch   ΓöéX         ΓöéX           ΓöéX         Γöé
  10750. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10751. ΓöéGetDescInfo         Γöé5Dh   ΓöéX         ΓöéX**         ΓöéX         Γöé
  10752. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10753. ΓöéLinToPageList       Γöé5Eh   ΓöéX         ΓöéX           ΓöéX         Γöé
  10754. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10755. ΓöéPageListToLin       Γöé5Fh   ΓöéX         ΓöéX           ΓöéX         Γöé
  10756. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10757. ΓöéPageListToGDTSelectoΓöé60h   ΓöéX         ΓöéX           ΓöéX         Γöé
  10758. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10759. ΓöéRegisterTmrDD       Γöé61h   Γöé          Γöé            ΓöéX         Γöé
  10760. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10761. ΓöéAllocateCtxHook     Γöé63h   ΓöéX         Γöé            ΓöéX         Γöé
  10762. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10763. ΓöéFreeCtxHook         Γöé64h   ΓöéX         Γöé            ΓöéX         Γöé
  10764. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10765. ΓöéArmCtxHook          Γöé65h   ΓöéX         ΓöéX           ΓöéX         Γöé
  10766. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10767. ΓöéVMSetMem            Γöé66h   ΓöéX         Γöé            ΓöéX         Γöé
  10768. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10769. ΓöéOpenEventSem        Γöé67h   ΓöéX         Γöé            Γöé          Γöé
  10770. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10771. ΓöéCloseEventSem       Γöé68h   ΓöéX         Γöé            Γöé          Γöé
  10772. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10773. ΓöéPostEventSem        Γöé69h   ΓöéX         Γöé            Γöé          Γöé
  10774. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10775. ΓöéResetEventSem       Γöé6Ah   ΓöéX         Γöé            Γöé          Γöé
  10776. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  10777. ΓöéDynamicAPI          Γöé6Ch   ΓöéX         Γöé            ΓöéX         Γöé
  10778. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  10779. Table A-2. Device Helper contexts 
  10780.  
  10781. * ADD initialization is performed at ring 0 
  10782.  
  10783. ** This function can return information on a Global Descriptor only at 
  10784. interrupt time. 
  10785.  
  10786.  
  10787. ΓòÉΓòÉΓòÉ 21.2. Device Helper Categories ΓòÉΓòÉΓòÉ
  10788.  
  10789. The OS/2 DevHlp Functions can also be grouped by functionality into 13 major 
  10790. categories. 
  10791.  
  10792. Category 1 - System Clock Management 
  10793.  
  10794.    o SchedClockAddr 
  10795.  
  10796. Category 2 - Process Management 
  10797.  
  10798.    o Block 
  10799.    o DevDone 
  10800.    o Run 
  10801.    o TCYield 
  10802.    o Yield 
  10803.  
  10804. Category 3 - Semaphore Functions 
  10805.  
  10806.    o CloseEventSem 
  10807.    o OpenEventSem 
  10808.    o PostEventSem 
  10809.    o ResetEventSem 
  10810.    o SemClear 
  10811.    o SemHandle 
  10812.    o SemRequest 
  10813.  
  10814. Category 4 - Request Queue Functions 
  10815.  
  10816.    o AllocReqPacket 
  10817.    o FreeReqPacket 
  10818.    o PullParticular 
  10819.    o PullReqPacket 
  10820.    o PushReqPacket 
  10821.    o SortReqPacket 
  10822.  
  10823. Category 5 - Memory Management Functions 
  10824.  
  10825.    o AllocGDTSelector 
  10826.    o AllocPhys 
  10827.    o FreeGDTSelector 
  10828.    o FreePhys 
  10829.    o LinToGDTSelector 
  10830.    o LinToPageList 
  10831.    o Lock 
  10832.    o PageListToGDTSelector 
  10833.    o PageListToLin 
  10834.    o PhysToGDTSel 
  10835.    o PhysToGDTSelector 
  10836.    o PhysToUVirt 
  10837.    o PhysToVirt 
  10838.    o Unlock 
  10839.    o UnPhysToVirt 
  10840.    o VerifyAccess 
  10841.    o VirtToLin 
  10842.    o VirtToPhys 
  10843.    o VMAlloc 
  10844.    o VMFree 
  10845.    o VMGlobalToProcess 
  10846.    o VMLock 
  10847.    o VMProcessToGlobal 
  10848.    o VMSetMem 
  10849.    o VMUnlock 
  10850.  
  10851. Category 6 - Device Monitor Functions 
  10852.  
  10853.    o DeRegister 
  10854.    o MonFlush 
  10855.    o MonitorCreate 
  10856.    o MonWrite 
  10857.    o Register 
  10858.  
  10859. Category 7 - Character Queue Functions 
  10860.  
  10861.    o QueueFlush 
  10862.    o QueueInit 
  10863.    o QueueRead 
  10864.    o QueueWrite 
  10865.  
  10866. Category 8 - Interrupt Management 
  10867.  
  10868.    o EOI 
  10869.    o SetIRQ 
  10870.    o UnSetIRQ 
  10871.  
  10872. Category 9 - Timer Functions 
  10873.  
  10874.    o RegisterTmrDD 
  10875.    o ResetTimer 
  10876.    o SetTimer 
  10877.    o TickCount 
  10878.  
  10879. Category 10 - System Functions 
  10880.  
  10881.    o Beep 
  10882.    o SaveMsg 
  10883.    o DynamicAPI 
  10884.    o GetDescInfo 
  10885.    o GetDOSVar 
  10886.    o RegisterBeep 
  10887.    o RegisterDeviceClass 
  10888.    o SendEvent 
  10889.    o VideoPause 
  10890.  
  10891. Category 11 - Advanced BIOS (ABIOS) Functions (PS/2 Only) 
  10892.  
  10893.    o ABIOSCall 
  10894.    o ABIOSCommonEntry 
  10895.    o ABIOSGetParms 
  10896.    o FreeLIDEntry 
  10897.    o GetDeviceBlock 
  10898.    o GetLIDEntry 
  10899.  
  10900. Category 12 - PDD - VDD Communications Services 
  10901.  
  10902.    o RegisterPDD 
  10903.  
  10904. Category 13 - Context Hook Services 
  10905.  
  10906.    o AllocateCtxHook 
  10907.    o ArmCtxHook 
  10908.    o FreeCtxHook 
  10909.  
  10910.  
  10911. ΓòÉΓòÉΓòÉ 21.3. DevHlp Routines ΓòÉΓòÉΓòÉ
  10912.  
  10913. The DevHlp functions are register based calls to the OS/2 kernel to perform 
  10914. functions necessary for OS/2 device driver operation. All parameters are passed 
  10915. and returned in registers. To provide an environment in which to write OS/2 2.1 
  10916. device drivers in C, you will have to provide a C-language interface to the 
  10917. DevHlp routines. You can write your own, or you can order them using the order 
  10918. form at the back of the book. All C callable routines use the PASCAL calling 
  10919. convention. 
  10920.  
  10921.  
  10922. ΓòÉΓòÉΓòÉ 21.3.1. ABIOSCall ΓòÉΓòÉΓòÉ
  10923.  
  10924. ____________________________________________________________
  10925. ABIOSCall           Mode: Kernel, Interrupt, Init
  10926.  
  10927. Invoke an ABIOS function
  10928.  
  10929. This routine is used to invoke an ABIOS service for the Operating System 
  10930. Transfer Convention. 
  10931.  
  10932. C Calling Convention 
  10933.  
  10934. if (ABIOSCall(USHORT Lid,USHORT Subfunction,(FARPOINTER) &ABIOSReqBlock)) error
  10935.  
  10936. Lid          = The LID obtained by a previous GetLIDEntry call
  10937. Subfunction  = ABIOS define subfunction
  10938. &ABIOSReqBlk = far pointer to DS-relative ABIOS request block
  10939.  
  10940. COMMENTS 
  10941.  
  10942. The indicated ABIOS function is called according to the Operating System 
  10943. Transfer Convention. ABIOSCall will clean up the stack before returning to the 
  10944. device driver. 
  10945.  
  10946. EXAMPLE 
  10947.  
  10948. // Get the size of the LID request block
  10949.  
  10950. ABIOS_l_blk.f_parms.req_blk_len = sizeof(struct lid_block_def);
  10951. ABIOS_l_blk.f_parms.LID = lid;
  10952. ABIOS_l_blk.f_parms.unit = 0;;
  10953. ABIOS_l_blk.f_parms.function = GET_LID_BLOCK_SIZE;
  10954. ABIOS_l_blk.f_parms.ret_code = 0x5a5a;
  10955. ABIOS_l_blk.f_parms.time_out = 0;
  10956.  
  10957. if (ABIOSCall(lid,(FARPOINTER)&ABIOS_l_blk,0))
  10958.  return 1;
  10959.  
  10960. lid_blk_size = ABIOS_l_blk.s_parms.blk_size; /* Get the block size  */
  10961.  
  10962. /* Fill POS regs and card ID with FF in case this does not work     */
  10963.  
  10964. *card_ID = 0xFFFF;
  10965. for (i=0; i<NUM_POS_BYTES; i++) { pos_regs[i] = 0x00; };
  10966.  
  10967. /* Get the POS registers and card ID for the commanded slot */
  10968.  
  10969. ABIOS_r_blk.f_parms.req_blk_len = lid_blk_size;
  10970. ABIOS_r_blk.f_parms.LID = lid;
  10971. ABIOS_r_blk.f_parms.unit = 0;;
  10972. ABIOS_r_blk.f_parms.function = READ_POS_REGS_CARD;
  10973. ABIOS_r_blk.f_parms.ret_code = 0x5a5a;
  10974. ABIOS_r_blk.f_parms.time_out = 0;
  10975.  
  10976. ABIOS_r_blk.s_parms.slot_num = (unsigned char)slot_num & 0x0F;
  10977. ABIOS_r_blk.s_parms.pos_buf = (FARPOINTER)pos_regs;
  10978. ABIOS_r_blk.s_parms.card_ID = 0xFFFF;
  10979.  
  10980. if (ABIOSCall(lid,(FARPOINTER)&ABIOS_r_blk,0))
  10981.  rc = FAILURE;
  10982. else
  10983. {                                             /* Else                  */
  10984.  *card_ID = ABIOS_r_blk.s_parms.card_ID;      /* Set the card ID value */
  10985.  rc = SUCCESS;
  10986. }
  10987. FreeLIDEntry(lid);
  10988. return(rc);
  10989.  
  10990.  
  10991. ΓòÉΓòÉΓòÉ 21.3.2. ABIOSCommonEntry ΓòÉΓòÉΓòÉ
  10992.  
  10993. ____________________________________________________________
  10994. ABIOSCommonEntry       Mode: Kernel, Interrupt, Init
  10995.  
  10996. Invoke ABIOS Common Entry Point
  10997.  
  10998. This service is used to invoke an ABIOS Common Entry Point according to the 
  10999. Advanced BIOS Transfer Convention. 
  11000.  
  11001. C Calling Convention 
  11002.  
  11003. if (ABIOSComm(USHORT Subfunction,(FARPOINTER) &ABIOSReqBlk)) error
  11004.  
  11005. Subfunction  = ABIOS defined subfunction
  11006. &ABIOSReqBlk = far pointer to DS-relative ABIOS request block
  11007.  
  11008. COMMENTS 
  11009.  
  11010. ABIOSCommonEntry invokes the indicated ABIOS common entry point. 
  11011.  
  11012. EXAMPLE 
  11013.  
  11014. if (ABIOSCommonEntry(0,(FARPOINTER)&ABIOS_r_blk))
  11015.     error;
  11016.  
  11017.  
  11018. ΓòÉΓòÉΓòÉ 21.3.3. ABIOSGetParms ΓòÉΓòÉΓòÉ
  11019.  
  11020. ____________________________________________________________
  11021. ABIOSGetParms         Mode: Kernel, Interrupt, Init
  11022.  
  11023. Get ABIOS Parameters
  11024.  
  11025. C Calling Convention 
  11026.  
  11027. if (ABIOSGetParms(USHORT Lid,(FARPOINTER) &ABIOSParmBlock)) error
  11028.  
  11029. Lid           = The LID obtained by a previous GetLIDEntry call
  11030. &ABIOSParmBlk = far pointer to DS-relative ABIOS parameter block
  11031.  
  11032. COMMENTS 
  11033.  
  11034. Refer to the IBM Personal System/2 and Personal Computer BIOS Interface 
  11035. Technical Reference, part number S68X-2341-00, for more detailed information on 
  11036. the use of ABIOS and its associated data structures. 
  11037.  
  11038.  
  11039. ΓòÉΓòÉΓòÉ 21.3.4. AllocateCtxHook ΓòÉΓòÉΓòÉ
  11040.  
  11041. ____________________________________________________________
  11042. AllocateCtxHook        Mode: Kernel, Init
  11043.  
  11044. Allocate a context hook
  11045.  
  11046. AllocateCtxHook allocates a context hook for use by a device driver that needs 
  11047. task time processing, but has no task time thread available to complete it. 
  11048.  
  11049. C Calling Convention 
  11050.  
  11051. if (AllocateCtxHook((OFF)&HookHandler,ULONG Val,(PLHANDLE) &NewHandle)) error
  11052.  
  11053. &HookHandler = 16 bit offset to context hook handler
  11054. Val          = 0xffffffff (reserved value)
  11055. NewHandle    = far pointer to returned handle
  11056.  
  11057. COMMENTS 
  11058.  
  11059. When the context hook is armed and triggers, the Hook Handler function is 
  11060. called with register EAX equal to the value passed in the HookData parameter of 
  11061. the ArmCtxHook call, and EBX equal to -1L. 
  11062.  
  11063. The hook handler is responsible for saving and restoring registers on entry and 
  11064. exit. The hook handler address should be zero extended. 
  11065.  
  11066.  
  11067. ΓòÉΓòÉΓòÉ 21.3.5. AllocGDTSelector ΓòÉΓòÉΓòÉ
  11068.  
  11069. ____________________________________________________________
  11070. AllocGDTSelector       Mode: Init
  11071.  
  11072. Allocate GDT Selector(s)
  11073.  
  11074. This function allocates one or more GDT selectors for a device driver to use. 
  11075. This allocation is performed at device driver INIT time. 
  11076.  
  11077. C Calling Convention 
  11078.  
  11079. if (AllocGDTSelector(USHORT Count,(FARPOINTER) &SelArray)) error
  11080. Count     = number of selectors to allocate
  11081. &SelArray = far pointer to selector array
  11082.  
  11083. COMMENTS 
  11084.  
  11085. AllocGDTSelector is used to allocate one or more GDT selectors for a device 
  11086. driver to use for kernel and interrupt mode operations. 
  11087.  
  11088. Allocating a GDT selector and then mapping an address to it using the 
  11089. PhysToGDTSelector DevHlp allows a driver to access the memory defined by the 
  11090. GDT selector in any context. 
  11091.  
  11092. EXAMPLE 
  11093.  
  11094. if (!(SetIRQ(5,(PFUNCTION)INTERRUPT_HANDLER,0)))
  11095. {
  11096.   if (!(AllocGDTSelector(1,(FARPOINTER)&Sel)))
  11097.   {
  11098.      if (!(PhysToGDTSelector(0xd8000,0x1000,Sel,&err)))
  11099.      {
  11100.  
  11101.         /* output initialization message */
  11102.  
  11103.         DosPutMessage(1, 2, CrLf);
  11104.         DosPutMessage(1, 8, devhdr.DHname);
  11105.         DosPutMessage(1, strlen(InitMessage), InitMessage);
  11106.  
  11107.         /* send back our cs and ds end values to os/2 */
  11108.  
  11109.         if (SegLimit(HIUSHORT((void far *) Init), &rp->s.InitExit.finalCS)
  11110.             || SegLimit(HIUSHORT((void far *) InitMessage),
  11111.             &rp->s.InitExit.finalDS))
  11112.               Abort();
  11113.         return(RPDONE);
  11114.      }
  11115.   }
  11116. }
  11117.  
  11118.  
  11119. ΓòÉΓòÉΓòÉ 21.3.6. AllocPhys ΓòÉΓòÉΓòÉ
  11120.  
  11121. ____________________________________________________________
  11122. AllocPhys           Mode: Kernel, Init
  11123.  
  11124. Allocate a Fixed Block of Physical Memory
  11125.  
  11126. AllocPhys is used by device drivers to allocate a block of fixed memory.
  11127.  
  11128. C Calling Convention 
  11129.  
  11130. if (AllocPhys(ULONG Size,USHORT Flag,far (PPHYSADDR) &pPhysAddr)) error
  11131.  
  11132. Size      = number of bytes to allocate
  11133. Flag      = 0 - Allocate memory above 1MB
  11134.           = 1 - Allocate memory below 1MB
  11135. &Physaddr = pointer to returned physical address
  11136.  
  11137. COMMENTS 
  11138.  
  11139. The memory allocated by this function is fixed memory, and may not be "unfixed" 
  11140. through the Unlock call. 
  11141.  
  11142. If memory is requested to be allocated high (above 1 megabyte), and no memory 
  11143. above 1 megabyte is available, then an error is returned. The device driver 
  11144. could then attempt to allocate low memory. 
  11145.  
  11146. Conversely, if memory is requested to be allocated low (below 1 megabyte), and 
  11147. no memory below 1 megabyte is available, then an error is returned and the 
  11148. device driver could try allocating high memory, if appropriate. 
  11149.  
  11150. EXAMPLE 
  11151.  
  11152. // allocate a 64KB segment above 1MB
  11153.  
  11154. if (AllocPhys(0x10000,1,(PPHYSADDR) &AllocAddress)) error
  11155.  
  11156.  
  11157. ΓòÉΓòÉΓòÉ 21.3.7. AllocReqPacket ΓòÉΓòÉΓòÉ
  11158.  
  11159. ____________________________________________________________
  11160. AllocReqPacket        Mode: Kernel
  11161.  
  11162. Get a Request Packet
  11163.  
  11164. This service returns a bimodal pointer to an empty Request Packet.
  11165.  
  11166. C Calling Convention 
  11167.  
  11168. if(AllocReqPacket(USHORT Flag,(PREQPACKET) &Ptr)) error
  11169.  
  11170. Flag = 0 - wait
  11171.      = 1 - do not wait
  11172. &Ptr = far pointer to Request Packet returned
  11173.  
  11174. COMMENTS 
  11175.  
  11176. AllocReqPacket returns a pointer to a maximum-size Request Packet. Some OS/2 
  11177. device drivers need to have additional Request Packets to service requests. 
  11178. Once the Request Packet address is obtained, it can be pushed on the Request 
  11179. Packet work queue with the PushReqPacket DevHlp. 
  11180.  
  11181. Request Packets allocated by the AllocReqPacket DevHlp should be returned to 
  11182. the kernel as soon as possible by calling the FreeReqPacket DevHlp, as the 
  11183. number of free Request Packets is limited system wide. 
  11184.  
  11185.  
  11186. ΓòÉΓòÉΓòÉ 21.3.8. ArmCtxHook ΓòÉΓòÉΓòÉ
  11187.  
  11188. ____________________________________________________________
  11189. ArmCtxHook          Mode: Kernel, Interrupt, Init
  11190.  
  11191. Arm a Context Hook
  11192.  
  11193. ArmCtxHook arms a context hook allocated by the AllocateCtxHook DevHlp 
  11194. function. This function can be called at interrupt time. The next available 
  11195. task time thread will be used to call the function address specified at hook 
  11196. allocation time. 
  11197.  
  11198. C Calling Convention 
  11199.  
  11200. if (ArmCtxHook(ULONG HookData,LHANDLE HookHandle,ULONG Val)) error
  11201.  
  11202. HookData   = data to be passed to hook handler
  11203. HookHandle = handle returned from AllocCtxHook
  11204. Val        = 0xffffffff (reserved value)
  11205.  
  11206. COMMENTS 
  11207.  
  11208. After the context hook is armed, it operates once and automatically disarms 
  11209. itself. It is an error to attempt to arm a context hook that is already armed. 
  11210. Once the context hook starts execution, the hook can be rearmed. 
  11211.  
  11212.  
  11213. ΓòÉΓòÉΓòÉ 21.3.9. AttachDD ΓòÉΓòÉΓòÉ
  11214.  
  11215. ____________________________________________________________
  11216. AttachDD           Mode: Kernel, Init
  11217.  
  11218. Get IDC Entry Point of a Driver
  11219.  
  11220. This function returns the address of the Inter-Device Driver Communication 
  11221. (IDC) Entry Point to a specified device. 
  11222.  
  11223. C Calling Convention 
  11224.  
  11225. if (AttachDD("DEVICE  ",(PATTACHAREA) &AttachArea)) error
  11226.  
  11227. &AttachArea = near pointer to returned structure, type AttachArea
  11228.  
  11229. AttachArea struct
  11230. {
  11231.    USHORT RealOffset;  // real mode offset of IDC entry point
  11232.    USHORT RealSegment; // real mode segment of IDC entry point
  11233.    USHORT RealDS;      // real mode DS of IDC device driver
  11234.    USHORT ProtOffset;  // protect mode offset of IDC entry point
  11235.    USHORT ProtCS;      // protect mode CS selector of IDC entry
  11236.    USHORT ProtDS;      // protect mode DS of IDC driver
  11237. }
  11238.  
  11239. COMMENTS 
  11240.  
  11241. The name field contains the ASCII name of the target device driver which must 
  11242. be eight characters in length. If the target device driver is a character 
  11243. device driver, the device driver name must match the name in the target device 
  11244. driver's Device Header. 
  11245.  
  11246. Before the device driver calls the entry point, it must verify that the entry 
  11247. point received is nonzero. The IDC entry point of the target device driver must 
  11248. follow the FAR CALL/RET model. 
  11249.  
  11250.  
  11251. ΓòÉΓòÉΓòÉ 21.3.10. Beep ΓòÉΓòÉΓòÉ
  11252.  
  11253. ____________________________________________________________
  11254. Beep             Mode: Kernel, Interrupt, Init
  11255.  
  11256. Generate a beep 
  11257.  
  11258. The Beep DevHlp service generates a beep. 
  11259.  
  11260. C Calling Convention 
  11261.  
  11262. if (Beep(USHORT Freq,USHORT Duration)) error
  11263.  
  11264. Freq     = frequency of beep in hertz
  11265. Duration = duration of beep in milliseconds
  11266.  
  11267. COMMENTS 
  11268.  
  11269. This function is similar to the DosBeep API. It generates a tone at Freq for 
  11270. Duration milliseconds. 
  11271.  
  11272. EXAMPLE 
  11273.  
  11274. Beep (1000,100);
  11275.  
  11276.  
  11277. ΓòÉΓòÉΓòÉ 21.3.11. Block ΓòÉΓòÉΓòÉ
  11278.  
  11279. ____________________________________________________________
  11280. Block             Mode: Kernel
  11281.  
  11282. Block This Thread From Running
  11283.  
  11284. The Block DevHlp blocks the current requesting thread and removes it from the 
  11285. run queue until it is released by a call to the Run DevHlp. 
  11286.  
  11287. C Calling Convention 
  11288.  
  11289. if (Block(ULONG BlockID,ULONG Timeout,USHORT Flag,(FARPOINTER) &Error)) error
  11290.  
  11291. BlockID  = ID used for Block and subsequent Run
  11292. Timeout  = timeout in milliseconds or -1L Block forever
  11293. Flag     = 0 - Block is interruptible
  11294.          = 1 - Block is noninterruptible
  11295. &Error   = far Pointer to error returned
  11296.          = 1 - Block timed out
  11297.          = 2 - Block interrupted by control-C
  11298. COMMENTS 
  11299.  
  11300. The return from the Block call indicates whether the wake-up occurred as the 
  11301. result of a Run DevHlp call or an expiration of the time limit. Block removes 
  11302. the current thread from the run queue, allowing any other waiting threads to 
  11303. run.  The thread blocked in the device driver is reactivated and Block returns 
  11304. when Run is called with the same event identifier, when the time limit expires, 
  11305. or when the thread is signalled.  The event identifier is an arbitrary 32-bit 
  11306. value, but an acceptable convention is to use the address of the Request Packet 
  11307. that made the request. 
  11308.  
  11309. Since the device driver may be Blocked in one mode and Run in the other, using 
  11310. the address of the Request Packet is the best choice, as this bimodal address 
  11311. is valid in either mode.  It is up to the device driver writer to insure that 
  11312. the Block was woken up by the correct mechanism, and not accidentally.  To 
  11313. avoid a deadlock condition by getting a Run before the Block call is completed, 
  11314. the device driver should disable interrupts before issuing the Block.  The 
  11315. Block DevHlp re-enables the interrupts. 
  11316.  
  11317. A timeout value of -1 means that Block waits indefinitely until Run is called. 
  11318. Only the Strategy sections of the device driver can call Block, but Run can be 
  11319. called by the Strategy section, interrupt handler, or timer handler.  When 
  11320. using Block to block a thread, the device driver can specify whether or not the 
  11321. Block may be interrupted.  If the Block is interruptible, then the kernel can 
  11322. abort the blocked thread and return from the Block without using a 
  11323. corresponding Run.  In general, the Block should be marked as interruptible so 
  11324. that a signal such as a control C will UnBlock the thread. 
  11325.  
  11326. The Block call will return when the thread has been run, when the timeout has 
  11327. expired, or if the thread was UnBlock by a signal, such as a control C. If the 
  11328. Block returns with a 1, the Block has timed out.  If the Block returns a 2, the 
  11329. Block was interrupted.  If the Block returns a 0, or valid return, then the 
  11330. Block was released by a call to the Run DevHlp, and the device driver should 
  11331. take the appropriate action. 
  11332.  
  11333. EXAMPLE 
  11334.  
  11335. if (Block(WriteID,blockcount, 0, &err))
  11336.  if (err == 2)  // interrupted
  11337.   return(RPDONE|RPERR|ERROR_CHAR_CALL_INTERRUPTED);
  11338.  
  11339.  if (err == 1)
  11340.   return (RPDONE|RPERR|ERROR_NOT_READY);
  11341.  
  11342.  
  11343. ΓòÉΓòÉΓòÉ 21.3.12. CloseEventSem ΓòÉΓòÉΓòÉ
  11344.  
  11345. ____________________________________________________________
  11346. CloseEventSem         Mode: Kernel
  11347.  
  11348. Close a 32-bit Shared Event Semaphore
  11349.  
  11350. CloseEventSem closes an event semaphore that was previously opened with 
  11351. OpenEventSem.  If this is the last reference to this event, then the event 
  11352. semaphore is destroyed. 
  11353.  
  11354. C Calling Convention 
  11355.  
  11356. if (CloseEventSem(ULONG SemHandle)) error
  11357.  
  11358. SemHandle = handle of semaphore
  11359.  
  11360. COMMENTS 
  11361.  
  11362. CloseEventSem can be called only from a Ring 0 device driver or file system 
  11363. device driver.  The handle passed in must be a handle to a shared event 
  11364. semaphore.  If the handle does not exist, or is not a "shared event" semaphore, 
  11365. or if the semaphore was not previously opened with OpenEventSem, then ERROR 
  11366. INVALID HANDLE will be returned. 
  11367.  
  11368. The system semaphores reside in a memory buffer rather than on a disk file. 
  11369. This means that when the last process that has a semaphore open exits or closes 
  11370. that semaphore, the semaphore disappears. 
  11371.  
  11372. The open/close operations may be nested.  A maximum of 65,534 (64KB - 1) opens 
  11373. per process is allowed for each semaphore at any one time.  If this limit is 
  11374. reached, the next call to OpenEventSem will return ERROR_TOO_MANY_OPENS. 
  11375.  
  11376. In order for a process to intentionally destroy a semaphore prior to 
  11377. termination, the number of CloseEventSem calls must equal the number of 
  11378. OpenEventSem calls. 
  11379.  
  11380.  
  11381. ΓòÉΓòÉΓòÉ 21.3.13. DeRegister ΓòÉΓòÉΓòÉ
  11382.  
  11383. ____________________________________________________________
  11384. DeRegister          Mode: Kernel
  11385.  
  11386. Remove Monitors from a Monitor Chain
  11387.  
  11388. DeRegister removes all of the monitors associated with the specified process 
  11389. from the specified monitor chain. 
  11390.  
  11391. C Calling Convention 
  11392.  
  11393. if (DeRegister(USHORT Handle,USHORT Pid,(PERRCODE) &Error)) error
  11394.  
  11395. Handle = the handle of the monitor chain
  11396. Pid    = PID of the process that created the monitor chain
  11397. &Error = far pointer to error returned
  11398.  
  11399. COMMENTS 
  11400.  
  11401. This function may only be called at Strategy time in protect mode. 
  11402.  
  11403. To remove a monitor from a monitor chain, the device driver supplies the PID of 
  11404. the process that created the monitor and the handle of the monitor chain.  All 
  11405. monitors belonging to the PID are removed from the monitor chain.  Since a 
  11406. process may register more than one monitor, all the monitors associated with 
  11407. the PID are removed with one call to DeRegister. 
  11408.  
  11409.  
  11410. ΓòÉΓòÉΓòÉ 21.3.14. DevDone ΓòÉΓòÉΓòÉ
  11411.  
  11412. ____________________________________________________________
  11413. DevDone            Mode: Kernel, Interrupt
  11414.  
  11415. Set Done Bit and Run Thread
  11416.  
  11417. This function sets the done bit in the Request Packet and runs any blocked 
  11418. threads waiting for the request to be completed. 
  11419.  
  11420. C Calling Convention 
  11421.  
  11422. if (DevDone((PREQPACKET) &RequestPacket)) error
  11423.  
  11424. &RequestPacket = far pointer to Request Packet
  11425.  
  11426. COMMENTS 
  11427.  
  11428. The DevDone DevHlp sets the DONE bit in the status field of the Request Packet 
  11429. header and issue RUNs on threads that are blocked in the kernel waiting for the 
  11430. particular Request Packet to be completed.  DevDone will not work with Request 
  11431. Packets that were allocated from the AllocReqPacket DevHlp call.  The device 
  11432. driver does not call DevDone to complete requests in the Strategy routine, 
  11433. rather the device driver returns to the kernel with the done status. 
  11434.  
  11435.  
  11436. ΓòÉΓòÉΓòÉ 21.3.15. DynamicAPI ΓòÉΓòÉΓòÉ
  11437.  
  11438. ____________________________________________________________
  11439. DynamicAPI          Mode: Kernel, Init
  11440.  
  11441. Create a Ring 0 Call Gate
  11442.  
  11443. This function creates a Ring 0 call gate to a routine in a device driver. 
  11444.  
  11445. C Calling Convention 
  11446.  
  11447. if (DynamicAPI((FARPOINTER) &Worker,USHORT ParamCount,USHORT Flag,
  11448.                (FPUSHORT) &Sel)) err
  11449.  
  11450. &Worker    = 16:16 or 0:32 bit address of driver function
  11451. ParamCount = count of the number of parameters
  11452.              if 16:16 call gate, the number of words
  11453.              if 0:32 call gate, the number of dwords
  11454. Flag       = bit 0 = 1 - 16 bit call gate
  11455.              bit 0 = 0 - 32 bit call gate
  11456.              bit 1 = 1 - 16:16 function address
  11457.              bit 1 = 0 - linear function address
  11458. Sel        = far pointer to Selector returned
  11459.  
  11460. COMMENTS 
  11461.  
  11462. The maximum number of parameters cannot exceed 16.  ParamCount cannot be larger 
  11463. than 16 for 16:16 call gates or 8 for 0:32 call gates. 
  11464.  
  11465. EXAMPLE 
  11466.  
  11467.  
  11468. // get ring 0 call gate
  11469.  
  11470. if(DynamicAPI((FARPOINTER)test_it,0,3,(FARPOINTER)&Newsel))
  11471.  return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  11472.  
  11473. // send back call gate to application
  11474.  
  11475. if (MoveBytes((FARPOINTER) &Newsel,
  11476.  rp->s.IOCtl.buffer,
  11477.  2))
  11478.   return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  11479.  
  11480.  
  11481. ΓòÉΓòÉΓòÉ 21.3.16. EOI ΓòÉΓòÉΓòÉ
  11482.  
  11483. ____________________________________________________________
  11484. EOI              Mode: Interrupt, Init
  11485.  
  11486. Issue an EOI to the Interrupt Controller
  11487.  
  11488. This routine is used to issue an End-Of-Interrupt to the cascaded 8259 priority 
  11489. interrupt controllers.  If the interrupt is located on the second 8259, and EOI 
  11490. is also issued to the lower 8259. 
  11491.  
  11492. C Calling Convention 
  11493.  
  11494. EOI(USHORT IRQnum)
  11495.  
  11496. IRQnum = IRQ number to issue EOI against
  11497.  
  11498. COMMENTS 
  11499.  
  11500. This routine is used to issue an End-Of-Interrupt to the 8259 interrupt 
  11501. controllers on behalf of a device driver interrupt handler.  If the specified 
  11502. interrupt level is for the slave 8259 interrupt controller, then this routine 
  11503. will issue the EOI to both the master and slave 8259s. 
  11504.  
  11505. On ISA bus systems, the interrupt handler is entered with the interrupts off. 
  11506. To prevent the nesting of interrupts, interrupts should not be re-enabled until 
  11507. the EOI has been issued.  On PS/2 and EISA systems, the interrupt handler is 
  11508. entered with interrupts enabled.  In this case, to prevent nested interrupts, 
  11509. the interrupt routine should disable interrupts, issue the EOI, and return to 
  11510. OS/2, where interrupts will be re-enabled. 
  11511.  
  11512. EXAMPLE 
  11513.  
  11514. EOI(10);
  11515.  
  11516.  
  11517. ΓòÉΓòÉΓòÉ 21.3.17. FreeCtxHook ΓòÉΓòÉΓòÉ
  11518.  
  11519. ____________________________________________________________
  11520. FreeCtxHook          Mode: Kernel, Init
  11521.  
  11522. Free a Context Hook
  11523.  
  11524. FreeCtxHook frees a context hook allocated by the AllocateCtxHook DevHlp 
  11525. service. 
  11526.  
  11527. C Calling Convention 
  11528.  
  11529. if (FreeCtxHook((LHANDLE) HookHandle)) error
  11530.  
  11531. HookHandle  =  handle from AllocateCtxHook
  11532.  
  11533.  
  11534. ΓòÉΓòÉΓòÉ 21.3.18. FreeGDTSelector ΓòÉΓòÉΓòÉ
  11535.  
  11536. ____________________________________________________________
  11537. FreeGDTSelector        Mode: Kernel, Init
  11538.  
  11539. Free Selector Allocated with AllocGDTSelector
  11540.  
  11541. FreeGDTSelector frees a selector allocated with the AllocGDTSelector DevHlp 
  11542. service. 
  11543.  
  11544. C Calling Convention 
  11545.  
  11546. if (FreeGDTSelector(USHORT Sel)) error
  11547.  
  11548. Sel  =  selector allocated by AllocGDTSelector call
  11549.  
  11550. COMMENTS 
  11551.  
  11552. The selector passed to this function must have been allocated using 
  11553. AllocGDTSelector.  This is verified and an error is returned if the selector 
  11554. was not properly allocated. 
  11555.  
  11556.  
  11557. ΓòÉΓòÉΓòÉ 21.3.19. FreeLIDEntry ΓòÉΓòÉΓòÉ
  11558.  
  11559. ____________________________________________________________
  11560. FreeLIDEntry         Mode: Kernel, Init
  11561.  
  11562. Release a Logical ID
  11563.  
  11564. This routine is used to release a Logical ID.  This can be done at either 
  11565. DEINSTALL or when the device driver is closed. 
  11566.  
  11567. C Calling Convention 
  11568.  
  11569. if (FreeLIDEntry(USHORT Lid)) error
  11570.  
  11571. Lid = LID obtained from a previous GetLIDEntry DevHlp call
  11572.  
  11573. COMMENTS 
  11574.  
  11575. The attempt to free a Logical ID not owned by the device driver, or that does 
  11576. not exist, will fail. 
  11577.  
  11578. EXAMPLE 
  11579.  
  11580.  
  11581. if (!(GetLIDEntry(0x10, 0, 1, &lid))) /* get LID for POS   */
  11582.  FreeLIDEntry(lid);
  11583.  
  11584.  
  11585. ΓòÉΓòÉΓòÉ 21.3.20. FreePhys ΓòÉΓòÉΓòÉ
  11586.  
  11587. ____________________________________________________________
  11588. FreePhys           Mode: Kernel, Init
  11589.  
  11590. Free Physical Memory
  11591.  
  11592. FreePhys is used to release memory previously allocated by the AllocPhys DevHlp 
  11593. call. 
  11594.  
  11595. C Calling Convention 
  11596.  
  11597. if (FreePhys((PHYSADDR) &PhysAddress)) error
  11598.  
  11599. &PhysAddress = 32 bit physical address of allocated memory
  11600.  
  11601. COMMENTS 
  11602.  
  11603. Any memory that the device driver allocated by way of the AllocPhys should be 
  11604. released prior to device driver termination. 
  11605.  
  11606.  
  11607. ΓòÉΓòÉΓòÉ 21.3.21. FreeReqPacket ΓòÉΓòÉΓòÉ
  11608.  
  11609. ____________________________________________________________
  11610. FreeReqPacket         Mode: Kernel
  11611.  
  11612. Free an Allocated Request Packet
  11613.  
  11614. This function is used to release a Request Packet previously allocated by a 
  11615. AllocReqPacket DevHlp call. 
  11616.  
  11617. C Calling Convention 
  11618.  
  11619. void FreeReqPacket ((PREQPACKET) &RequestPacket)
  11620.  
  11621. &RequestPacket = far pointer to Request Packet
  11622.  
  11623. COMMENTS 
  11624.  
  11625. FreeReqPacket should only be performed on a Request Packet that was previously 
  11626. allocated by an AllocReqPacket DevHlp call.  The DevDone function should not be 
  11627. used to return an allocated Request Packet. Since the system has a limited 
  11628. number of Request Packets, it is important that a device driver free up 
  11629. allocated Request Packets as soon as possible. 
  11630.  
  11631.  
  11632. ΓòÉΓòÉΓòÉ 21.3.22. GetDescInfo ΓòÉΓòÉΓòÉ
  11633.  
  11634. ____________________________________________________________
  11635. GetDesclnfo          Mode: Kernel, Interrupt, Init
  11636.  
  11637. Return Information on the Contents of Descriptor
  11638.  
  11639. GetDesclnfo is used to obtain information about a descriptor's contents. 
  11640.  
  11641. C Calling Convention 
  11642.  
  11643. if (GetDsecInfo(USHORT Selector,(FPUSHORT) &AX_Reg,(FPULONG) &ECX_Reg,
  11644.                (FPULONG) &EDX_Reg)) error
  11645.  
  11646. Selector  =  any selector
  11647. AX_Reg    =  AX register  (see below)
  11648. ECX_Reg   =  ecx register (see below)
  11649. EDX_Reg   =  edx register (see below)
  11650.  
  11651. Register Contents Returned
  11652.  
  11653. If descriptor was a call gate:
  11654.  
  11655.    AL (LOUSHORT AX_Reg)  = descriptors access byte
  11656.    AH (HIUSHORT AX_Reg)  = number of parameters
  11657.    CX (LOUSHORT ECX_Reg) = selector
  11658.    EDX                   = 32-bit offset (0:32 addressing)
  11659.  
  11660. If descriptor was not a call gate:
  11661.  
  11662.    AL (LOUSHORT AX_Reg)  = descriptors access byte
  11663.    AH (HIUSHORT AX_Reg   = BIG and GRANULARITY fields of attribute
  11664.                            byte
  11665.    ECX                   = the 32 bit linear address in descriptor
  11666.    EDX                   = the 32 bit byte-granular size of the
  11667.                            descriptor(0 if 4GB)
  11668.  
  11669. COMMENTS 
  11670.  
  11671. When called for an LDT (Local Descriptor Table) descriptor, GetDesclnfo may 
  11672. block other threads from executing.  Therefore, at interrupt time, this routine 
  11673. is callable only on GDT (Global Descriptor Table) descriptors.  The routine can 
  11674. be called with either type of descriptor at initialization or task time. 
  11675.  
  11676.  
  11677. ΓòÉΓòÉΓòÉ 21.3.23. GetDeviceBlock ΓòÉΓòÉΓòÉ
  11678.  
  11679. ____________________________________________________________
  11680. GetDeviceBlock        Mode: Init
  11681.  
  11682. Get ABIOS Device Block
  11683.  
  11684. GetDeviceBlock returns an ABIOS Device block pointer.  The function returns a 
  11685. protect mode pointer only.  Real mode pointers are not returned, rather the 
  11686. data is initialized to zero. 
  11687.  
  11688. Calling Sequence 
  11689.  
  11690. if (GetDeviceBlock(USHORT Lid,far (FARPOINTER) &ABIOSDeviceBlock)) error
  11691.  
  11692. Lid               = lid from GetLIDEntry
  11693. &ABIOSDeviceBlock = far pointer to device block data
  11694.  
  11695. COMMENTS 
  11696.  
  11697. This function will always fail on non-PS/2 machines. 
  11698.  
  11699. Refer to the IBM Personal System/2 and Personal Computer BIOS Interface 
  11700. Technical Reference, part number S68X-2341-00, for more detailed information on 
  11701. the use of ABIOS and its associated data structures. 
  11702.  
  11703.  
  11704. ΓòÉΓòÉΓòÉ 21.3.24. GetDOSVar ΓòÉΓòÉΓòÉ
  11705.  
  11706. ____________________________________________________________
  11707. GetDOSVar           Mode: Kernel, Init
  11708.  
  11709. Get the Address of a System Variable
  11710.  
  11711. This routine is used to return the address of a system variable.
  11712.  
  11713. C Calling Convention
  11714.  
  11715. if (GetDOSVar(USHORT ID,(FPFARPOINTER) &Ptr)) error
  11716.  
  11717. ID   = identifier number of the variable
  11718. &Ptr = far pointer to address of returned pointer
  11719.  
  11720. COMMENTS 
  11721.  
  11722. Table A-4 contains a list of read-only variables that can be examined. 
  11723.  
  11724. ΓöîΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  11725. ΓöéID  ΓöéDescription of Variable       Γöé
  11726. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11727. Γöé1   ΓöéSysINFOseg:WORD - segment     Γöé
  11728. Γöé    Γöéaddress of the System Global  Γöé
  11729. Γöé    ΓöéInfoSeg. Valid at both task   Γöé
  11730. Γöé    Γöétime and interrupt time, but  Γöé
  11731. Γöé    Γöénot Init time.                Γöé
  11732. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11733. Γöé2   ΓöéLocINFOseg:DWORD -            Γöé
  11734. Γöé    ΓöéSelector/Segment address of   Γöé
  11735. Γöé    Γöéthe local (LDT) INFO segment. Γöé
  11736. Γöé    ΓöéValid only at task time.      Γöé
  11737. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11738. Γöé3   ΓöéReserved                      Γöé
  11739. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11740. Γöé4   ΓöéVectorSDF:DWORD - Pointer to  Γöé
  11741. Γöé    Γöéthe stand-alone dump facility.Γöé
  11742. Γöé    ΓöéValid at both task time and   Γöé
  11743. Γöé    Γöéinterrupt time.               Γöé
  11744. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11745. Γöé5   ΓöéVectorReboot:DWORD - Pointer  Γöé
  11746. Γöé    Γöéto restart OS/2. Valid at bothΓöé
  11747. Γöé    Γöétask time and interrupt time. Γöé
  11748. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11749. Γöé6   ΓöéReserved                      Γöé
  11750. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11751. Γöé7   ΓöéYieldFlag:BYTE - Indicator forΓöé
  11752. Γöé    Γöéperforming time- critical     Γöé
  11753. Γöé    Γöéyields. Valid only at task    Γöé
  11754. Γöé    Γöétime.                         Γöé
  11755. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11756. Γöé8   ΓöéTCYieldFlag:BYTE - Indicator  Γöé
  11757. Γöé    Γöéfor performing time-critical  Γöé
  11758. Γöé    Γöéyields. Valid only at task    Γöé
  11759. Γöé    Γöétime.                         Γöé
  11760. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11761. Γöé9   ΓöéReserved                      Γöé
  11762. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11763. Γöé0x0aΓöéReserved                      Γöé
  11764. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11765. Γöé0x0bΓöéDOS mode Code Page Tag        Γöé
  11766. Γöé    ΓöéPointer: DWORD Segment/offset Γöé
  11767. Γöé    Γöéof the current code page tag  Γöé
  11768. Γöé    Γöéof DOS mode. Valid only at    Γöé
  11769. Γöé    ΓöéStrategy time.                Γöé
  11770. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11771. Γöé0x0dΓöé16:16 pointer in the          Γöé
  11772. Γöé    ΓöéInterruptLevel when called in Γöé
  11773. Γöé    Γöéthe interrupt context         Γöé
  11774. Γö£ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  11775. Γöé0x0eΓöé16:16 pointer to table of     Γöé
  11776. Γöé    Γöéregistered ADD entry points   Γöé
  11777. ΓööΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  11778. Table A-4. Read Only System Variables 
  11779.  
  11780. EXAMPLE 
  11781.  
  11782. /* get current processes id */
  11783.  
  11784. if (GetDOSVar(2,&ptr))
  11785.  return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  11786.  
  11787. /* get process info */
  11788.  
  11789. liptr = *((PLINFOSEG far *) ptr);
  11790.  
  11791. /* if this device never opened, can be opened by any process       */
  11792.  
  11793. if ( opencount == 0)          /* first time this device opened     */
  11794.  savepid = liptr->pidCurrent; /* save current process id           */
  11795. else
  11796. {
  11797.  if ( savepid != liptr->pidCurrent)  /* another proc tried to open */
  11798.   return (RPDONE | RPERR | RPBUSY ); /* so return error            */
  11799.  
  11800.  ++opencount[dev];                   /* bump counter, same pid     */
  11801. }
  11802. return (RPDONE);
  11803.  
  11804.  
  11805. ΓòÉΓòÉΓòÉ 21.3.25. GetLIDEntry ΓòÉΓòÉΓòÉ
  11806.  
  11807. ____________________________________________________________
  11808. GetLIDEntry          Mode: Kernel, Init
  11809.  
  11810. Get a Logical ID
  11811.  
  11812. This routine is used to obtain a Logical ID (LID) for devices that exist. 
  11813.  
  11814. C Calling Convention 
  11815.  
  11816. if (GetLIDEntry(USHORT DevType,USHORT Spec,USHORT Type,(FPUSHORT) &Lid)) error
  11817.  
  11818. DevID  = device type
  11819. Spec   = 0 - get first unclaimed LID, 1 - the first LID
  11820. Type   = 1 - DMA or POS
  11821.        = 0 - all others
  11822. &Lid   = far pointer to variable where the LID is returned
  11823.  
  11824. COMMENTS 
  11825.  
  11826. GetLIDEntry is used by a device driver to obtain a LID entry.  Because OS/2 
  11827. does not support the Advanced BIOS Sleep/Wake functions, only devices that are 
  11828. "awake" are considered to exist, and thus available to device drivers. 
  11829.  
  11830. This function may be employed in two ways.  One way is for the device driver to 
  11831. specify a relative LID.  Because the ordering of LlDs corresponds to the 
  11832. ordering of physical devices, a device driver that desires to support a certain 
  11833. relative device can determine if a LID entry is available.  (An example is a 
  11834. character device driver that supports COM4; that is, it wishes to get the LID 
  11835. entry for the fourth COM port.) 
  11836.  
  11837. The other way to use this function is for the device driver to request the 
  11838. first available LID for its device type.  (An example is a block device driver 
  11839. that wishes to get the first available LID for diskettes.) 
  11840.  
  11841. In either use of this function, GetLIDEntry will search the ABIOS Common Data 
  11842. Area table for an entry corresponding to the specified device ID. If an entry 
  11843. is located that matches the caller's form of request, it is returned to the 
  11844. caller.  If a LID entry is found but already owned, an error is returned.  If 
  11845. no LID entry is found, an error is also returned. 
  11846.  
  11847. Some LlDs can not be allocated to device drivers, as they are used by the 
  11848. operating system kernel to perform such actions as mode switching. Certain LIDs 
  11849. can be allocated as shared.  For these devices, GetLIDEntry will allow multiple 
  11850. device drivers to access the LID concurrently.  lt is up to the device driver 
  11851. to determine if the device is busy or available for use when needed. 
  11852.  
  11853. EXAMPLE 
  11854.  
  11855. if (!(GetLIDEntry(0x10, 0, 1, &lid))) /* get LID for POS   */
  11856.  FreeLIDEntry(lid);
  11857.  
  11858.  
  11859. ΓòÉΓòÉΓòÉ 21.3.26. InternalError ΓòÉΓòÉΓòÉ
  11860.  
  11861. ____________________________________________________________
  11862. InternalError         Mode: Kernel, Interrupt, Init
  11863.  
  11864. Signal an Internal Error
  11865.  
  11866. This function is called when an internal inconsistency has been detected. 
  11867.  
  11868. C Calling Convention 
  11869.  
  11870. InternalError((PSTRING) &Msg,USHORT MsgLen)
  11871.  
  11872. &Msg   = DS relative offset of message
  11873. MsgLen = length of message
  11874.  
  11875. COMMENTS 
  11876.  
  11877. This DevHlp routine should be used only when an major internal problem is 
  11878. detected.  Continuing from this point may cause serious problems or possible 
  11879. data loss, so the routine never returns.  InternalError should not be used for 
  11880. less than fatal errors. 
  11881.  
  11882. The maximum message length is 128 characters.  Longer messages are truncated to 
  11883. 128 characters.  The device driver name should appear as the first item in the 
  11884. message text. 
  11885.  
  11886.  
  11887. ΓòÉΓòÉΓòÉ 21.3.27. LinToGDTSelector ΓòÉΓòÉΓòÉ
  11888.  
  11889. ____________________________________________________________
  11890. LinToGDTSelector       Mode: Kernel, Interrupt, Init
  11891.  
  11892. Convert a Linear Address to a Virtual Address
  11893.  
  11894. LinToGDTSelector converts a linear address to a virtual (Selector:Offset) 
  11895. address by mapping the given GDT (Global Descriptor Table) selector to the 
  11896. memory region referred to by the given linear address and range.  The size of 
  11897. the range mapped must be less than or equal to 64 kilobytes. 
  11898.  
  11899. C Calling Convention 
  11900.  
  11901. if (LinToGDTSelector(USHORT Selector,LINADDR Address,ULONG Size)) error
  11902.  
  11903. Selector  =  selector allocated by AllocGDTSelector
  11904. Address   =  32 bit linear address
  11905. Size      =  size of memory in bytes
  11906.  
  11907. COMMENTS 
  11908.  
  11909. The memory that is being mapped must be fixed or locked prior to this call. 
  11910. After this call is issued for a particular selector, the addressability will 
  11911. remain valid until the device driver changes its content with a subsequent call 
  11912. to the PageListToGDTSelector, PhysToGDTSel, PhysToGDTSelector, or 
  11913. LinToGDTSelector DevHlp services. 
  11914.  
  11915.  
  11916. ΓòÉΓòÉΓòÉ 21.3.28. LinToPageList ΓòÉΓòÉΓòÉ
  11917.  
  11918. ____________________________________________________________
  11919. LinToPageList         Mode: Kernel, Interrupt, Init
  11920.  
  11921. Returns the Physical Pages Mapped by a Linear Range
  11922.  
  11923. LinToPageList translates a linear address range to an array of PAGELIST 
  11924. structures that describes the physical pages to be mapped. 
  11925.  
  11926. C Calling Convention 
  11927.  
  11928. if (LinToPageList(LINADDR LinAddress,ULONG Size,(FLATPOINTER) &PageList,
  11929.                   FPULONG Elements)) error
  11930.  
  11931. LinAddress   =  32 bit linear starting address
  11932. Size         =  size of the range to translate
  11933. &PageList    =  flat pointer to PageList structure
  11934. Elements     =  number of elements in PageList array
  11935.  
  11936. The linear address range is translated into an array of PAGELIST structures. 
  11937. Each PAGELIST structure describes a single physically contiguous subregion of 
  11938. the physical memory that is mapped by the linear range.  The format of the 
  11939. PAGELIST structure is: 
  11940.  
  11941. typedef struct _PAGELIST
  11942. {
  11943.   ULONG pl_PhysAddr;          // physical address of first byte
  11944.                               // in this subregion
  11945.   ULONG pl_cb;                // Number of contiguous bytes
  11946.                               // starting at pl_PhysAddr
  11947.   }
  11948.  
  11949. COMMENTS 
  11950.  
  11951. The sum of the pl_cb fields in the PageList array produced by this function 
  11952. will be equal to Size. 
  11953.  
  11954. The physical pages that are mapped by the linear range must be fixed or locked 
  11955. prior to this call. 
  11956.  
  11957. It is the device driver's responsibility to insure that enough entries have 
  11958. been reserved for the range of memory being translated (possibly one entry per 
  11959. page in the range, plus one more if the region does not begin on a page 
  11960. boundary). 
  11961.  
  11962.  
  11963. ΓòÉΓòÉΓòÉ 21.3.29. LockSeg ΓòÉΓòÉΓòÉ
  11964.  
  11965. ____________________________________________________________
  11966. LockSeg            Mode: Kernel, Init
  11967.  
  11968. Lock a Caller's Memory Segment
  11969.  
  11970. LockSeg is called by device drivers at Strategy time to lock a caller's memory 
  11971. segment. 
  11972.  
  11973. C Calling Convention 
  11974.  
  11975. if (LockSeg(USHORT Sel,USHORT Type,USHORT Wait,(PLHANDLE) &Lhandle)) error
  11976.  
  11977. Sel      = selector of user's memory from req packet
  11978. Type     = 00 short term, any memory
  11979.          = 01 long term, any memory
  11980.          = 03 long term, high memory
  11981.          = 04 short term, any memory, verify lock
  11982. Wait     = 00 block until available
  11983.          = 01 return if not immediately available
  11984. &Lhandle = far pointer to returned handle
  11985.  
  11986. COMMENTS 
  11987.  
  11988. LockSeg should be called to lock the caller's memory segment before attempting 
  11989. to transfer data from the device driver to the calling application or from the 
  11990. application to the device driver. 
  11991.  
  11992. LockSeg Type 3: 
  11993.  
  11994. For type 3, the segment is marked fixed, and the system may move it into the 
  11995. region reserved for fixed segments.  If the Lock returns no error, the segment 
  11996. is guaranteed to be in high memory.  Type 3 is available only during INIT, and 
  11997. is generally used to reserve extra code or data segments for use by the device 
  11998. driver.  A type 3 Lock cannot be undone. 
  11999.  
  12000. LockSeg Type 4: 
  12001.  
  12002. The segment remains swappable.  lt will not be freed or shrunk until the verify 
  12003. lock is removed. 
  12004.  
  12005. ADDITIONAL COMMENTS 
  12006.  
  12007.  1. Short term locks are less than 2 seconds.  Long term locks are always 
  12008.     greater than 2 seconds.  Unless the device driver operation will be 
  12009.     completed very quickly, do not use the short term LockSeg.  Using up all 
  12010.     swappable memory could cause a system hang if the operating system runs out 
  12011.     of swappable memory. 
  12012.  2. Failure to call UnLockSeg to release the locked segment will result in all 
  12013.     of the GDT entries being used up and the system will halt. 
  12014.  3. If the device driver is entered with a standard device driver function, 
  12015.     such as DosRead or DosWrite, the caller's segment is already locked by the 
  12016.     kernel.  However, if the device driver is entered as a result of an IOCtl 
  12017.     call, the device driver must lock the segment.  Although some documentation 
  12018.     states that the caller's segment should be locked before verifying that it 
  12019.     is valid (with the VerifyAccess call), it is still safe to verify the 
  12020.     segment first and then lock it immediately after the VerifyAccess call. 
  12021.  4. OS/2 2.2 device drivers should always call LockSeg with the wait option 
  12022.     (wait = 0). 
  12023.  
  12024. EXAMPLE 
  12025.  
  12026. /* lock the segment down temp */
  12027.  
  12028. if(LockSeg(
  12029.  SELECTOROF(rp->s.IOCtl.buffer),     /* selector              */
  12030.  0,                                  /* lock for < 2 sec      */
  12031.  0,                                  /* wait for seg lock     */
  12032.  (PLHANDLE) &lock_seg_han))          /* handle returned       */
  12033.   return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  12034.  
  12035.  
  12036. ΓòÉΓòÉΓòÉ 21.3.30. MonFlush ΓòÉΓòÉΓòÉ
  12037.  
  12038. ____________________________________________________________
  12039. MonFlush           Mode: Kernel
  12040.  
  12041. Flush Data from Monitor Chain
  12042.  
  12043. MonFlush removes all data from the specified monitor chain (such as the data 
  12044. stream). 
  12045.  
  12046. C Calling Convention 
  12047.  
  12048. if (MonFlush(SHANDLE Handle,(PERRCODE) &Error))error
  12049.  
  12050. Handle = short (16-bit) monitor handle
  12051. &Error = far pointer to error code
  12052.  
  12053. COMMENTS 
  12054.  
  12055. When a device driver calls MonFlush, the OS/2 monitor dispatcher creates and 
  12056. places a flush record into the monitor chain.  The general format of monitor 
  12057. records requires that every record contains a flag word as the first entry. 
  12058. One of the flags is used to indicate that this record is a flush record.  The 
  12059. flush record consists only of the flag word.  This record is used by monitors 
  12060. along the chain to reset internal state information, and to assure that all 
  12061. internal buffers are flushed.  The flush record must be passed along to the 
  12062. next monitor, because the monitor dispatcher will not process any more 
  12063. information until the flush record is received at the end of the monitor chain. 
  12064. That is, until it is returned to the device driver's monitor chain buffer at 
  12065. the end of the monitor chain 
  12066.  
  12067. Subsequent MonWrite requests will fail (or block) until the flush completes, 
  12068. that is, until the flush record is returned to the device driver's monitor 
  12069. chain buffer. 
  12070.  
  12071.  
  12072. ΓòÉΓòÉΓòÉ 21.3.31. MonCreate ΓòÉΓòÉΓòÉ
  12073.  
  12074. ____________________________________________________________
  12075. MonCreate           Mode: Kernel, Init
  12076.  
  12077. Create a Monitor Chain
  12078.  
  12079. MonCreate creates an initially empty chain of monitors or removes an empty 
  12080. chain of monitors. 
  12081.  
  12082. C Calling Convention 
  12083.  
  12084.  
  12085. if (MonCreate((PSHANDLE) &Handle,(FARPOINTER) &Buf,(FPFUNCTION) &Routine,
  12086.               (PERRCODE) &Error)) error
  12087.  
  12088. &Handle  = far pointer to handle
  12089. &Buf     = far pointer to monitor buffer
  12090. &Routine = far pointer to monitor routine
  12091. &Error   = far pointer to returned error
  12092.  
  12093. COMMENTS 
  12094.  
  12095. This function may be called at task time only. 
  12096.  
  12097. The monitor chain buffer (final buffer) is a buffer owned by the device driver. 
  12098. On calling MonCreate, the first word of this buffer is the length of the buffer 
  12099. in bytes (including the first word). 
  12100.  
  12101. When the monitor chain handle specified is 0, a new monitor chain is created. 
  12102. When the monitor chain handle specified is a handle that was previously 
  12103. returned from a call to MonCreate (that is, Handle != 0) the monitor chain 
  12104. referenced by that handle is destroyed. 
  12105.  
  12106. A monitor chain is a list of monitors, with a device driver monitor chain 
  12107. buffer address and code address as the last element on this list. Data is 
  12108. placed into a monitor chain through the MonWrite function; the monitor 
  12109. dispatcher feeds the data through all registered monitors, putting the 
  12110. resulting data, if any, into the specified device driver monitor chain buffer. 
  12111. When data is placed in this buffer, the device driver's notification routine is 
  12112. called at task time.  The device driver should initiate any necessary action in 
  12113. a timely fashion and return from the notification entry point without delay. 
  12114.  
  12115. If the MonWrite function is called at interrupt time, and if the monitor chain 
  12116. is empty, the device driver notification routine will be called at interrupt 
  12117. time.  Under all other circumstances, it is called at task time.  The MonCreate 
  12118. function establishes one of these monitor chains.  The chains are created empty 
  12119. so that data written into them is placed immediately into the device driver's 
  12120. buffer. 
  12121.  
  12122. This routine can also destroy a monitor chain if the handle parameter (AX) is 
  12123. nonzero.  The nonzero value is the handle of the chain to remove.  If the 
  12124. monitor chain to be removed is not empty (that is, all monitors registered with 
  12125. this chain have not been previously deregistered), an invalid parameter error 
  12126. is returned to the device driver. 
  12127.  
  12128. A MonCreate call must be made before a monitor can be registered with the 
  12129. chain.  This can be done at any time, including during the installation of the 
  12130. device driver at system initialization. 
  12131.  
  12132. The device driver's notification routine is called by the monitor dispatcher 
  12133. when a data record has been placed in the device driver's monitor chain buffer. 
  12134. The device driver must process the contents of the monitor chain buffer before 
  12135. returning to the monitor dispatcher. This entry point will be called in the 
  12136. OS/2 mode only. 
  12137.  
  12138. When the driver's notification routine is called, the first word of the buffer 
  12139. is filled in with the length of the record just sent to the device driver. 
  12140. There is one notification routine call for each record. 
  12141.  
  12142.  
  12143. ΓòÉΓòÉΓòÉ 21.3.32. MonWrite ΓòÉΓòÉΓòÉ
  12144.  
  12145. ____________________________________________________________
  12146. MonWrite           Mode: Kernel, Interrupt
  12147.  
  12148. Give Data to Monitors
  12149.  
  12150. MonWrite passes data records to the monitors for filtering. 
  12151.  
  12152. C Calling Convention 
  12153.  
  12154. if (MonWrite(SHANDLE Handle, (POINTER) &Rec,USHORT Size,USHORT Flag,
  12155.              ULONG SyncTime,far &Error))error
  12156.  
  12157. Handle   = monitor handle
  12158. &Rec     = pointer to data record
  12159. Size     = length of data record
  12160. Flag     = wait flag, explained below
  12161. SyncTime = sync time, see below
  12162. &Error   = address of returned error code
  12163.  
  12164. COMMENTS 
  12165.  
  12166. This function may be called at task time or interrupt time.  The wait flag is 
  12167. set to 0 if the MonWrite request occurs at task or user time and the device 
  12168. driver indicates that the monitor dispatcher is to do the synchronization. 
  12169. That is, if the wait flag is set to 0, the device driver waits until the data 
  12170. can be placed into the monitor chain before the monitor dispatcher returns to 
  12171. the device driver.  If the wait flag is set to 1, the device driver does not 
  12172. wait; and if the data cannot be placed into the monitor chain, the monitor 
  12173. dispatcher will return immediately with the appropriate error.  The wait flag 
  12174. must be set to 1 if the MonWrite request occurs at interrupt time.  Wait flag 
  12175. is set to 2 if the MonWrite request occurs at task or user time, and the device 
  12176. driver indicates that the monitor dispatcher is to do the synchronization for 
  12177. the time in milliseconds, specified in Timeout. 
  12178.  
  12179. The error, NOT_ENOUGH_MEMORY, will be returned to the device driver when the 
  12180. MonWrite call is made and the monitors are not able to receive the data.  If 
  12181. this condition occurs at interrupt time, an overrun occurred. If it occurs at 
  12182. task (or user) time, the process can block. 
  12183.  
  12184. The error, NOT_ENOUGH_MEMORY, also will be returned to the device driver when a 
  12185. flush record, sent to the monitors by a previous MonFlush call, was not 
  12186. returned to the device driver. 
  12187.  
  12188. If the thread on which the device driver calls MonWrite blocks (the device 
  12189. driver specified the wait option) and is awakened because the process that owns 
  12190. the thread is terminating, a call-interrupted error is returned to the device 
  12191. driver.  The device driver must return the error to the caller so that the 
  12192. process can complete termination. 
  12193.  
  12194. Each call to MonWrite will send a single complete record.  The data sent by 
  12195. this call is considered to be a complete record.  A data record must not be 
  12196. longer than two bytes less than the length of the device driver's monitor chain 
  12197. buffer. 
  12198.  
  12199.  
  12200. ΓòÉΓòÉΓòÉ 21.3.33. OpenEventSem ΓòÉΓòÉΓòÉ
  12201.  
  12202. ____________________________________________________________
  12203. OpenEventSem         Mode: Kernel
  12204.  
  12205. Open a 32-bit Shared Event Semaphore
  12206.  
  12207. OpenEventSem opens a 32-bit shared event semaphore. 
  12208.  
  12209. Calling Sequence 
  12210.  
  12211. if (OpenEventSem(LHANDLE Handle)) error
  12212.  
  12213. Handle  =  long handle to semaphore
  12214.  
  12215. COMMENTS 
  12216.  
  12217. OpenEventSem can be called only from a Ring 0 device driver or file system 
  12218. device driver.  The handle passed in must be a handle to a shared event 
  12219. semaphore.  If the handle does not exist, or is not a "shared event" semaphore, 
  12220. then an ERROR_INVALID_HANDLE will be returned. 
  12221.  
  12222. The open/close operations can be nested.  A maximum of 65,534 (64KB - 1) opens 
  12223. per process are allowed for each semaphore at any one time.  If this limit is 
  12224. reached, the next call to OpenEventSem will return an ERROR_TOO_MANY_OPENS.  In 
  12225. order for a process to intentionally destroy a semaphore prior to termination, 
  12226. the number of CloseEventSem calls must equal the number of OpenEventSem calls. 
  12227.  
  12228. The event semaphores were intended to be used for signaling between threads. 
  12229. When an event is reset, any thread that wants to wait on the event will be 
  12230. blocked.  When the event is posted, all threads waiting on the event will run. 
  12231. For example, if thread 1 is allocating a piece of shared memory, then it will 
  12232. reset the event.  Now, any thread waiting to read data from this memory will be 
  12233. blocked.  Threads 2 and 3 want to read or use what is in the memory allocated 
  12234. by thread 1. They will request to wait on the event, and so they will block. 
  12235. After thread 1 is finished allocating and filling in the memory, it will post 
  12236. the event and threads 2 and 3 will run. 
  12237.  
  12238.  
  12239. ΓòÉΓòÉΓòÉ 21.3.34. PageListToGDTSelector ΓòÉΓòÉΓòÉ
  12240.  
  12241. ____________________________________________________________
  12242. PageListToGDTSelector     Mode: Kernel, Interrupt, Init
  12243.  
  12244. Maps a Given Physical Addresses to Selector
  12245.  
  12246. PageListToGDTSelector maps physical addresses described in an array of PAGELIST 
  12247. structures to a GDT (Global Descriptor Table) selector, setting the access byte 
  12248. of the descriptor to the requested type.  The virtual memory needed to map the 
  12249. physical ranges described by the PageList array must not exceed 64 kilobytes. 
  12250.  
  12251. C Calling Convention 
  12252.  
  12253.  
  12254. if (PageListToGDTSelector(USHORT Selector,ULONG Size,(LINADDR) &PageList,
  12255.                           USHORT Access,(FPUSHORT) &ModSelector)) error
  12256.  
  12257. Selector     = selector to map
  12258. Size         = number of bytes to map
  12259. &PageList    = flat pointer to an array of PAGELIST structures
  12260. Access       = descriptor's type and privilege level
  12261. &ModSelector = far pointer to selector returned with modified RPL bits
  12262.  
  12263. &PageList is the flat address of an array of PAGELIST structures. Each PAGELIST 
  12264. structure describes a single physically contiguous subregion of the physical 
  12265. memory to be mapped.  The format of the PAGELIST structure is: 
  12266.  
  12267. typedef struct _PAGELIST
  12268. {
  12269.   ULONG pl_PhysAddr;          // physical address of first byte
  12270.                               // in this subregion
  12271.   ULONG pl_cb;                // Number of contiguous bytes
  12272.                               // starting at pl_PhysAddr
  12273.   }
  12274.  
  12275. COMMENTS 
  12276.  
  12277. The physical memory that is being mapped must be fixed or locked prior to this 
  12278. call.  After this call, offset 0 within the selector will correspond to the 
  12279. first byte in the first entry in the array pointed to by PageList.  If the 
  12280. PageList is an unmodified return array from VMLock or LinToPageList, then the 
  12281. mapping returned from this call will be, byte for byte, the same as the 
  12282. original linear range.  However, if the PageList array was constructed by some 
  12283. other means, or is a concatenation of two or more PAGELIST arrays returned from 
  12284. various other DevHlp services, the selector mapping may be noncontiguous. 
  12285. Because linear addresses must be mapped to physical addresses on a 
  12286. page-granular basis, if the PageList contains physical addresses and sizes that 
  12287. do not directly correspond to page boundaries, then the selector mapping will 
  12288. necessarily contain "holes", which map unrequested front or tail ends of pages 
  12289. that contain requested addresses. 
  12290.  
  12291. The first byte mapped by the selector will correspond to the first byte 
  12292. described in the first entry in the PageList array.  The next n bytes, where n 
  12293. is the size parameter of the first PageList entry, will be mapped contiguously 
  12294. from that point. 
  12295.  
  12296. The offset within the selector of subsequent PageList entries can be computed 
  12297. by the formula 0 + PS - (A mod PS) + (B mod PS), where 0 is the offset within 
  12298. the selector of the byte following the end of the previous PageList entry, PS 
  12299. is the page size (4 kilobytes), A is the physical address of the byte following 
  12300. the end of the previous PageList entry, and B is the physical address of the 
  12301. start of the next PageList entry. 
  12302.  
  12303. After this call has been issued for a particular selector, the addressability 
  12304. will remain valid until the device driver changes its content with a subsequent 
  12305. call to the DevHlp PageListToGDTSelector, PhysToGDTSel, PhysToGDTSelector, or 
  12306. LinToGDTSelector services. 
  12307.  
  12308.  
  12309. ΓòÉΓòÉΓòÉ 21.3.35. PageListToLin ΓòÉΓòÉΓòÉ
  12310.  
  12311. ____________________________________________________________
  12312. PageListToLin         Mode: Kernel, Interrupt, Init
  12313.  
  12314. Maps a Physical Pages to a Linear Address
  12315.  
  12316. PageListToLin maps physical memory pages, described in an array of PageList s 
  12317. structures, to a linear address.  The size of the linear mapping must not 
  12318. exceed 64 kilobytes. 
  12319.  
  12320. C Calling Convention 
  12321.  
  12322. if (PageListToLin(ULONG Size,(FLATPOINTER) &PageList,(PLINADDR) &LinAddr)) error
  12323.  
  12324. Size      = count of bytes of memory to be mapped
  12325. &PageList = flat pointer to PageList structs
  12326. &LinAddr  = far pointer to variable to receive linear address
  12327.  
  12328. Each PAGELIST structure describes a single physically contiguous subregion of 
  12329. the physical memory to be mapped.  The format of the PAGELIST structure is: 
  12330.  
  12331. typedef struct _PAGELIST
  12332. {
  12333.   ULONG pl_PhysAddr;          // physical address of first byte
  12334.                               // in this subregion
  12335.   ULONG pl_cb;                // Number of contiguous bytes
  12336.                               // starting at pl_PhysAddr
  12337.   }
  12338.  
  12339. COMMENTS 
  12340.  
  12341. The physical memory that is being mapped must be fixed or locked prior to this 
  12342. call.  After this call, the first byte within the returned linear range will 
  12343. correspond to the first byte in the first entry in the array pointed to by 
  12344. PageList.  If the PageList is an unmodified return array from VMLock or 
  12345. LinToPageList, then the mapping returned from this call will be, byte for byte, 
  12346. the same as the original linear range. However, if the PageList array was 
  12347. constructed by some other means, or is a concatenation of two or more PageList 
  12348. arrays returned from various other DevHlp services, the linear mapping may be 
  12349. noncontiguous.  Because linear addresses can only be mapped to physical 
  12350. addresses on a page- granular basis, if the PageList contains physical 
  12351. addresses and sizes that do not directly correspond to page boundaries, then 
  12352. the linear mapping will necessarily contain "holes", which map unrequested 
  12353. front or tail ends of pages that contain requested addresses. 
  12354.  
  12355. The first byte in the linear mapping will correspond to the first byte 
  12356. described in the first entry in the PageList array.  The next n bytes, where n 
  12357. is the size parameter of the first PageList entry, will be mapped contiguously 
  12358. from that point. 
  12359.  
  12360. The starting linear address of subsequent PageList entries may be computed by 
  12361. rounding up the linear address of the end of the previous entry to a page 
  12362. boundary, and then adding on the low order 12 bits of the physical address of 
  12363. the target PageList entry. 
  12364.  
  12365. The linear mapping produced by this call is only valid until the caller yields 
  12366. the CPU, or until it issues another PageListToLin call or a PhysToVirt call.  A 
  12367. PageListToLin will also invalidate any outstanding PhysToVirt mappings. 
  12368.  
  12369.  
  12370. ΓòÉΓòÉΓòÉ 21.3.36. PhysToGDTSel ΓòÉΓòÉΓòÉ
  12371.  
  12372. ____________________________________________________________
  12373. PhysToGDTSel         Mode: Kernel, Interrupt, Init
  12374.  
  12375. Maps a Physical Address to a GDT Selector 
  12376.  
  12377. PhysToGDTSel maps a given GDT selector to a specified physical address, setting 
  12378. the access byte of the descriptor to the desired privilege value.  The 
  12379. specified segment size must be less than or equal to 64 kilobytes. 
  12380.  
  12381. C Calling Convention 
  12382.  
  12383. if (PhysToGDTSel(PHYADDR PhysAddr,ULONG Size,SEL Selector,USHORT Access,
  12384.                 (FPUSHORT) &NewSel)) error
  12385.  
  12386. PhysAddr = physical address to be mapped to selector
  12387. Size     = size of segment, must be less than or equal to 64KB
  12388. Selector = GDT selector, from AllocGDTSelector
  12389. Access   = descriptor's type and access level
  12390. &NewSel  = address of returned modified selector
  12391.  
  12392. COMMENTS 
  12393.  
  12394. The physical memory that is being mapped must be fixed or locked prior to this 
  12395. call.  After this call has been issued for a particular selector, the 
  12396. addressability remains valid until the device driver changes its content with a 
  12397. subsequent call to the PhysToGDTSel, PhysToGDTSelector, PageListToGDTSelector, 
  12398. or LinToGDTSelector DevHlp functions. 
  12399.  
  12400.  
  12401. ΓòÉΓòÉΓòÉ 21.3.37. PhysToGDTSelector ΓòÉΓòÉΓòÉ
  12402.  
  12403. ____________________________________________________________
  12404. PhysToGDTSelector       Mode: Kernel, Interrupt, Init
  12405.  
  12406. Map a Physical Address to a GDT Selector
  12407.  
  12408. This function converts a 32-bit address to a GDT selector-offset pair. 
  12409.  
  12410. C Calling Convention 
  12411.  
  12412. if (PhysGDTSelector(PHYSADDR Physaddr,USHORT Len,SEL Sel,(PERRCODE) &Error)) error
  12413.  
  12414. Physaddr = physical address to map selector to
  12415. Len      = length of segment
  12416. Sel      = selector from AllocGDTSelector
  12417. &Error   = far pointer to returned error code
  12418.  
  12419. COMMENTS 
  12420.  
  12421. PhysToGDTSelector is used to provide addressability through a GDT selector to 
  12422. data.  The interrupt handler of a bimodal device driver must be able to address 
  12423. data buffers regardless of the context of the current process (the current LDT 
  12424. will not necessarily address the data space that contains the data buffer that 
  12425. the interrupt handler needs to access).  The GDT selector's addressability will 
  12426. remain valid and the same until another PhysToGDTSelector call is made for the 
  12427. same selector. 
  12428.  
  12429. The AllocGDTSelector function is used at INIT time to allocate the GDT 
  12430. selectors that the device driver may use with the PhysToGDTSelector. 
  12431.  
  12432. PhysToGDTSelector creates selector:offset addressability for a 32-bit physical 
  12433. address.  The selector created, however, does not represent a normal memory 
  12434. segment such as those usually managed by OS/2, and is more of a "fabricated 
  12435. segment" for private use by the device driver.  Such a segment cannot be passed 
  12436. on system calls, and may only be used by the device driver to fetch data. 
  12437.  
  12438. EXAMPLE 
  12439.  
  12440. if (!(SetIRQ(5,(PFUNCTION)INTERRUPT_HANDLER,0)))
  12441. {
  12442.   if (!(AllocGDTSelector(1,(FARPOINTER)&Sel)))
  12443.   {
  12444.      if (!(PhysToGDTSelector(0xd8000,0x1000,Sel,&err)))
  12445.      {
  12446.  
  12447.         /* output initialization message */
  12448.  
  12449.         DosPutMessage(1, 2, CrLf);
  12450.         DosPutMessage(1, 8, devhdr.DHname);
  12451.         DosPutMessage(1, strlen(InitMessage), InitMessage);
  12452.  
  12453.         /* send back our cs and ds end values to os/2 */
  12454.  
  12455.         if (SegLimit(HIUSHORT((void far *) Init), &rp->s.InitExit.finalCS)
  12456.             || SegLimit(HIUSHORT((void far *) InitMessage),
  12457.             &rp->s.InitExit.finalDS))
  12458.               Abort();
  12459.         return(RPDONE);
  12460.      }
  12461.   }
  12462. }
  12463.  
  12464.  
  12465. ΓòÉΓòÉΓòÉ 21.3.38. PhysToUVirt ΓòÉΓòÉΓòÉ
  12466.  
  12467. ____________________________________________________________
  12468. PhysToUVirt          Mode: Kernel, Init
  12469.  
  12470. Map a Physical Address to a User Virtual Address
  12471.  
  12472. PhysToUVirt converts a 32-bit physical address to a valid selector-offset pair 
  12473. addressable out of the current LDT.  Additional information about the selector 
  12474. may be retained by the memory manager if special processing, based on the tag 
  12475. type, is required. 
  12476.  
  12477. C Calling Convention 
  12478.  
  12479. if (PhysToUVirt(PHYSADDR Physaddr,USHORT Len,USHORT Type,
  12480.                (FPFARPOINTER) &Virt)) error
  12481.  
  12482. Physaddr = physical address to map to LDT selector
  12483. Len      = length of fabricated segment
  12484. Type     = create, release (see comments)
  12485. &Virt    = far pointer to returned virtual address
  12486.  
  12487. COMMENTS 
  12488.  
  12489. This function is typically used to provide a caller of a device driver with 
  12490. addressability to a fixed memory area, such as a memory-mapped adapter address. 
  12491. The device driver must know the physical address of the memory area to be 
  12492. addressed. 
  12493.  
  12494. PhysToUVirt creates selector:offset LDT addressability for a 32-bit physical 
  12495. address.  This function is provided so that a device driver can give an 
  12496. application process addressability to a fixed memory area, such as in the 
  12497. BlOS-reserved range from 640KB to 1 MB.  lt can also be used to give a client 
  12498. application addressability to a device driver's data segment. 
  12499.  
  12500. The selector created, however, does not represent a normal memory segment such 
  12501. as those usually managed by OS/2, and is more of a fabricated segment for 
  12502. private use between a device driver and an application.  Data within such a 
  12503. segment cannot be passed on system calls, and may only be used by the receiving 
  12504. application to fetch data variables. 
  12505.  
  12506. In previous releases of OS/2, all LDT selectors returned by the PhysToUVirt 
  12507. Device Helper routine were marked as Application Program Privilege (privilege 
  12508. level 3) selectors.  In OS/2 Version 2.2, the device driver can specify whether 
  12509. the selector should be marked with Application Program Privilege or I/O Privi- 
  12510. lege (privilege level 2). This allows an LDT selector used by a dynamic link 
  12511. library routine, which is running with I/O privilege, to be protected from 
  12512. accidental modification by the application program. 
  12513.  
  12514. EXAMPLE 
  12515.  
  12516. /* map board address to pte */
  12517.  
  12518. if ( PhysToUVirt(DRIVER_BASE,BASE_LENGTH,1,&mem))
  12519.  return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  12520.  
  12521.  
  12522. ΓòÉΓòÉΓòÉ 21.3.39. PhysToVirt ΓòÉΓòÉΓòÉ
  12523.  
  12524. ____________________________________________________________
  12525. PhysToVirt          Mode: Kernel, Interrupt, Init
  12526.  
  12527. Map a Physical Address to a Virtual Address
  12528.  
  12529. PhysToVirt converts a 32-bit address to a valid selector-offset pair. 
  12530.  
  12531. C Calling Convention 
  12532.  
  12533. if (PhysToVirt(PHYSADDR Physaddr,USHORT Len,USHORT Type,
  12534.               (FPFARPOINTER) &Virt)) error
  12535.  
  12536. Physaddr = physical address to map GDT selector to
  12537. Len      = length of fabricated segment
  12538. Type     = must be 0 for returned selector in DS:SI
  12539. &Virt    = far pointer to returned virtual address
  12540.  
  12541. COMMENTS 
  12542.  
  12543. The returned virtual address will not remain valid if the device driver blocks 
  12544. or yields control.  The returned virtual address may also destroyed if the 
  12545. device driver routine that issues the PhysToVirt calls another routine. 
  12546.  
  12547. The device driver must not enable interrupts or change the segment register 
  12548. before the device driver has finished accessing the data area. Any change to 
  12549. the contents of the segment register in question will invalidate the mapping. 
  12550. Once the device driver has finished accessing the data area, it must restore 
  12551. the previous interrupt state. 
  12552.  
  12553. While pointers generated by this routine are in use, the device driver may only 
  12554. call another PhysToVirt request.  No other DevHlp routines can be called, 
  12555. because they may not preserve the special DS/ES values created by the 
  12556. PhysToVirt. 
  12557.  
  12558. The pool of temporary selectors used by PhysToVirt in the OS/2 mode is not 
  12559. dynamically extendable.  The converted addresses are valid as long as the 
  12560. device driver does not relinquish control (Block, Yield, or RET). An interrupt 
  12561. handler may use converted addresses prior to its EOI, with interrupts enabled. 
  12562. Interrupt handlers should issue an UnPhysToVirt if necessary before making the 
  12563. EOI statement.  If an interrupt handler needs to use converted addresses after 
  12564. its EOI, it must protect the converted addresses by running with interrupts 
  12565. disabled.  For performance reasons, a device driver should try to optimize its 
  12566. usage of PhysToVirt and UnPhysToVirt. 
  12567.  
  12568. Under OS/2 2.2, UnPhysToVirt exists for compatibility with older drivers.  It 
  12569. can be eliminated from driver which run exclusively under OS/2 2.2. 
  12570.  
  12571. EXAMPLE 
  12572.  
  12573. // get pointer to screen memory, 16K long
  12574.  
  12575. if(PhysToVirt(0xb8000L,0x4000,0,(FARPOINTER) &Address)) error
  12576.  
  12577.  
  12578. ΓòÉΓòÉΓòÉ 21.3.40. PostEventSem ΓòÉΓòÉΓòÉ
  12579.  
  12580. ____________________________________________________________
  12581. PostEventSem         Mode: Kernel
  12582.  
  12583. Posts a 32-bit shared event semaphore
  12584.  
  12585. PostEventSem posts an event semaphore that was previously reset with 
  12586. ResetEventSem.  If the event is already posted, the post count is incremented 
  12587. and the ERROR_ALREADY_POSTED return code is returned. Otherwise, the event is 
  12588. posted, the post count is set to one, and all threads that called 
  12589. DosWaitEventSem are made runnable. 
  12590.  
  12591. C Calling Convention 
  12592.  
  12593. if (PostEventSem(LHANDLE Handle)) error
  12594.  
  12595. Handle = long handle to event semaphore
  12596.  
  12597. PostEventSem can be called only from a Ring 0 device driver or file system 
  12598. driver.  The handle passed in must be a handle to a shared event semaphore.  If 
  12599. the handle does not exist, is not a "shared event" semaphore, or if the 
  12600. semaphore was not previously opened with OpenEventSem, then 
  12601. ERROR_INVALID_HANDLE will be returned. 
  12602.  
  12603. There is a limit of 65,534 (64KB - 1) posts allowed per event semaphore. If 
  12604. this limit is reached, then the ERROR_TOO_MANY_POSTS return code is returned. 
  12605.  
  12606. To reverse this operation, call ResetEventSem.  This will reset the event, so 
  12607. that any threads that subsequently wait on the event semaphore (with 
  12608. DosWaitEventSem) will be blocked. 
  12609.  
  12610.  
  12611. ΓòÉΓòÉΓòÉ 21.3.41. PullParticular ΓòÉΓòÉΓòÉ
  12612.  
  12613. ____________________________________________________________
  12614. PullParticular        Mode: Kernel, Interrupt
  12615.  
  12616. Remove a Specific Request From a List 
  12617.  
  12618. PullParticular pulls the specified packet from the selected Request Packet 
  12619. linked list.  If the packet is not found, then an indicator is set on return. 
  12620.  
  12621. C Calling Convention 
  12622.  
  12623. if (PullParticular((PQHEAD) &QueueHead,(PREQPACKET) &RequestPacket))error
  12624.  
  12625. &QueueHead     = address of queue head
  12626. &RequestPacket = far pointer to Request Packet
  12627.  
  12628. COMMENTS 
  12629.  
  12630. A device driver uses the PushReqPacket and PullReqPacket DevHlps to maintain a 
  12631. work queue for each of its devices.  PullParticular is used to remove a 
  12632. specific Request Packet from the work queue, typically for the case where a 
  12633. process has terminated before finishing its I/O. 
  12634.  
  12635. PullParticular may also be used to remove Request Packets that were allocated 
  12636. by an AllocReqPacket from the Request Packet linked list. 
  12637.  
  12638.  
  12639. ΓòÉΓòÉΓòÉ 21.3.42. PullReqPacket ΓòÉΓòÉΓòÉ
  12640.  
  12641. ____________________________________________________________
  12642. PullReqPacket         Mode: Kernel, Interrupt
  12643.  
  12644. Remove a Request Packet From a List 
  12645.  
  12646. PullReqPacket pulls the next waiting Request Packet from the selected Request 
  12647. Packet linked list.  If there is no packet in the list, then an indicator is 
  12648. set on return. 
  12649.  
  12650. C Calling Convention 
  12651.  
  12652. if (PullReqPacket((PQHEAD) &QueueHead,(PREQPACKET) &RequestPacket)) error
  12653.  
  12654. &QueueHead     = address of queue head
  12655. &RequestPacket = far pointer to Request Packet
  12656.  
  12657. COMMENTS 
  12658.  
  12659. A device driver uses the PushReqPacket and PullReqPacket DevHlps to maintain a 
  12660. work queue for each of its devices/units.  The device driver must provide the 
  12661. storage for the DWORD work queue head, which defines the start of the Request 
  12662. Packet linked list.  The work queue head must be initialized to 0. 
  12663.  
  12664. PullReqPacket may also be used to remove Request Packets that were allocated by 
  12665. an AllocReqPacket from the Request Packet queue. 
  12666.  
  12667.  
  12668. ΓòÉΓòÉΓòÉ 21.3.43. PushReqPacket ΓòÉΓòÉΓòÉ
  12669.  
  12670. ____________________________________________________________
  12671. PushReqPacket         Mode: Kernel
  12672.  
  12673. Add a Request Packet To a List 
  12674.  
  12675. PushReqPacket adds the current device Request Packet to the linked list of 
  12676. packets to be executed by the device driver. 
  12677.  
  12678. C Calling Convention 
  12679.  
  12680. if (PushReqPacket((PQHEAD) &QueueHead,(PREQPACKET) &RequestPacket)) error
  12681.  
  12682. &QueueHead     = address of queue head
  12683. &RequestPacket = far pointer to of Request Packet
  12684.  
  12685. COMMENTS 
  12686.  
  12687. A device driver uses the PushReqPacket and PullReqPacket DevHlps to maintain a 
  12688. work queue for each of its devices.  The device driver must provide the storage 
  12689. for the DWORD work queue head, which defines the start of the Request Packet 
  12690. linked list.  The work queue head must be initialized to 0. 
  12691.  
  12692. The device driver task-time thread should add all incoming read/write requests 
  12693. to its request list.  The driver task-time thread should then determine whether 
  12694. the interrupt-time thread is active, and if not, it should send the request to 
  12695. the device.  Because the device may be active at this point, the driver 
  12696. task-time thread must turn off interrupts before calling the device; otherwise, 
  12697. a window exists in which the device finishes processing the request before the 
  12698. packet is put on the list. 
  12699.  
  12700. PushReqPacket may also be used to place Request Packets that were allocated by 
  12701. an AllocReqPacket in the Request Packet work queue. 
  12702.  
  12703.  
  12704. ΓòÉΓòÉΓòÉ 21.3.44. QueueFlush ΓòÉΓòÉΓòÉ
  12705.  
  12706. ____________________________________________________________
  12707.  
  12708. QueueFlush          Mode: Kernel, Interrupt
  12709.  
  12710. Clear a Character Queue 
  12711.  
  12712. QueueFlush clears the character queue structure that is specified (it empties 
  12713. the buffer). 
  12714.  
  12715. C Calling Convention 
  12716.  
  12717. if (QueueFlush((PCHARQUEUE) &CharQueue)) error
  12718.  
  12719. &CharQueue = address of DS relative CHARQUEUE
  12720.  
  12721. COMMENTS 
  12722.  
  12723. QueueFlush operates on the simple character queue structure initialized by 
  12724. QueueInit. 
  12725.  
  12726. typedef struct _CHARQUEUE
  12727. {
  12728.   USHORT Qsize;            // size of queue in bytes
  12729.   USHORT QIndex;           // index of next char out
  12730.   USHORT Qcount            // count of chars in the queue
  12731.   UCHAR  buf[Qsize]        // start of queue buffer
  12732. } CHARQUEUE;
  12733.  
  12734.  
  12735. ΓòÉΓòÉΓòÉ 21.3.45. QueueInit ΓòÉΓòÉΓòÉ
  12736.  
  12737. ____________________________________________________________
  12738. QueueInit           Mode: Kernel, Interrupt, Init
  12739.  
  12740. Initialize a Character Queue 
  12741.  
  12742. QueueInit initializes the specified character queue structure. 
  12743.  
  12744. C Calling Convention 
  12745.  
  12746. if (QueueInit((PCHARQUEUE) &CharQueue)) error
  12747.  
  12748. &CharQueue = address of DS relative CHARQUEUE
  12749.  
  12750. COMMENTS 
  12751.  
  12752. QueueInit must be called before any other queue manipulation subroutine. Prior 
  12753. to this call, the device driver must allocate the character queue buffer with 
  12754. the following queue header and initialize the Qsize field. 
  12755.  
  12756. typedef struct _CHARQUEUE
  12757. {
  12758.   USHORT Qsize;            // size of queue in bytes
  12759.   USHORT QIndex;           // index of next char out
  12760.   USHORT Qcount            // count of chars in the queue
  12761.   UCHAR  buf[Qsize]        // start of queue buffer
  12762. } CHARQUEUE;
  12763.  
  12764.  
  12765. ΓòÉΓòÉΓòÉ 21.3.46. QueueRead ΓòÉΓòÉΓòÉ
  12766.  
  12767. ____________________________________________________________
  12768. QueueRead           Mode: Kernel, Interrupt
  12769.  
  12770. Read a Character From a Queue 
  12771.  
  12772. QueueRead returns and removes a character from the beginning of the specified 
  12773. character queue structure.  If the queue is empty, an indicator is set. 
  12774.  
  12775. C Calling Convention 
  12776.  
  12777. if (QueueRead((PCHARQUEUE) &CharQueue, (FPUCHAR) &Char)) error
  12778.  
  12779. &CharQueue = address of DS relative CHARQUEUE
  12780. &Char      = far pointer to returned char
  12781.  
  12782. COMMENTS 
  12783.  
  12784. QueueRead operates on the simple character queue structure initialized by 
  12785. QueueInit. 
  12786.  
  12787. typedef struct _CHARQUEUE
  12788. {
  12789.   USHORT Qsize;            // size of queue in bytes
  12790.   USHORT QIndex;           // index of next char out
  12791.   USHORT Qcount            // count of chars in the queue
  12792.   UCHAR  buf[Qsize]        // start of queue buffer
  12793. } CHARQUEUE;
  12794.  
  12795.  
  12796. ΓòÉΓòÉΓòÉ 21.3.47. QueueWrite ΓòÉΓòÉΓòÉ
  12797.  
  12798. ____________________________________________________________
  12799. QueueWrite          Mode: Kernel, Interrupt
  12800.  
  12801. Put a Character into a Queue
  12802.  
  12803. QueueWrite adds a character at the end of the specified character queue 
  12804. structure.  If the queue is full, an indicator is set. 
  12805.  
  12806. C Calling Convention 
  12807.  
  12808. if (QueueWrite((PCHARQUEUE) &CharQueue,UCHAR Char)) error
  12809.  
  12810. &CharQueue = address of DS relative queue
  12811. Char       = character to write to queue
  12812.  
  12813. COMMENTS 
  12814.  
  12815. QueueWrite operates on the simple character queue structure initialized by 
  12816. QueueInit. 
  12817.  
  12818. typedef struct _CHARQUEUE
  12819. {
  12820.   USHORT Qsize;            // size of queue in bytes
  12821.   USHORT QIndex;           // index of next char out
  12822.   USHORT Qcount            // count of chars in the queue
  12823.   UCHAR  buf[Qsize]        // start of queue buffer
  12824. } CHARQUEUE;
  12825.  
  12826.  
  12827. ΓòÉΓòÉΓòÉ 21.3.48. Register ΓòÉΓòÉΓòÉ
  12828.  
  12829. ____________________________________________________________
  12830.  
  12831. Register           Mode: Kernel
  12832.  
  12833. Add a Device Monitor 
  12834.  
  12835. Register adds a device monitor to the chain of monitors for a class of device. 
  12836.  
  12837. C Calling Convention 
  12838.  
  12839. if (Register(SHANDLE Handle,USHORT Position,PID,(FARPOINTER) &Inbuf,(OFF) Outbuf,
  12840.             (PERRCODE) &Error)) error
  12841.  
  12842. Handle   = monitor handle
  12843. Position = position in chain
  12844. PID      = PID of owning program
  12845. &Inbuf   = far address of monitor input buffer
  12846. &Outbuf  = short offset of output buffer
  12847. &Error   = far address of returned error code
  12848.  
  12849. COMMENTS 
  12850.  
  12851. This function may be called at task time only.  A monitor chain must have 
  12852. previously been created with MonCreate. 
  12853.  
  12854. A single process may register more than one monitor (with different input and 
  12855. output buffers) with the same monitor chain.  The first word of each of the 
  12856. input and output buffers must contain the length in bytes (length-word 
  12857. inclusive) of the buffers.  The length of the monitor's input and output 
  12858. buffers must be greater than the length of the device driver's monitor chain 
  12859. buffer plus 20 bytes. 
  12860.  
  12861. The input buffer, output buffer offset, and placement flag are supplied to the 
  12862. device driver by the monitor application that is requesting monitor 
  12863. registration (that is, calling DosMonReg). 
  12864.  
  12865. The device driver must identify the monitor chain with the monitor handle 
  12866. returned from a previous MonCreate call.  The device driver can determine the 
  12867. PID of the requesting monitor task from the local infoseg. 
  12868.  
  12869.  
  12870. ΓòÉΓòÉΓòÉ 21.3.49. RegisterBeep ΓòÉΓòÉΓòÉ
  12871.  
  12872. ____________________________________________________________
  12873. RegisterBeep         Mode: Kernel, Init
  12874.  
  12875. Register a Physical Device Driver's Beep Service Entry Point 
  12876.  
  12877. RegisterBeep is called by the clock device driver during initialization time to 
  12878. register the beep service entry point, so that other device drivers or the 
  12879. kernel can generate preempt beeps. 
  12880.  
  12881. C Calling Convention 
  12882.  
  12883. if (RegisterBeep((FPFUNCTION) &BeepRoutine)) error
  12884.  
  12885. &BeepRoutine = 16:16 address of driver's beep routine
  12886.  
  12887.  
  12888. ΓòÉΓòÉΓòÉ 21.3.50. RegisterDeviceClass ΓòÉΓòÉΓòÉ
  12889.  
  12890. ____________________________________________________________
  12891.  
  12892. RegisterDeviceClass      Mode: Kernel, Interrupt, Init
  12893.  
  12894. Registers an ADD Device Class 
  12895.  
  12896. C Calling Convention 
  12897.  
  12898. if (RegisterDeviceClass(&DDName,&CmdHandler,Flags,Class,&Handle)) error
  12899.  
  12900. &DDName     = ASCIIZ driver name
  12901. &CmdHandler = 16:16 address of ADD's command handler
  12902. Flags           = 0 for ADDs
  12903. Class           = 1 for ADDs
  12904. &Handle     = address of returned ADD handle
  12905.  
  12906. COMMENTS 
  12907.  
  12908. If this call fails, the driver should fail quietly by returning RPDONE | 
  12909. ERROR_I24_QUIET+INIT_FAIL. 
  12910.  
  12911. Information about each registered device is kept in a class table.  The driver 
  12912. can obtain a 16:16 pointer to the table by calling the GetDosVar DevHlp with 
  12913. the DHGETDOSV_DEVICECLASSTABLE option.  The class table format is described in 
  12914. Figure A-1. 
  12915.  
  12916. A device driver can derive an ADD's entry point using the ADD's handle by 
  12917. calling GetDOSVar, and then using the code stub shown in Figure A-2. 
  12918.  
  12919. /*
  12920.  * Device Class Structure -  returned by dh_GetDOSVar when
  12921.  * AL=DHGETDOSV_DEVICECLASSTABLE and CX = device_class
  12922.  *
  12923.  */
  12924.  
  12925. #define  MAXDEVCLASSNAMELEN 16   /*   Max len of DevClass Name         */
  12926. #define  MAXDEVCLASSTABLES   2   /*   Max num of DevClass tables       */
  12927.  
  12928. #define  MAXDISKDCENTRIES   32   /*  Max num of entries in DISK table  */
  12929. #define  MAXMOUSEDCENTRIES   3   /*  Max num of entries in Mouse table */
  12930.  
  12931. /* structures for the DeviceClassTable  */
  12932.  
  12933. struct DevClassTableEntry
  12934. {
  12935.   USHORT   DCOffset;
  12936.   USHORT   DCSelector;
  12937.   USHORT   DCFlags;
  12938.   UCHAR    DCName[MAXDEVCLASSNAMELEN];
  12939. };
  12940.  
  12941.  
  12942. struct DevClassTableStruc
  12943. {
  12944.   USHORT                     DCCount;
  12945.   USHORT                     DCMaxCount;
  12946.   struct DevClassTableEntry  DCTableEntries[1];
  12947. };
  12948.  
  12949. Figure A-1. ADD Device Class Table. 
  12950.  
  12951. {
  12952.    USHORT Index = AddHandle-1
  12953.  
  12954.    AddSel = pClassTable->DCTableEntries[Index].DCSelector;
  12955.    AddOff = pClassTable->DCTableEntries[Index].DCOffset;
  12956. }
  12957.  
  12958. Figure A-2. Retreiving an ADD's entry point using GetDOSVar. 
  12959.  
  12960.  
  12961. ΓòÉΓòÉΓòÉ 21.3.51. RegisterTmrDD ΓòÉΓòÉΓòÉ
  12962.  
  12963. ____________________________________________________________
  12964. RegisterTmrDD         Mode: Init
  12965.  
  12966. Return the Kernel Address of the Tmr Value and Rollover Count 
  12967.  
  12968. RegisterTmrDD sends the device driver pointers to the Tmr value and Tmr 
  12969. rollover count in kernel address space. 
  12970.  
  12971. C Calling Convention 
  12972.  
  12973. if (RegisterTmrDD((FPFUNCTION) &TimerEntry,FPFARPOINTER &TmrRollover,
  12974.                   (FPFARPOINTER) &TmrValue)) error
  12975.  
  12976. &TimerEntry = 16:16 address of Timer entry point
  12977.  
  12978. COMMENTS 
  12979.  
  12980. RegisterTmrDD is callable only at Timer device driver initialization time. It 
  12981. returns the Tmr value and rollover count. 
  12982.  
  12983.  
  12984. ΓòÉΓòÉΓòÉ 21.3.52. ResetEventSem ΓòÉΓòÉΓòÉ
  12985.  
  12986. ____________________________________________________________
  12987. ResetEventSem         Mode: Kernel
  12988.  
  12989. Resets a 32-bit shared event semaphore 
  12990.  
  12991. ResetEventSem resets an event semaphore that has previously been opened with 
  12992. OpenEventSem.  The number of posts performed on the event before it was reset 
  12993. is returned to the caller in the pulPostCt parameter.  If the event was already 
  12994. reset, the ERROR ALREADY RESET return code is returned, and zero is returned in 
  12995. the pulPostCt parameter.  lt is not reset a second time. 
  12996.  
  12997. C Calling Convention 
  12998.  
  12999. if (ResetEventSem(LHANDLE Handle,(PLINADDR) &Posts)) error
  13000.  
  13001. Handle = semaphore handle
  13002. &Posts = address of variable to receive # of posts before reset
  13003.  
  13004. COMMENTS 
  13005.  
  13006. ResetEventSem can only be called from a Ring 0 device driver or file system 
  13007. driver.  The handle passed in must be a handle to a shared event semaphore.  If 
  13008. the handle does not exist or is not a "shared event" semaphore, or if the 
  13009. semaphore was not previously opened with OpenEventSem, then 
  13010. ERROR_INVALID_HANDLE will be returned. 
  13011.  
  13012. To reverse this operation, call PostEventSem.  This will post the event, so 
  13013. that any threads that were waiting for the event semaphore to be posted (with 
  13014. DosWaitEventSem) will be allowed to run. 
  13015.  
  13016.  
  13017. ΓòÉΓòÉΓòÉ 21.3.53. ResetTimer ΓòÉΓòÉΓòÉ
  13018.  
  13019. ____________________________________________________________
  13020. ResetTimer          Mode: Kernel, Interrupt, Init
  13021.  
  13022. Reset a Timer Handler
  13023.  
  13024. ResetTimer removes a timer handler for the device driver. 
  13025.  
  13026. C Calling Convention 
  13027.  
  13028. if (ResetTimer((PFUNCTION) &TimerRoutine)) error
  13029.  
  13030. &TimerRoutine = address of DS relative timer
  13031.  
  13032. COMMENTS 
  13033.  
  13034. This function removes a timer handler from the list of timer handlers. Timer 
  13035. handlers are analogous to the user timer interrupt (INT 1Ch) of DOS. 
  13036.  
  13037. DS should be set to the device driver's data segment.  If the device driver had 
  13038. done a PhysToVirt referencing the DS register, it should restore DS to the 
  13039. original value. 
  13040.  
  13041.  
  13042. ΓòÉΓòÉΓòÉ 21.3.54. Run ΓòÉΓòÉΓòÉ
  13043.  
  13044. ____________________________________________________________
  13045. Run              Mode: Kernel, Interrupt
  13046.  
  13047. Release Blocked Threads
  13048.  
  13049. This is the companion routine to Block.  When Run is called, it awakens the 
  13050. threads that were blocked for this particular event identifier. 
  13051.  
  13052. C Calling Convention 
  13053.  
  13054. if (Run((ULONG) ID)) error
  13055.  
  13056. ID = ID of previously Blocked thread
  13057.  
  13058. COMMENTS 
  13059.  
  13060. Run returns immediately to its caller; the awakened threads will be run at the 
  13061. next available opportunity.  Run is often called at interrupt time. 
  13062.  
  13063.  
  13064. ΓòÉΓòÉΓòÉ 21.3.55. SaveMsg ΓòÉΓòÉΓòÉ
  13065.  
  13066. ____________________________________________________________
  13067. SaveMsg (formerly DispMsg)  Mode: Init
  13068.  
  13069. Display Message
  13070.  
  13071. This function displays a message from a base device driver on the system 
  13072. console. 
  13073.  
  13074. C Calling Convention 
  13075.  
  13076. DispMsg((FPSTRING) &MsgTbl)
  13077.  
  13078. &MsgTbl = far pointer to message table struct
  13079.  
  13080. COMMENTS 
  13081.  
  13082. The message is not displayed immediately, but is queued until system 
  13083. initialization retrieves it from the system message file. 
  13084.  
  13085. The structure of the message table is: 
  13086.  
  13087. MsgTbl struct
  13088. {
  13089.  WORD     Message ID
  13090.  WORD     Number of fill-in items
  13091.  DWORD    Pointer to first fill-in item of ASCII-Z string
  13092.  DWORD    Pointer to second fill-in item of ASCII-Z string
  13093.  DWORD    Pointer to last fill-in item of ASCII-Z string
  13094.  }
  13095.  
  13096. The messages are obtained, by ordinal, from the system message file OSO001.msg 
  13097. with DosGetMessage.  The driver can substitute elements of the message with its 
  13098. own message, but leave country and language-specific data intact.  For 
  13099. instance, the word "printer", in English, would be different for each country. 
  13100. The driver can use the data contained in the message file to build a buffer of 
  13101. data to send to the display device.  DispMessage then calls DosPutMessage to 
  13102. display the data.  Drivers that utilize SaveMsg can be used without regard to 
  13103. country or language differences. 
  13104.  
  13105. If an error message is displayed, the "press any key to continue" message is 
  13106. displayed unless the CONFIG.SYS file contains PAUSEONERROR=NO. 
  13107.  
  13108. The special message ID 0x 1178 is used when defining the driver's own messages. 
  13109.  
  13110.  
  13111. ΓòÉΓòÉΓòÉ 21.3.56. SchedClockAddr ΓòÉΓòÉΓòÉ
  13112.  
  13113. ____________________________________________________________
  13114. SchedClockAddr        Mode: Kernel, Init
  13115.  
  13116. Get system clock routine
  13117.  
  13118. This service is provided to the clock device driver to allow it to obtain a 
  13119. pointer to the address of the system's clock tick handler, SchedClock. 
  13120. SchedClock must be called on each occurrence of a periodic clock tick. 
  13121.  
  13122. C Calling Convention 
  13123.  
  13124. if (SchedClockAddr((PFARPOINTER) &Ptr)) error
  13125.  
  13126. &Ptr = DS-relative far pointer to returned address
  13127.  
  13128. COMMENTS 
  13129.  
  13130. The clock device driver calls this DevHlp service during the clock device 
  13131. driver's initialization.  SchedClock must be called at interrupt time for each 
  13132. periodic clock tick to indicate the passage of system time.  The "tick" is then 
  13133. dispersed to the appropriate components of the system. 
  13134.  
  13135. The clock device driver's interrupt handler must run with interrupts enabled as 
  13136. the convention, prior to issuing the EOI for the timer interrupt.  Any critical 
  13137. processing, such as updating the fraction-of-seconds count, must be done prior 
  13138. to calling SchedClock. SchedClock must then be called to allow system proc- 
  13139. essing prior to the dismissal of the interrupt.  When SchedClock returns, the 
  13140. clock device driver must issue the EOI and call SchedClock again.  Note that 
  13141. once the EOI has been issued, the device driver's interrupt handler may be 
  13142. reentered.  The DevHlp SchedClock is also reentrant. 
  13143.  
  13144. The device driver must not get the actual address of the SchedClock routine, 
  13145. but instead use the pointer returned by the DevHlp call. 
  13146.  
  13147.  
  13148. ΓòÉΓòÉΓòÉ 21.3.57. SemClear ΓòÉΓòÉΓòÉ
  13149.  
  13150. ____________________________________________________________
  13151. SemClear           Mode: Kernel, Interrupt
  13152.  
  13153. Release a Semaphore
  13154.  
  13155. This function releases a semaphore and restarts any blocked threads waiting on 
  13156. the semaphore. 
  13157.  
  13158. C Calling Convention 
  13159.  
  13160. if (SemClear(LHANDLE Handle)) error
  13161.  
  13162. Handle = handle to semaphore
  13163.  
  13164. COMMENTS 
  13165.  
  13166. A device driver may clear either a RAM semaphore or a system semaphore. The 
  13167. device driver may obtain (own) a semaphore through SemRequest. 
  13168.  
  13169. The semaphore handle for a RAM semaphore is the virtual address of the 
  13170. doubleword of storage allocated for the semaphore.  To access a RAM semaphore 
  13171. at interrupt time, the device driver must locate the semaphore in the device 
  13172. driver's data segment. 
  13173.  
  13174. For a system semaphore, the handle must be passed to the device driver by the 
  13175. caller by way of a generic IOCtl.  The device driver must convert the caller's 
  13176. handle to a system handle with SemHandle. 
  13177.  
  13178. A RAM semaphore can be cleared at interrupt time only if it is in storage that 
  13179. is directly addressable by the device driver, that is, in the device driver's 
  13180. data segment. 
  13181.  
  13182.  
  13183. ΓòÉΓòÉΓòÉ 21.3.58. SemHandle ΓòÉΓòÉΓòÉ
  13184.  
  13185. ____________________________________________________________
  13186. SemHandle           Mode: Kernel, Interrupt
  13187.  
  13188. Obtain a Semaphore Handle 
  13189.  
  13190. This function provides a semaphore handle to the device driver. 
  13191.  
  13192. C Calling Convention 
  13193.  
  13194. if (SemHandle(LHANDLE Handle,USHORT Flag,(PLHANDLE) &NewHandle)) error
  13195.  
  13196. Handle     = handle of user's semaphore
  13197. Flag       = see comments
  13198. &NewHandle = pointer to new DD-specific handle
  13199.  
  13200. COMMENTS 
  13201.  
  13202. This function is used to convert the semaphore handle (or user "key") provided 
  13203. by the caller of the device driver to a system handle that the device driver 
  13204. may use.  This handle then becomes the "key" that the device driver uses to 
  13205. reference the system semaphore.  This allows the system semaphore to be 
  13206. referenced at interrupt time by the device driver.  This "key" is also used 
  13207. when the device driver is finished with the system semaphore.  The device 
  13208. driver must call SemHandle with the usage flag, indicating that the device 
  13209. driver is finished with the system semaphore. 
  13210.  
  13211. SemHandle is called at task time to indicate that the system semaphore is 
  13212. IN_USE, and is called at either task time or interrupt time to indicate that 
  13213. the system semaphore is NOT_IN_USE.  IN_USE means that the device driver may be 
  13214. referencing the system semaphore.  NOT_IN_USE means that the device driver has 
  13215. finished using the system semaphore and will not be referencing it again. 
  13216.  
  13217. The "key" of a RAM semaphore is its virtual address.  SemHandle may be used for 
  13218. RAM semaphores.  Because RAM semaphores have no system handles, SemHandle will 
  13219. simply return the RAM semaphore "key" back to the caller. 
  13220.  
  13221. A device driver can determine that a semaphore is a RAM semaphore if the key 
  13222. remains unchanged upon return from the SemHandle function.  If the key returned 
  13223. from SemHandle is different from the one passed to the function, then the 
  13224. device driver can determine that it is a handle for a system semaphore. 
  13225.  
  13226. If carry is returned from this function, the device driver should issue the 
  13227. DevHlp VerifyAccess request with the type of access of Read/Write indicated 
  13228. before assuming that this is a RAM semaphore.  If a RAM semaphore is to be 
  13229. used, it must be accessed only at task time unless it is in locked storage. 
  13230.  
  13231. It is necessary to call SemHandle at task time to indicate that a system 
  13232. semaphore is IN_USE because: 
  13233.  
  13234.  1. The caller-supplied semaphore handle refers to task-specific system 
  13235.     semaphore structures.  These structures are not available at interrupt 
  13236.     time, so SemHandle converts the task-specific handle to a system-specific 
  13237.     handle.  For uniformity, the other semaphore DevHlp functions accept only 
  13238.     system-specific handles, regardless of the mode (task time or interrupt 
  13239.     time). 
  13240.  2. An application could delete a system semaphore while the device driver is 
  13241.     using it.  If a second application were to create a system semaphore soon 
  13242.     after, the system structure used by the original semaphore could be 
  13243.     reassigned.  A device driver that tried to manipulate the original 
  13244.     process's semaphore would inadvertently manipulate the new process's 
  13245.     semaphore.  Therefore, the SemHandle IN-USE indicator increases a counter 
  13246.     so that, although the calling thread may still delete its task-specific 
  13247.     reference to the semaphore, the semaphore remains in the system. 
  13248.  
  13249. A device driver must subsequently call SemHandle with NOT_IN_USE when the 
  13250. semaphore use is done so that the system semaphore structure can be freed. 
  13251. There must be a call to indicate NOT_IN_USE to match every call to indicate 
  13252. IN_USE (one-to-one relationship). 
  13253.  
  13254.  
  13255. ΓòÉΓòÉΓòÉ 21.3.59. SemRequest ΓòÉΓòÉΓòÉ
  13256.  
  13257. ____________________________________________________________
  13258. SemRequest          Mode: Kernel
  13259.  
  13260. Claim a Semaphore
  13261.  
  13262. This function claims a semaphore.  If the semaphore is already owned, the 
  13263. thread in the device driver is blocked until the semaphore is released or until 
  13264. a time-out occurs. 
  13265.  
  13266. C Calling Convention 
  13267.  
  13268. if (SemRequest(LHANDLE Handle,ULONG Timeout,(PERRCODE) &Error)) error
  13269.  
  13270. Handle    = handle of DD semaphore
  13271. Timeout   = how long to wait in ms
  13272. &Error    = far address of variable to receive error code
  13273.  
  13274. COMMENTS 
  13275.  
  13276. SemRequest checks the state of the semaphore.  If it is unowned, SemRequest 
  13277. marks it "owned" and returns immediately to the caller.  If the semaphore is 
  13278. owned, SemRequest will optionally block the device driver thread until the 
  13279. semaphore is unowned, then try again.  The time-out parameter is used to place 
  13280. an upper limit on the amount of time to block before returning to the 
  13281. requesting device driver thread. 
  13282.  
  13283. SemClear is used at either task time or interrupt time to release the 
  13284. semaphore. 
  13285.  
  13286. The semaphore handle for a RAM semaphore is the virtual address of the 
  13287. doubleword of storage allocated for the semaphore.  To access a RAM semaphore 
  13288. at interrupt time, the device driver must locate the semaphore in the device 
  13289. driver's data segment. 
  13290.  
  13291. For a system semaphore, the handle must be passed to the device driver by the 
  13292. caller through a generic IOCtl.  The device driver must convert the caller's 
  13293. handle to a system handle with SemHandle. 
  13294.  
  13295.  
  13296. ΓòÉΓòÉΓòÉ 21.3.60. SendEvent ΓòÉΓòÉΓòÉ
  13297.  
  13298. ____________________________________________________________
  13299. SendEvent           Mode: Kernel, Interrupt
  13300.  
  13301. Indicate an Event
  13302.  
  13303. This routine is called by a device driver to indicate the occurrence of an 
  13304. event. 
  13305.  
  13306. C Calling Convention 
  13307.  
  13308. if (SendEvent(USHORT EventNumber,USHORT Parameter)) error
  13309.  
  13310. EventNumber = number of event (see comments)
  13311. Parameter   = (see comments)
  13312.  
  13313. The device driver events are described in Table A-5. 
  13314.  
  13315. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  13316. ΓöéEvent          ΓöéEvent ΓöéParameter     ΓöéComments                      Γöé
  13317. Γöé               ΓöénumberΓöé              Γöé                              Γöé
  13318. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  13319. ΓöéSession managerΓöé0     Γöé2-byte time   ΓöéWhere the high-order byte is  Γöé
  13320. Γöéhot key from   Γöé      Γöéstamp         Γöéin seconds and the low- order Γöé
  13321. Γöéthe mouse      Γöé      Γöé              Γöébyte is in hundredths of      Γöé
  13322. Γöé               Γöé      Γöé              Γöéseconds.                      Γöé
  13323. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  13324. ΓöéCtrl + Break   Γöé1     Γöé0             Γöé                              Γöé
  13325. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  13326. ΓöéCtrl + C       Γöé2     Γöé0             Γöé                              Γöé
  13327. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  13328. ΓöéCtrl + NumLock Γöé3     ΓöéForeground    Γöénumber                        Γöé
  13329. Γöé               Γöé      Γöésession       Γöé                              Γöé
  13330. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  13331. ΓöéCtrl + PrtSc   Γöé4     Γöé0             Γöé                              Γöé
  13332. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  13333. ΓöéShift + PrtSc  Γöé5     Γöé0             Γöé                              Γöé
  13334. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  13335. ΓöéSession ManagerΓöé6     ΓöéHot Key ID    ΓöéThe keyboard device driver    Γöé
  13336. Γöéhot key from   Γöé      Γöé              Γöéuses the hot key ID, which wasΓöé
  13337. Γöéthe keyboard   Γöé      Γöé              Γöéset by way of keyboard IOCtl  Γöé
  13338. Γöé               Γöé      Γöé              Γöé56H (SET SESSION MANAGER HOT  Γöé
  13339. Γöé               Γöé      Γöé              ΓöéKEY).                         Γöé
  13340. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  13341. ΓöéReboot key     Γöé7     Γöé0             Γöé                              Γöé
  13342. Γöésequence from  Γöé      Γöé              Γöé                              Γöé
  13343. Γöéthe keyboard   Γöé      Γöé              Γöé                              Γöé
  13344. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  13345. Table A-5. Device Driver Events 
  13346.  
  13347.  
  13348. ΓòÉΓòÉΓòÉ 21.3.61. SetIRQ ΓòÉΓòÉΓòÉ
  13349.  
  13350. ____________________________________________________________
  13351. SetIRQ            Mode: Kernel, Init
  13352.  
  13353. Register a Hardware Interrupt Handler
  13354.  
  13355. This service is used to set a hardware interrupt vector to the device driver 
  13356. interrupt handler. 
  13357.  
  13358. C Calling Convention 
  13359.  
  13360. if (SetIRQ(USHORT IRQNumber,(PFUNCTION) &Handler,USHORT SharedFlag)) error
  13361.  
  13362. IRQNumber  = IRQ level
  13363. &Handler   = offset to interrupt handler in 1st code segment
  13364. SharedFlag = shared or unshared interrupt
  13365.  
  13366. COMMENTS 
  13367.  
  13368. The attempt to register an interrupt handler for an IRQ to be Shared will fail 
  13369. if the IRQ is already owned by another device driver as Not Shared, or is the 
  13370. IRQ used to cascade the slave 8259 interrupt controller (IRQ 2). 
  13371.  
  13372. Hardware interrupt sharing is not supported on all systems.  A SetIRQ request 
  13373. to share an interrupt level on a system where sharing is not supported (ISA 
  13374. bus) will return an error. 
  13375.  
  13376. EXAMPLE 
  13377.  
  13378. if(SetIRQ(10,(PFUNCTION)INT_HNDLR,0))
  13379. {
  13380.  /* if we failed, deinstall driver with cs+ds=0 */
  13381.  
  13382.  DosPutMessage(1, 8, devhdr[dev].DHname);
  13383.  DosPutMessage(1,strlen(IntFailMsg),IntFailMsg);
  13384.  rp->s.InitExit.finalCS = (OFF) 0;
  13385.  rp->s.InitExit.finalDS = (OFF) 0;
  13386.   return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  13387. }
  13388.  
  13389.  
  13390. ΓòÉΓòÉΓòÉ 21.3.62. SetTimer ΓòÉΓòÉΓòÉ
  13391.  
  13392. ____________________________________________________________
  13393. SetTimer           Mode: Kernel, Init
  13394.  
  13395. Register a Timer Handler 
  13396.  
  13397. SetTimer adds a timer handler to the list of timer handlers to be called on a 
  13398. timer tick. 
  13399.  
  13400. C Calling Convention 
  13401.  
  13402. if (SetTimer((PFUNCTION) &TimerHandler)) error
  13403.  
  13404. &TimerHandler = offset of timer handler routine in 1st code segment
  13405.  
  13406. COMMENTS 
  13407.  
  13408. The DevHlp SetTimer is a subset of the DevHlp TickCount. 
  13409.  
  13410. This function allows a device driver to add a timer handler to a list of timer 
  13411. handlers called on every timer tick.  A device driver may use a timer handler 
  13412. to drive a non-interrupt device instead of using time-outs with the Block and 
  13413. Run services.  Block and Run are costly on a character-by-character basis; the 
  13414. cost is one or more task switches for each character I/0.  Timer handlers are 
  13415. required to save and restore registers. 
  13416.  
  13417. A maximum of 32 different timer handlers are available in the system. 
  13418.  
  13419. While a timer handler is in the format of a FAR CALL/RETURN routine (when it is 
  13420. finished processing, it performs a return), it operates in the interrupt state. 
  13421. The timer handler is analogous to the user timer (Int 1Ch) handler.  Care 
  13422. should be taken not to remain in the handler very long. 
  13423.  
  13424. Timer handlers are responsible for saving and restoring registers upon entry 
  13425. and exit. 
  13426.  
  13427. IMPORTANT NOTE 
  13428.  
  13429. Drivers that call SetTimer during Init should not make the call until the end 
  13430. of the Init code, just prior to returning the code and data offsets to the 
  13431. kernel.  This is especially important if the timer handler references a 
  13432. variable in the driver╨ós data segment.  If the driver calls SetTimer, then 
  13433. calls other DevHlps, one of the other DevHlps might fail.  When they fail, the 
  13434. Init section returns 0 for the code and data offsets, thereby dereferencing the 
  13435. variable in the data segment.  Since the timer handler is still active, it will 
  13436. get called before the driver finishes its clean-up, causing a general 
  13437. protection fault. 
  13438.  
  13439.  
  13440. ΓòÉΓòÉΓòÉ 21.3.63. SortReqPacket ΓòÉΓòÉΓòÉ
  13441.  
  13442. ____________________________________________________________
  13443.  
  13444. SortReqPacket         Mode: Kernel
  13445.  
  13446. Insert a Request in Sorted Order to a List 
  13447.  
  13448. This routine is used by block (disk) device drivers to add a new request to 
  13449. their work queue.  This routine inserts the Request Packet in the linked list 
  13450. of Request Packets in the order of starting sector number. 
  13451.  
  13452. C Calling Convention 
  13453.  
  13454. if (SortReqPacket((PQHEAD) &QueueHead,(PREQPACKET) &RequestPacket))) error
  13455.  
  13456. &QueueHead     = address of queue head
  13457. &RequestPacket = far address of Request Packet
  13458.  
  13459. COMMENTS 
  13460.  
  13461. The sorting by sector number is aimed at reducing the length and number of head 
  13462. seeks.  This is a simple algorithm and does not account for multiple heads on 
  13463. the media or for a target drive in the Request Packet. SortReqPacket inserts 
  13464. the current Request Packet into the specified linked list of packets, sorted by 
  13465. starting sector number. 
  13466.  
  13467. SortReqPacket may be used to place Request Packets that were allocated by an 
  13468. AllocReqPacket in the Request Packet queue. 
  13469.  
  13470.  
  13471. ΓòÉΓòÉΓòÉ 21.3.64. SysTrace ΓòÉΓòÉΓòÉ
  13472.  
  13473. ____________________________________________________________
  13474. SysTrace           Mode: Kernel
  13475.  
  13476. Add Record To System Trace Buffer 
  13477.  
  13478. SysTrace adds a trace record to the system trace buffer. 
  13479.  
  13480. C Calling Convention 
  13481.  
  13482. if (SysTrace(USHORT MajCode,USHORT MinCode,(FARPOINTER) &TraceData,
  13483.              USHORT DataLength) error
  13484.  
  13485. MajCode    = Major error number
  13486. MinCode    = Minor error number
  13487. &TraceData = Far pointer to relative trace data
  13488. DataLength = Length of trace data, in bytes
  13489.  
  13490. COMMENTS 
  13491.  
  13492. SysTrace provides device drivers with a method of logging device driver events 
  13493. by writing data to the system trace buffer.  Writes to the trace buffer are 
  13494. interrupt protected.  The buffer can be parsed, formatted and viewed later 
  13495. using the TRACEFMT utility, supplied with OS/2 2.x. 
  13496.  
  13497. OS/2 allows for a 63KB maximum size trace buffer.  The call to SysTrace will 
  13498. fail if the buffer is full.  The entry TRACEBUF=nnKB in CONFIG.SYS specifies 
  13499. the trace buffer size.  The default is 4KB.  If the CONFIG.SYS file contains 
  13500. the statement TRACE=OFF, tracing must first be enabled by running TRACE from an 
  13501. OS/2 command line prompt. 
  13502.  
  13503. The system trace facility maintains a list of the major event codes currently 
  13504. enabled for tracing.  Before calling DevHlp SysTrace, the driver must insure 
  13505. that tracing for the particular major code is enabled by checking the specific 
  13506. bit in word xx of the Global Info Seg.  The driver can obtain a pointer to the 
  13507. Global Info Seg by calling DevHlp GetDOSVar. 
  13508.  
  13509.  
  13510. ΓòÉΓòÉΓòÉ 21.3.65. TcYield ΓòÉΓòÉΓòÉ
  13511.  
  13512. ____________________________________________________________
  13513. TCYield            Mode: Kernel
  13514.  
  13515. Yield the CPU 
  13516.  
  13517. This function is similar to the Yield function, except that the CPU may only be 
  13518. yielded to a time-critical thread, if one is available. 
  13519.  
  13520. C Calling Convention 
  13521.  
  13522. TCYield()
  13523.  
  13524. COMMENTS 
  13525.  
  13526. It is not necessary for the device driver to do both a Yield and a TCYield. 
  13527. The TCYield function is a subset of the Yield function. 
  13528.  
  13529. The one part of the kernel that can take a lot of CPU time is in device 
  13530. drivers, particularly those that perform program I/O on long strings of data, 
  13531. or that poll a device.  These device drivers should periodically check the 
  13532. TCYield Flag, and call the TCYield function to yield the CPU to a time-critical 
  13533. thread. 
  13534.  
  13535. The location of the TCYield Flag is obtained from the GetDOSVar call. 
  13536.  
  13537. For performance reasons, the device driver should check the TCYield Flag once 
  13538. every three milliseconds.  If the flag is set, then the device driver should 
  13539. call TCYield. 
  13540.  
  13541. Because the device driver may relinquish control of the CPU, the device driver 
  13542. should not assume that the state of the interrupt flag will be preserved across 
  13543. a call to TCYield. 
  13544.  
  13545.  
  13546. ΓòÉΓòÉΓòÉ 21.3.66. TickCount ΓòÉΓòÉΓòÉ
  13547.  
  13548. ____________________________________________________________
  13549. TickCount           Mode: Kernel, Interrupt, Init
  13550.  
  13551. Modify a Timer 
  13552.  
  13553. TickCount will register a new timer handler, or modify a previously registered 
  13554. timer handler, to be called on every N timer ticks instead of every timer tick. 
  13555.  
  13556. C Calling Convention 
  13557.  
  13558. if (TickCount((PFUNCTION) &TimerRoutine,USHORT Count)) error
  13559.  
  13560. &TimerRoutine = offset of timer handler in 1st code segment
  13561. Count         = number of ticks
  13562.  
  13563. COMMENTS 
  13564.  
  13565. A device driver may use a timer handler to drive a non-interrupt device, 
  13566. instead of using time-outs with the Block and Run services.  Block and Run are 
  13567. costly on a character-by-character basis; the cost is one or more task switches 
  13568. for each character I/O.  Timer handlers are required to save and restore 
  13569. registers. 
  13570.  
  13571. For a previously registered timer handler, TickCount changes the number of 
  13572. ticks that must take place before the timer handler gets control. This will 
  13573. allow device drivers to support the time-out function without needing to count 
  13574. ticks. 
  13575.  
  13576.  
  13577. ΓòÉΓòÉΓòÉ 21.3.67. UnLockSeg ΓòÉΓòÉΓòÉ
  13578.  
  13579. ____________________________________________________________
  13580. UnlockSeg           Mode: Kernel, Init
  13581.  
  13582. Unlock a Memory Segment 
  13583.  
  13584. C Calling Convention 
  13585.  
  13586. if (UnLockSeg(LHANDLE Handle)) error
  13587.  
  13588. Handle = handle to memory area from LockSeg call
  13589.  
  13590. COMMENTS 
  13591.  
  13592. This DevHlp UnLocks a segment previously locked with the LockSeg DevHelp. 
  13593.  
  13594. EXAMPLE 
  13595.  
  13596. if(UnLockSeg(lock_seg_han))
  13597.  return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  13598.  
  13599.  
  13600. ΓòÉΓòÉΓòÉ 21.3.68. UnPhysToVirt ΓòÉΓòÉΓòÉ
  13601.  
  13602. ____________________________________________________________
  13603. UnPhysToVirt         Mode: Kernel, Interrupt, Init
  13604.  
  13605. Mark the Completion of Virtual Address Use 
  13606.  
  13607. UnPhysToVirt is required to mark the completion of address conversion from 
  13608. PhysToVirt. 
  13609.  
  13610. C Calling Convention 
  13611.  
  13612. if (UnPhysToVirt()) error
  13613.  
  13614. COMMENTS 
  13615.  
  13616. For OS/2 1.X, UnPhysToVirt must be called by the same procedure that issued the 
  13617. PhysToVirt when the use of converted addresses is completed and before the 
  13618. procedure returns to its caller.  The procedure that called PhysToVirt may call 
  13619. other procedures before calling UnPhysToVirt. Multiple PhysToVirt calls may be 
  13620. issued prior to issuing the UnPhysToVirt.  Only one call to UnPhysToVirt is 
  13621. needed. 
  13622.  
  13623. Under OS/2 2.2, UnPhysToVirt performs no function, but is left in for 
  13624. compatibility with OS/2 1.X drivers. 
  13625.  
  13626. EXAMPLE 
  13627.  
  13628. if (UnPhysToVirt())
  13629.  return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  13630.  
  13631.  
  13632. ΓòÉΓòÉΓòÉ 21.3.69. UnSetIRQ ΓòÉΓòÉΓòÉ
  13633.  
  13634. ____________________________________________________________
  13635. UnSetIRQ           Mode: Kernel, Interrupt, Init
  13636.  
  13637. Remove a Hardware Interrupt Handler 
  13638.  
  13639. This routine removes the current hardware interrupt handler. 
  13640.  
  13641. C Calling Convention 
  13642.  
  13643. if (UnSetIRQ(USHORT IRQNum)) error
  13644.  
  13645. IRQNum = IRQ level to remove
  13646.  
  13647. COMMENTS 
  13648.  
  13649. DS must point to the device driver's data segment on entry. 
  13650.  
  13651.  
  13652. ΓòÉΓòÉΓòÉ 21.3.70. VerifyAccess ΓòÉΓòÉΓòÉ
  13653.  
  13654. ____________________________________________________________
  13655. VerifyAccess         Mode: Kernel
  13656.  
  13657. Verify Access to Memory 
  13658.  
  13659. This routine verifies that the user process has the correct access rights for 
  13660. the memory that it passed to the device driver.  If the process does not have 
  13661. the needed access rights to the memory, then it will be terminated.  If it does 
  13662. have the needed access rights, these rights are guaranteed to remain valid 
  13663. until the device driver exits its Strategy routine. 
  13664.  
  13665. C Calling Convention 
  13666.  
  13667. if (VerifyAccess(SEL Sel,OFF Off,USHORT Memsize,USHORT Code)) error
  13668.  
  13669. Sel      = selector of memory area
  13670. Off      = offset of memory area
  13671. Memsize  = number of bytes to verify
  13672. Code     = read, read/write. (see comments)
  13673.  
  13674. COMMENTS 
  13675.  
  13676. A device driver can receive addresses to memory as part of a generic IOCtl 
  13677. request from a process.  Because the operating system cannot verify addresses 
  13678. imbedded in the IOCtl command, the device driver must request verification in 
  13679. order to prevent itself from accidentally erasing memory on behalf of a user 
  13680. process.  If the verification test fails, then VerifyAccess will terminate the 
  13681. process. 
  13682.  
  13683. Once the device driver has verified that the process has the needed access to 
  13684. addresses of interest, it does not need to repeat the verification until it 
  13685. yields the CPU.  When the device driver yields the CPU, all address access 
  13686. verifications that it has done become unreliable, except for segments that have 
  13687. been locked.  The device driver could yield the CPU by accessing a 
  13688. not-present-segment, exiting its Strategy routine, or calling a DevHlp service 
  13689. that yields while performing the service. 
  13690.  
  13691. EXAMPLE 
  13692.  
  13693. /* verify caller owns this buffer area */
  13694.  
  13695. if(VerifyAccess(
  13696.  SELECTOROF(rp->s.IOCtl.buffer), /* selector              */
  13697.  OFFSETOF(rp->s.IOCtl.buffer),   /* offset                */
  13698.  4,                              /* 4 bytes               */
  13699.  0) )                            /* read only             */
  13700.  return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  13701.  
  13702.  
  13703. ΓòÉΓòÉΓòÉ 21.3.71. VideoPause ΓòÉΓòÉΓòÉ
  13704.  
  13705. ____________________________________________________________
  13706.  
  13707. VideoPause          Mode: Kernel, Interrupt, Init
  13708.  
  13709. Suspend/Resume Video Active Threads 
  13710.  
  13711. This function is called by device drivers when the controller reports a DMA 
  13712. overrun. VideoPause starts or stops high-priority threads. This halts threads 
  13713. using the CPU for video transfers, which allows the diskette DMA to complete 
  13714. termination properly. 
  13715.  
  13716. C Calling Convention 
  13717.  
  13718. if (VideoPause(USHORT PauseFlag)) error
  13719.  
  13720. PauseFlag = 0 - turn off pause
  13721.           = 1 - turn on pause
  13722. COMMENTS 
  13723.  
  13724. Use this function after a DMA transfer retry has failed.  Turn VideoPause on 
  13725. just long enough to accomplish the DMA transfer; otherwise, impairment of the 
  13726. system could occur.  If multiple device drivers turn VideoPause on, it is not 
  13727. turned off until all device drivers have turned it off. 
  13728.  
  13729.  
  13730. ΓòÉΓòÉΓòÉ 21.3.72. VirtToLin ΓòÉΓòÉΓòÉ
  13731.  
  13732. ____________________________________________________________
  13733. VirtToLin           Mode: Kernel, Interrupt, Init
  13734.  
  13735. Converts a Selector:Offset to a Linear Address 
  13736.  
  13737. VirtToLin converts a Selector:Offset pair into a linear address. 
  13738.  
  13739. C Calling Convention 
  13740.  
  13741. if (VirtToLin((FARPOINTER) VirtAddress,(PLINADDR) &LinAddr)) error
  13742.  
  13743. VirtAddress = 16:16 virtual address
  13744. LinAddr     = variable to receive linear address
  13745.  
  13746. EXAMPLE
  13747.  
  13748. Flags = 0x1a;
  13749.  
  13750. if (VirtToLin((FARPOINTER)PageList,(PLINADDR)&lpPageList));
  13751.  
  13752. if (VirtToLin((FARPOINTER)LockHandle,(PLINADDR)&lpLockHandle));
  13753.  
  13754. if (VMLock(linaddr,100,lpPageList,lpLockHandle,
  13755.      Flags,(FARPOINTER) &Elements))
  13756. {
  13757.    DosPutMessage(1, 2, CrLf);
  13758.    DosPutMessage(1, strlen(LockFailMessage), LockFailMessage);
  13759. }
  13760. else
  13761. {
  13762.    DosPutMessage(1, 2, CrLf);
  13763.    DosPutMessage(1, strlen(LockPassMessage), LockPassMessage);
  13764. }
  13765.  
  13766.  
  13767. ΓòÉΓòÉΓòÉ 21.3.73. VirtToPhys ΓòÉΓòÉΓòÉ
  13768.  
  13769. ____________________________________________________________
  13770. VirtToPhys          Mode: Kernel, Init
  13771.  
  13772. Map a Virtual Address to a Physical Address 
  13773.  
  13774. Converts a selector-offset pair to a 32-bit physical address. 
  13775.  
  13776. C Calling Convention 
  13777.  
  13778. if (VirtToPhys((FARPOINTER) &VirtAddr,(PHYSADDR) &PhysAddr))error
  13779.  
  13780. &VirtAddr = virtual pointer to memory
  13781. &PhysAddr = pointer to returned physical address
  13782.  
  13783. COMMENTS 
  13784.  
  13785. The virtual address should be locked by way of the DevHlp Lock call prior to 
  13786. invoking this function, if the segment is not known to be locked already. 
  13787.  
  13788. This function is typically used to convert a virtual address supplied by a 
  13789. process, by way of a generic IOCtl, in order that the memory may be accessed at 
  13790. interrupt time. 
  13791.  
  13792. EXAMPLE 
  13793.  
  13794. /* get physical address of buffer */
  13795.  
  13796. if (VirtToPhys(
  13797.  (FARPOINTER) rp->s.IOCtl.buffer,    /* the virtual address   */
  13798.  (FARPOINTER) &appl_buffer))     /* physical address      */
  13799.   return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  13800.  
  13801.  
  13802. ΓòÉΓòÉΓòÉ 21.3.74. VMAlloc ΓòÉΓòÉΓòÉ
  13803.  
  13804. ____________________________________________________________
  13805. VMAlloc            Mode: Kernel, Init
  13806.  
  13807. Allocate a Block of Physical Memory 
  13808.  
  13809. VMAlloc allocates virtual memory and, depending on the value of a flag, either 
  13810. commits physical storage or maps virtual memory to a given physical address. 
  13811.  
  13812. C Calling Convention 
  13813.  
  13814. if (VMAlloc(lin_addr,ULONG Size,ULONG Flags,
  13815.            (PLINADDR) &Linaddr)) error
  13816.  
  13817. lin_addr = flat pointer to physical address to be mapped
  13818. Size     = size of object in bytes
  13819. Flags    = flags used for allocation request (see comments)
  13820. &Linaddr = pointer to linear address returned
  13821.  
  13822. COMMENTS 
  13823.  
  13824. VMAlloc obtains a global, Ring 0 linear mapping to a block of memory. The 
  13825. physical address of the memory can be specified for non-system memory, or the 
  13826. system will allocate the block from general system memory.  A linear address is 
  13827. returned to address the memory.  For contiguous fixed allocation requests, the 
  13828. physical address is also returned. 
  13829.  
  13830. The physical address passed to VMAlloc is actually the linear address of a 
  13831. variable containing the physical address to be mapped. 
  13832.  
  13833. Virtual memory is allocated in global (system) address space, unless private 
  13834. process space is requested. 
  13835.  
  13836. Memory requested in process space can only be swappable. 
  13837.  
  13838. If requested, memory allocated in process space can be registered under screen 
  13839. group switch control.  In that case, a task will be denied write access to this 
  13840. memory unless it is in the foreground. 
  13841.  
  13842. Flags 
  13843.  
  13844. Bit 0, if set, specifies the creation of the object in the region below 16 MB. 
  13845. Bit 0 is used by device drivers that cannot support more than 16 megabyte 
  13846. addresses.  If the device driver requests memory below 16 MB, the memory must 
  13847. also be resident at all times. 
  13848.  
  13849. Bit 1, if set, specifies that the object remain in memory at all times and not 
  13850. be swapped or moved. 
  13851.  
  13852. Bit 2, if set, specifies the allocation of swappable memory.  Bit 1 must be 
  13853. clear if bit 2 is set. 
  13854.  
  13855. Bit 3, if set, specifies that the object must be in contiguous memory. Bit 1 
  13856. must also be set if bit 3 is set. 
  13857.  
  13858. Bit 4, if set, specifies linear address mapping for the physical address in the 
  13859. parameters.  If bit 4 is set, virtual memory is mapped to a given physical 
  13860. address.  The physical memory must be fixed or locked.  This could be used for 
  13861. non- system memory, like memory-mapped adapters or the video buffer.  If it is 
  13862. used for system memory, it is the device driver's responsibility to insure that 
  13863. the physical pages corresponding to the PhysAddr will never move or become 
  13864. invalid. 
  13865.  
  13866. Bit 5, if set, specifies that the linear address returned will be in the 
  13867. process address range. 
  13868.  
  13869. Bit 6, if set, specifies that the allocated memory can be registered under 
  13870. screen group switch control, such as a video shadow buffer. Memory-mapping 
  13871. allocated with bit 6 set will be invalid when the process is not in the 
  13872. foreground. 
  13873.  
  13874. Bit 7 is reserved, and should be set to 0. 
  13875.  
  13876. Bit 8, if set, specifies that the memory only be reserved, but not actually 
  13877. mapped.  If bit 8 is set, the linear address returned will be page-aligned. 
  13878. The size requested will be rounded up to the nearest page boundary.  All other 
  13879. allocations may return byte granular size and addresses. 
  13880.  
  13881. Bit 11, if set, specifies that the memory be allocated above the 16MB region. 
  13882. If no memory above 16MB exists, the memory is allocated from existing memory. 
  13883. This bit is valid only at Init time.  Calling VMAlloc with bit 11 set at any 
  13884. other time will return an error. 
  13885.  
  13886. All other bits must be 0. 
  13887.  
  13888. EXAMPLE 
  13889.  
  13890. // use VMAlloc to map the adapter address to a linear address in the
  13891. // global address space
  13892.  
  13893. ULONG   MapAddress  = 0xd8000;
  13894. LINADDR LinAddress  = 0;       // linear address to MapAddress
  13895. LINADDR dev_linaddr = 0;       // for global linear address
  13896.  
  13897. // VMalloc requires a linear address to the physical map address
  13898.  
  13899. VirtToLin((FARPOINTER)&MapAddress,(PLINADDR)&LinAddress);
  13900.  
  13901. if (VMAlloc(LinAddress,0x1000,0x30,(PLINADDR)&dev_linaddr))
  13902. {
  13903.   DosPutMessage(1, 2, CrLf);
  13904.   DosPutMessage(1, strlen(AllocFailMessage), AllocFailMessage);
  13905. }
  13906. else
  13907. {
  13908.   DosPutMessage(1, 2, CrLf);
  13909.   DosPutMessage(1, strlen(AllocPassMessage), AllocPassMessage);
  13910. }
  13911.  
  13912.  
  13913. ΓòÉΓòÉΓòÉ 21.3.75. VMFree ΓòÉΓòÉΓòÉ
  13914.  
  13915. ____________________________________________________________
  13916.  
  13917. VMFree            Mode: Kernel, Init
  13918.  
  13919. Free memory or a mapping 
  13920.  
  13921. VMFree frees memory allocated with VMAlloc, or a mapping created by 
  13922. VMProcessToGlobal, or VMGlobalToProcess. 
  13923.  
  13924. C Calling Convention 
  13925.  
  13926. if (VMFree(LINADDR Linaddr)) error
  13927.  
  13928. Linaddr = 32 bit linear address of memory to release
  13929.  
  13930. COMMENTS 
  13931.  
  13932. All memory mapping allocated by the device driver must be released before 
  13933. device driver termination. 
  13934.  
  13935.  
  13936. ΓòÉΓòÉΓòÉ 21.3.76. VMGlobalToProcess ΓòÉΓòÉΓòÉ
  13937.  
  13938. ____________________________________________________________
  13939. VMGlobalToProcess       Mode: Kernel
  13940.  
  13941. Map a Global Address into Process Address Space 
  13942.  
  13943. VMGlobalToProcess maps an address in the system region of the global address 
  13944. space into an address in the current process's address space. 
  13945.  
  13946. C Calling Convention 
  13947.  
  13948. if VMGlobalToProcess(LINADDR Linaddr,ULONG Len,ULONG Flags,
  13949.                     (PLINADDR) &Plinaddr)) error
  13950.  
  13951. Linaddr   = linear address in global address space
  13952. Len       = length of memory to be mapped
  13953. Flags     = (see comments)
  13954. &Plinaddr = pointer to returned linear address
  13955.  
  13956. COMMENTS 
  13957.  
  13958. The mapping created by this call must be released with VMFree. 
  13959.  
  13960. The address range must not cross object boundaries. 
  13961.  
  13962. The process's address space used in this call is the current process. 
  13963.  
  13964. Flags 
  13965.  
  13966. Bit 0, if set, specifies read/write access, Bit 0 clear specifies read-only 
  13967. access. 
  13968.  
  13969. Bit 1, if set, specifies a map of the 32-bit memory region, using 16-bit 
  13970. selectors. 
  13971.  
  13972. Bit 2, if set, the mapping is tracked for the validation and invalidation of 
  13973. screen buffers. 
  13974.  
  13975. Bit 3, if set, specifies that the memory be allocated on a 4K page boundary. 
  13976.  
  13977. Bits 4-31 must be 0. 
  13978.  
  13979. EXAMPLE 
  13980.  
  13981. if (VMGlobalToProcess(linaddr,0x1000,0x01,(FARPOINTER) &new_linaddr))
  13982.    return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  13983.  
  13984.  
  13985. ΓòÉΓòÉΓòÉ 21.3.77. VMLock ΓòÉΓòÉΓòÉ
  13986.  
  13987. ____________________________________________________________
  13988. VMLock            Mode: Kernel, Init
  13989.  
  13990. Lock a Linear Address Range of Memory Within a Segment 
  13991.  
  13992. VMLock verifies accessibility to a region of memory and locks the memory region 
  13993. into physical memory.  If the region is unavailable, the caller must specify 
  13994. whether VMLock should block until the region is available and locked, or return 
  13995. immediately. 
  13996.  
  13997. C Calling Convention 
  13998.  
  13999. if (VMLock(LINADDR Linaddr,ULONG Len,(PLINADDR) &PageList,
  14000.     (PLINADDR) &LockInfo, ULONG Flags, FPULONG )) error
  14001.  
  14002. Linaddr    = 32 bit linear address of region to lock
  14003. Len        = 32 bit length in bytes
  14004. &PageList  = flat pointer to PAGELIST struct
  14005. &LockInfo  = linear address of 12-byte variable to receive the lock
  14006.              handle
  14007. Flags      = (see comments)
  14008.  
  14009. Each PAGELIST structure will describe a single physically contiguous subregion 
  14010. of the physical memory that was locked.  The format of the PAGELIST structure 
  14011. is: 
  14012.  
  14013. typedef struct _PAGELIST
  14014. {
  14015.   ULONG pl_PhysAddr;          // physical address of first byte
  14016.                               // in this sub-region
  14017.   ULONG pl_cb;                // Number of contiguous bytes
  14018.                               // starting at pl_PhysAddr
  14019. }
  14020.  
  14021. COMMENTS 
  14022.  
  14023. The use of short-term locks for greater than two seconds can prevent an 
  14024. adequate number of pages from being available for system use.  Under these 
  14025. circumstances, a system halt could occur. 
  14026.  
  14027. If satisfying the lock request will reduce the amount of free memory in the 
  14028. system to below a predetermined minimum, both short and long-term locks can 
  14029. fail . 
  14030.  
  14031. Address verification is done automatically with every VMLock request. Locking 
  14032. down memory in fixed physical addresses is done only if the "verify only" bit 
  14033. is not set. 
  14034.  
  14035. lt is the device driver's responsibility to insure that enough entries have 
  14036. been reserved for the range of memory being locked (possibly one entry per page 
  14037. in the range, plus one more if the region does not begin on a page boundary). 
  14038. If this pointer contains the value - 1, then no physical addresses are 
  14039. returned.  This parameter must be - 1 for verify locks. 
  14040.  
  14041. Since locking occurs on a per-page basis, the VMLock service routine will round 
  14042. Linear Address down to the nearest page boundary.  If physically contiguous 
  14043. locking is requested, Length cannot exceed 64 kilobytes; otherwise an error is 
  14044. returned.  Because locking occurs on a per-page basis, the combination of 
  14045. Linear Address + Length will be rounded up to the nearest page boundary. 
  14046.  
  14047. Flags 
  14048.  
  14049. Bit 0, if set, specifies an immediate return if the pages are not available, If 
  14050. bit 0 is 0, the call will block until the pages become available. 
  14051.  
  14052. Bit 1, if set, specifies that the pages be contiguous. 
  14053.  
  14054. Bit 2, if set, specifies that the memory be below the 16-MB address line. 
  14055.  
  14056. Bit 3, if set, specifies that the device driver plans to write to the segment. 
  14057.  
  14058. Bit 4, if set, specifies a long-term lock. 
  14059.  
  14060. Bit 5, if set, specifies a verify-only lock. 
  14061.  
  14062. Bits 6-31 must be 0. 
  14063.  
  14064. EXAMPLE 
  14065.  
  14066. Flags = 0x1a;
  14067.  
  14068. if (VirtToLin((FARPOINTER)PageList,(PLINADDR)&lpPageList));
  14069.  
  14070. if (VirtToLin((FARPOINTER)LockHandle,(PLINADDR)&lpLockHandle));
  14071.  
  14072. if (VMLock(linaddr,100,lpPageList,lpLockHandle,
  14073.      Flags,(FARPOINTER) &Elements))
  14074. {
  14075.    DosPutMessage(1, 2, CrLf);
  14076.    DosPutMessage(1, strlen(LockFailMessage), LockFailMessage);
  14077. }
  14078. else
  14079. {
  14080.    DosPutMessage(1, 2, CrLf);
  14081.    DosPutMessage(1, strlen(LockPassMessage), LockPassMessage);
  14082. }
  14083.  
  14084.  
  14085. ΓòÉΓòÉΓòÉ 21.3.78. VMProcessToGlobal ΓòÉΓòÉΓòÉ
  14086.  
  14087. ____________________________________________________________
  14088. VMProcessToGlobal       Mode: Kernel
  14089.  
  14090. Map a Process Address into Global Address Space 
  14091.  
  14092. VMProcessToGlobal converts an address in the current process address space to 
  14093. an address in the system region of the global address space. 
  14094.  
  14095. C Calling Convention 
  14096.  
  14097. if (VMProcessToGlobal(LINADDR Linaddr,ULONG Len,ULONG Flags,
  14098.     (PLINADDR) &Address)) error
  14099.  
  14100. Linaddr  = linear address within process address space that is to be
  14101.            mapped into a global context
  14102. Len      = len in bytes
  14103. Flags    = (see comments)
  14104. &Address = pointer to linear address returned
  14105.  
  14106. COMMENTS 
  14107.  
  14108. The address range must be on a page boundary and must not cross object 
  14109. boundaries. 
  14110.  
  14111. Flags 
  14112.  
  14113. Bit 0, if set, specifies that the mapping be writable, If clear, the mapping 
  14114. will be read-only. 
  14115.  
  14116. Bits 1-31 must be 0. 
  14117.  
  14118. This call copies the linear mapping from the process's address space to the 
  14119. system - shared address space, which allows the device driver to access the 
  14120. data independent of the current process's context.  The following steps show 
  14121. how you would use the DevHlp services to gain interrupt-time access to a 
  14122. process's buffer. 
  14123.  
  14124.  1. Call VMLock to verify the address and to lock the range of memory needed 
  14125.     into physical memory. 
  14126.  
  14127.  2. Call VMProcessToGlobal to map a process's private address into global 
  14128.     address space.  If the device driver requests it, an array of physical 
  14129.     addresses corresponding to the locked region will be returned.  You may 
  14130.     also map the linear address to a GDT selector by calling LinToGDTSelector. 
  14131.  
  14132.  3. Access the memory using the linear address returned by the call to 
  14133.     VMProcessToGlobal. 
  14134.  
  14135.  4. Call VMFree to remove global mapping to process address space. 
  14136.  
  14137.  5. Call VMUnlock to unlock the object. 
  14138.  
  14139. EXAMPLE 
  14140.  
  14141. if (VMGlobalToProcess(linaddr,0x1000,0x01,(FARPOINTER) &new_linaddr))
  14142.     return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  14143.  
  14144.  
  14145. ΓòÉΓòÉΓòÉ 21.3.79. VMSetMem ΓòÉΓòÉΓòÉ
  14146.  
  14147. ____________________________________________________________
  14148. VMSetMem           Mode: Kernel, Init
  14149.  
  14150. Commit or Decommit Physical Memory 
  14151.  
  14152. VMSetMem commits and decommits physical storage, or changes the type of 
  14153. committed memory reserved with the VMAlloc DevHlp service.  The address range 
  14154. specified must not cross object boundaries.  The range must be entirely of 
  14155. uniform type,that is, all decommitted (invalid), all swappable, or all 
  14156. resident.  The range to be decommitted must be entirely precommitted. 
  14157.  
  14158. C Calling Convention 
  14159.  
  14160. if (VMSetMem(LINADDR Linaddr,ULONG Size,ULONG Flags)) error
  14161.  
  14162. Linaddr  = linear address, page aligned, of memory
  14163. Size     = size in bytes in 4k pages
  14164. Flags    = (see comments)
  14165.  
  14166. COMMENTS 
  14167.  
  14168. The entire region (Linear Address + Size) must lie within a memory object 
  14169. previously allocated with a VMAlloc 'Reserved Only' call 
  14170.  
  14171. Flags 
  14172.  
  14173. Bit 0, if set, specifies that the address range is to be decommitted. 
  14174.  
  14175. Bit 1, if set, specifies that the address range is to be made resident. 
  14176.  
  14177. Bit 2, if set, specifies that the address range is to be made swappable. 
  14178.  
  14179.  
  14180. ΓòÉΓòÉΓòÉ 21.3.80. VMUnLock ΓòÉΓòÉΓòÉ
  14181.  
  14182. ____________________________________________________________
  14183. VMUnlock           Mode: Kernel, Init
  14184.  
  14185. UnLock a Linear Address Range of Memory Within a Segment 
  14186.  
  14187. VMUnlock unlocks a previously locked memory range. 
  14188.  
  14189. C Calling Convention 
  14190.  
  14191. if (VMUnlock(LHANDLE LockHandle)) error
  14192.  
  14193. LockHandle = handle from VMLock
  14194.  
  14195. COMMENTS 
  14196.  
  14197. A successful unlock may modify the caller's lock handle. 
  14198.  
  14199.  
  14200. ΓòÉΓòÉΓòÉ 21.3.81. Yield ΓòÉΓòÉΓòÉ
  14201.  
  14202. ____________________________________________________________
  14203. Yield             Mode: Kernel
  14204.  
  14205. Relinquish the CPU 
  14206.  
  14207. This routine yields the CPU to a scheduled thread of equal or higher priority. 
  14208.  
  14209. C Calling Convention 
  14210.  
  14211. Yield();
  14212.  
  14213. COMMENTS 
  14214.  
  14215. OS/2 is designed so that the CPU is never scheduled preemptively while in 
  14216. kernel mode.  In general, the kernel either performs its job and exits quickly, 
  14217. or it blocks waiting for (usually) I/O or (occasionally) a resource.  lt is not 
  14218. necessary for the device driver to do both a Yield and a TCYield; the Yield 
  14219. function is a superset of the TCYield function. 
  14220.  
  14221. The one part of the kernel that can take a lot of CPU time are device drivers, 
  14222. particularly those that perform program I/O on long strings of data, or that 
  14223. poll the device.  These drivers should periodically check the Yield Flag and 
  14224. call the Yield function to yield the CPU if another process needs it.  Much of 
  14225. the time the context won't switch; Yield switches context only if an equal or 
  14226. higher priority thread is scheduled to run. 
  14227.  
  14228. The address of the Yield Flag is obtained from the GetDOSVar call.  For 
  14229. performance reasons, the device driver should check the Yield Flag once every 3 
  14230. milliseconds.  If the flag is set, then the device driver should call Yield. 
  14231.  
  14232. Because the device driver may relinquish control of the CPU to another thread, 
  14233. the device driver should not assume that the state of the interrupt flag will 
  14234. be preserved across a call to Yield. 
  14235.  
  14236.  
  14237. ΓòÉΓòÉΓòÉ 22. Appendix B - Reference Publications ΓòÉΓòÉΓòÉ
  14238.  
  14239. Bowlds, Pat, Micro Channel Architecture, New York:  Van Nostrand Reinhold, 
  14240. 1991. 
  14241.  
  14242. Deitel, H. M.; Kogan, M. S., The Design of OS/2, New York: Addison-Wesley, 
  14243. 1992. 
  14244.  
  14245. IBM Corporation, IBM Operating System/2 Programming Tools and Information: IBM, 
  14246. 1992. 
  14247.  
  14248. IBM Corporation, IBM OS/2 2.1 Physical Device Driver Reference: IBM, 1992. 
  14249.  
  14250. IBM Corporation, IBM OS/2 2.1 Presentation Driver Reference: IBM, 1992. 
  14251.  
  14252. IBM Corporation, IBM OS/2 2.1 Virtual Device Driver Reference: IBM, 1992. 
  14253.  
  14254. IBM Corporation, IBM OS/2 2.1 Control Program Reference: IBM, 1992. 
  14255.  
  14256. Intel Corporation, iAPX 86/88 User's Manual Hardware Reference: Intel, 1989. 
  14257.  
  14258. Letwin, Gordon, Inside OS/2, Redmond, Washington:  Microsoft Press, 1988. 
  14259.  
  14260.  
  14261. ΓòÉΓòÉΓòÉ 23. Appendix C - Listings ΓòÉΓòÉΓòÉ
  14262.  
  14263.  
  14264. ΓòÉΓòÉΓòÉ 23.1. Device Header, One Device ΓòÉΓòÉΓòÉ
  14265.  
  14266. // sample Device Header, 1 device
  14267.  
  14268. DEVICEHDR devhdr = {
  14269.    (void far *) 0xFFFFFFFF,          // link
  14270.    (DAW_CHR | DAW_OPN | DAW_LEVEL1), // attribute
  14271.    (OFF) STRAT,                      // &strategy
  14272.    (OFF) 0,                          // &IDCroutine
  14273.    "DEVICE1 "                        // device name
  14274.    };
  14275.  
  14276.  
  14277. ΓòÉΓòÉΓòÉ 23.2. Device Header, Two Devices ΓòÉΓòÉΓòÉ
  14278.  
  14279. DEVICEHDR devhdr[2] = {
  14280.    { (void far *) &devhdr[1],    // link to next dev
  14281.    (DAW_CHR | DAW_OPN | DAW_LEVEL1), // attribute
  14282.    (OFF) STRAT1,                     // &strategy
  14283.    (OFF) 0,                          // &IDCroutine
  14284.    "DEVICE1 "
  14285.    },
  14286.  
  14287.    {(void far *) 0xFFFFFFFF,   // link(no more devs)
  14288.    (DAW_CHR | DAW_OPN | DAW_LEVEL1), // attribute
  14289.    (OFF) STRAT2,                    // &strategy
  14290.    (OFF) 0,                         // &IDCroutine
  14291.    "DEVICE2 "
  14292.    }
  14293. };
  14294.  
  14295.  
  14296. ΓòÉΓòÉΓòÉ 23.3. C Startup Routine, One Device ΓòÉΓòÉΓòÉ
  14297.  
  14298. ;
  14299. ;    C startup routine, one device, w/interrupt and timer
  14300. ;
  14301.    PUBLIC  _STRAT
  14302.    PUBLIC  __acrtused
  14303.    PUBLIC  _INT_HNDLR
  14304.    PUBLIC  _TIM_HNDLR
  14305.  
  14306.    EXTRN   _interrupt_handler:near
  14307.    EXTRN   _timer_handler:near
  14308.    EXTRN   _main:near
  14309.  
  14310. _DATA      segment   word public 'DATA'
  14311. _DATA      ends
  14312.  
  14313. CONST      segment   word public 'CONST'
  14314. CONST      ends
  14315.  
  14316. _BSS       segment word public 'BSS'
  14317. _BSS       ends
  14318.  
  14319. DGROUP     group     CONST, _BSS, _DATA
  14320.  
  14321. _TEXT      segment   word public 'CODE'
  14322.  
  14323.            assume    cs:_TEXT,ds:DGROUP,es:NOTHING, ss:NOTHING
  14324.            .286P
  14325. ;
  14326. _STRAT     proc far
  14327. __acrtused:   ; no startup code
  14328. ;
  14329.            push 0
  14330.            jmp start  ;signal device 0
  14331. ;
  14332. start:
  14333.            push es  ;send Request Packet address
  14334.            push bx
  14335.            call _main  ;call driver mainline
  14336.            pop bx  ;restore es:bx
  14337.            pop es
  14338.            add sp,2  ;clean up stack
  14339.            mov word ptr es:[bx+3],ax ;send completion status
  14340.            ret
  14341. ;
  14342. _STRAT     endp
  14343. ;
  14344. _INT_HNDLR proc far
  14345. ;
  14346.            call _interrupt_handler ;handle rupts
  14347.            ret   ;bail out
  14348. ;
  14349. _INT_HNDLR endp
  14350. ;
  14351. _TIM_HNDLR proc far
  14352. ;
  14353.            pusha
  14354.            push es
  14355.            push ds
  14356.            call _timer_handler
  14357.            pop ds
  14358.            pop es
  14359.            popa
  14360.            ret
  14361. ;
  14362. _TIM_HNDLR endp
  14363. ;
  14364. _TEXT      ends
  14365.            end
  14366.  
  14367.  
  14368. ΓòÉΓòÉΓòÉ 23.4. C Startup Routine, Four Devices ΓòÉΓòÉΓòÉ
  14369.  
  14370. ;
  14371. ;    C startup routine, 4 devices
  14372. ;
  14373.    PUBLIC  _STRAT1
  14374.    PUBLIC  _STRAT2
  14375.    PUBLIC  _STRAT3
  14376.    PUBLIC  _STRAT4
  14377.    PUBLIC  __acrtused
  14378.    PUBLIC  _INT_HNDLR
  14379.    PUBLIC  _TIM_HNDLR
  14380.  
  14381.    EXTRN   _interrupt_handler:near
  14382.    EXTRN   _timer_handler:near
  14383.    EXTRN   _main:near
  14384.  
  14385. _DATA      segment word public 'DATA'
  14386. _DATA      ends
  14387.  
  14388. CONST      segment word public 'CONST'
  14389. CONST      ends
  14390.  
  14391. _BSS       segment word public 'BSS'
  14392. _BSS       ends
  14393.  
  14394. DGROUP     group   CONST, _BSS, _DATA
  14395.  
  14396. _TEXT      segment word public 'CODE'
  14397.  
  14398.            assume    cs:_TEXT,ds:DGROUP,es:NOTHING,ss:NOTHING
  14399.            .286P
  14400. ;
  14401. _STRAT1    proc   far
  14402. __acrtused:   ; satisfy EXTRN modules
  14403. ;
  14404.            push 0
  14405.            jmp start  ;signal device 0
  14406.  
  14407. _STRAT1    endp
  14408.  
  14409. _STRAT2    proc far
  14410. ;
  14411.            push 1  ;signal second device
  14412.            jmp start
  14413.  
  14414. _STRAT2    endp
  14415.  
  14416. _STRAT3    proc far
  14417. ;
  14418.            push 2  ;signal third device
  14419.            jmp start
  14420.  
  14421. _STRAT3    endp
  14422.  
  14423. _STRAT4    proc far
  14424. ;
  14425.            push 3  ;signal fourth device
  14426.            jmp start
  14427.  
  14428. ;
  14429. start:
  14430.            push es  ;send Request Pkt address
  14431.            push bx
  14432.            call _main  ;call driver mainline
  14433.            pop bx  ;restore es:bx
  14434.            pop es
  14435.            add sp,2  ;clean up stack
  14436.            mov word ptr es:[bx+3],ax ;send completion status
  14437.            ret
  14438. ;
  14439. _STRAT4    endp
  14440. ;
  14441. _INT_HNDLR proc far
  14442. ;
  14443.            call    _interrupt_handler ;handle rupts
  14444.            ret   ;bail out
  14445. ;
  14446. _INT_HNDLR endp
  14447. ;
  14448. _TIM_HNDLR proc far
  14449. ;
  14450.            pusha
  14451.            push    es
  14452.            push    ds
  14453.            call    _timer_handler
  14454.            pop    ds
  14455.            pop    es
  14456.            popa
  14457.            ret
  14458. ;
  14459. _TIM_HNDLR endp
  14460. ;
  14461. _TEXT      ends
  14462.            end
  14463.  
  14464.  
  14465. ΓòÉΓòÉΓòÉ 23.5. Standard OS/2 Device Driver Include File ΓòÉΓòÉΓòÉ
  14466.  
  14467. //  file drvlib.h
  14468. //   This header file contains definitions intended to go along with
  14469. //   DRVLIB.LIB, a C-callable subroutine library.
  14470. //
  14471. //   This file is for OS/2 2.x
  14472.  
  14473. typedef unsigned char   UCHAR;
  14474. typedef unsigned short  USHORT;
  14475. typedef unsigned short  BOOLEAN;
  14476. typedef unsigned long   ULONG;
  14477. typedef UCHAR near      *PUCHAR;
  14478. typedef UCHAR far       *FPUCHAR;
  14479. typedef USHORT near     *PUSHORT;
  14480. typedef USHORT far      *FPUSHORT;
  14481. typedef ULONG near      *PULONG;
  14482. typedef ULONG far       *FPULONG;
  14483. typedef char near       *PCHAR;
  14484. typedef short near      *PSHORT;
  14485. typedef long near       *PLONG;
  14486. typedef void near       *POINTER;
  14487. typedef POINTER near    *PPOINTER;
  14488. typedef void far        *FARPOINTER;
  14489. typedef FARPOINTER near *PFARPOINTER;
  14490. typedef FARPOINTER far  *FPFARPOINTER;
  14491.  
  14492. typedef USHORT          ERRCODE;    // error code returned
  14493. typedef ERRCODE far     *PERRCODE;  // pointer to an error code
  14494. typedef UCHAR           FLAG;       // 8-bit flag
  14495. typedef FLAG far        *PFLAG;     // pointer to 8-bit flag
  14496. typedef USHORT          SEL;        // 16-bit selector
  14497. typedef SEL near        *PSEL;      // pointer to a selector
  14498. typedef SEL far         *FPSEL;     // far pointer to selector
  14499. typedef USHORT          SEG;        // 16-bit segment
  14500. typedef USHORT          OFF;        // 16-bit offset
  14501. typedef ULONG           LOFF;       // 32-bit offset
  14502. typedef USHORT          PID;        // Process ID
  14503. typedef USHORT          TID;        // Thread ID
  14504. typedef ULONG           PHYSADDR;   // 32-bit physical address
  14505. typedef ULONG           LINADDR;    // 32-bit linear address
  14506. typedef LINADDR  far    *PLINADDR;  // pointer to 32 bit linear address
  14507. typedef PLINADDR far    *PPLINADDR; // pointer to linear address pointer
  14508. typedef PHYSADDR far    *PPHYSADDR; // pointer to 32-bit physical address
  14509. typedef char near       *PSTRING;   // pointer to character string
  14510. typedef char far        *FPSTRING;// far pointer to string
  14511. typedef USHORT          SHANDLE;    // short (16-bit) handle
  14512. typedef SHANDLE far     *PSHANDLE;  // pointer to a short handle
  14513. typedef ULONG           LHANDLE;    // long  (32-bit) handle
  14514. typedef LHANDLE far     *PLHANDLE;  // pointer to a long handle
  14515.  
  14516. //  pointers to functions
  14517.  
  14518. typedef int (pascal near          *PFUNCTION) ();
  14519. typedef int (pascal near * near  *PPFUNCTION) ();
  14520. typedef int (pascal far          *FPFUNCTION) ();
  14521. typedef int (pascal far  * near *PFPFUNCTION) ();
  14522.  
  14523. // macros
  14524.  
  14525. #define FALSE   0
  14526. #define TRUE    1
  14527.  
  14528. #define NP near pascal
  14529.  
  14530. // far pointer from selector-offset
  14531.  
  14532. #define MAKEP(sel, off)     ( (void far *) MAKEULONG(off, sel) )
  14533.  
  14534. // get selector or offset from far pointer
  14535.  
  14536. #define SELECTOROF(p)       ( ((USHORT far *) &(p)) [1])
  14537. #define OFFSETOF(p)         ( ((USHORT far *) &(p)) [0])
  14538.  
  14539. // Combine l(ow) & h(igh) to form a 32 bit quantity.
  14540.  
  14541. #define MAKEULONG(l, h)  ((ULONG)(((USHORT)(l)) | ((ULONG)((USHORT)(h))) << 16))
  14542. #define MAKELONG(l, h)   ((LONG)MAKEULONG(l, h))
  14543. #define MAKEBIGOFFSETOF(p) ((ULONG) (OFFSETOF (p)))
  14544.  
  14545. // Combine l(ow) & h(igh) to form a 16 bit quantity.
  14546.  
  14547. #define MAKEUSHORT(l, h) (((USHORT)(l)) | ((USHORT)(h)) << 8)
  14548. #define MAKESHORT(l, h)  ((SHORT)MAKEUSHORT(l, h))
  14549.  
  14550. // get high and low order parts of a 16 and 32 bit quantity
  14551.  
  14552. #define LOBYTE(w)       LOUCHAR(w)
  14553. #define HIBYTE(w)       HIUCHAR(w)
  14554. #define LOUCHAR(w)      ((UCHAR)(w))
  14555. #define HIUCHAR(w)      (((USHORT)(w) >> 8) & 0xff)
  14556. #define LOUSHORT(l)     ((USHORT)(l))
  14557. #define HIUSHORT(l)     ((USHORT)(((ULONG)(l) >> 16) & 0xffff))
  14558.  
  14559. //  the driver device header
  14560.  
  14561. typedef struct DeviceHdr {
  14562.    struct    DeviceHdr far *DHnext; // pointer to next header, or FFFF
  14563.    USHORT    DHattribute;           // device attribute word
  14564.    OFF       DHstrategy;            // offset of strategy routine
  14565.    OFF       DHidc;                 // offset of IDC routine
  14566.    UCHAR     DHname[8];             // dev name (char) or #units (blk)
  14567.    char      reserved[8];
  14568.    ULONG     bit_strip;             // bit 0 DevIOCtl2, bit 1 32 bit addr
  14569.    } DEVICEHDR;
  14570. typedef DEVICEHDR near *PDEVICEHDR;
  14571.  
  14572. //  driver device attributes word
  14573.  
  14574. #define DAW_CHR    0x8000           // 1=char, 0=block
  14575. #define DAW_IDC    0x4000           // 1=IDC available in this DD
  14576. #define DAW_IBM    0x2000           // 1=non-IBM block format
  14577. #define DAW_SHR    0x1000           // 1=supports shared device access
  14578. #define DAW_OPN    0x0800           // 1=open/close, or removable media
  14579. #define DAW_LEVEL1 0x0080           // level 1
  14580. #define DAW_LEVEL2 0x0100           // level 2 DosDevIOCtl2
  14581. #define DAW_LEVEL3 0x0180           // level 3 bit strip
  14582. #define DAW_GIO    0x0040           // 1=generic IOCtl supported
  14583. #define DAW_CLK    0x0008           // 1=CLOCK device
  14584. #define DAW_NUL    0x0004           // 1=NUL device
  14585. #define DAW_SCR    0x0002           // 1=STDOUT (screen)
  14586. #define DAW_KBD    0x0001           // 1=STDIN  (keyboard)
  14587.  
  14588. // capabilities bit strip
  14589.  
  14590. #define CBS_SHD    0x0001           // 1=shutdown/DevIOCtl2
  14591. #define CBS_HMEM   0x0002           // hign memory map for adapters
  14592. #define CBS_PP     0x0004           // supports parallel ports
  14593. #define CBS_ADD    0x0010           // driver is an ADD
  14594. #define CBS_INIT   010020           // driver receives InitComplete
  14595.  
  14596. // SaveMessage structure
  14597.  
  14598. typedef struct MessageTable {
  14599.    USHORT      id;
  14600.    USHORT      fill_in_item;
  14601.    FARPOINTER  item1;
  14602.    FARPOINTER  item2;
  14603.    FARPOINTER  item_last;
  14604.    } MESSAGETABLE;
  14605.  
  14606. // OS/2 circular character queues
  14607.  
  14608. #define QUEUE_SIZE  512             //  size of queues
  14609. typedef struct CharQueue {
  14610.    USHORT   qsize;                  // number of bytes in queue
  14611.    USHORT   qchrout;                // index of next char to put out
  14612.    USHORT   qcount;                 // number of charactes in queue
  14613.    UCHAR    qbuf[QUEUE_SIZE];
  14614.    } CHARQUEUE;
  14615. typedef CHARQUEUE near *PCHARQUEUE;
  14616.  
  14617. // AttachDD inter device driver communication data area
  14618.  
  14619. typedef struct AttachArea {
  14620.    OFF realOFF;                     // real-mode offset of idc entry point
  14621.    SEG realCS;                      // real-mode CS of IDC entry point
  14622.    SEG realDS;                      // real-mode DS of IDC DD
  14623.    OFF protOFF;                     // protect-mode offset of entry point
  14624.    SEL protCS;                      // protect-mode CS of entry point
  14625.    SEL protDS;                      // protect-mode DS of other DD
  14626.    } ATTACHAREA;
  14627. typedef ATTACHAREA near *PATTACHAREA;
  14628.  
  14629. // driver request packet
  14630.  
  14631. typedef struct ReqPacket {
  14632.    UCHAR RPlength;                  // request packet length
  14633.    UCHAR   RPunit;                  // unit code for block DD only
  14634.    UCHAR RPcommand;                 // command code
  14635.    USHORT  RPstatus;                // status word
  14636.    UCHAR   RPreserved[4];           // reserved bytes
  14637.    ULONG RPqlink;                   // queue linkage
  14638.    union {                          // command-specific data
  14639.    UCHAR   avail[19];
  14640.     struct {                        // init
  14641.       UCHAR      units;             // number of units
  14642.       FPFUNCTION DevHlp;            // &DevHlp
  14643.       char far   *args;             // &args
  14644.       UCHAR      drive;             // drive #
  14645.       }Init;
  14646.     struct {
  14647.       UCHAR     units;              // same as input
  14648.       OFF       finalCS;            // final offset, 1st code segment
  14649.       OFF       finalDS;            // final offset, 1st data segment
  14650.       FARPOINTER BPBarray;          // &BPB
  14651.       } InitExit;
  14652.  
  14653.     struct {                        // read, write, write w/verify
  14654.       UCHAR      media;             // media descriptor
  14655.       PHYSADDR   buffer;            // transfer address
  14656.       USHORT     count;             // bytes/sectors
  14657.       ULONG      startsector;       // starting sector#
  14658.       USHORT     reserved;
  14659.       } ReadWrite;
  14660.  
  14661.     struct {                        // cached read, write, write w/verify
  14662.       UCHAR      media;             // media descriptor
  14663.       PHYSADDR   buffer;            // transfer address
  14664.       USHORT     count;             // bytes/sectors
  14665.       ULONG      startsector;       // starting sector#
  14666.       USHORT     reserved;
  14667.       } CReadWrite;
  14668.  
  14669.     struct {                        // system shutdown
  14670.       UCHAR      subcode;           // sub request code
  14671.       ULONG      reserved;
  14672.       } Shutdown;
  14673.  
  14674.     struct {                        // open/close
  14675.       USHORT     sysfilenum;        // system file number
  14676.       } OpenClose;
  14677.  
  14678.     struct {                        // IOCtl
  14679.       UCHAR      category;          // category code
  14680.       UCHAR      function;          // function code
  14681.       FARPOINTER parameters;        // ¶meters
  14682.       FARPOINTER buffer;            // &buffer
  14683.       } IOCtl;
  14684.  
  14685.     struct {                        // read, no wait
  14686.       UCHAR      char_returned;     // char to return
  14687.       } ReadNoWait;
  14688.  
  14689.     struct {                        // media check
  14690.       UCHAR      media;             // media descriptor
  14691.       UCHAR      return_code;       // see #defines
  14692.       FARPOINTER prev_volume;       // &previous volume ID
  14693.       } MediaCheck;
  14694.  
  14695.     struct {                        // build BPB
  14696.       UCHAR      media;             // media descriptor
  14697.       FARPOINTER buffer;            // 1-sector buffer FAT
  14698.       FARPOINTER BPBarray;          // &BPB array
  14699.       UCHAR      drive;             // drive #
  14700.       } BuildBPB;
  14701.  
  14702.     struct {                        // query partitionalble fixed disks
  14703.       UCHAR      count;             // # disks
  14704.       ULONG      reserved;
  14705.       } Partitionable;
  14706.  
  14707.     struct {                        // fixed disk LU map
  14708.       ULONG      units;             // units supported
  14709.       ULONG      reserved;
  14710.       } GetFixedMap;
  14711.  
  14712.     struct {                        // get driver capabilities
  14713.       UCHAR      reserved[3];
  14714.       FARPOINTER capstruct;         // 16:16 pointer to DCS
  14715.       FARPOINTER volcharstruct;     // 16:16 pointer to VCS
  14716.       } GetDriverCaps;
  14717.  
  14718.    } s;                             // command info
  14719. } REQPACKET;
  14720.  
  14721. typedef REQPACKET far *PREQPACKET;
  14722. typedef PREQPACKET far *PPREQPACKET;
  14723. typedef PREQPACKET QHEAD;           // Queue Head is &ReqPacket
  14724. typedef QHEAD near *PQHEAD;
  14725.  
  14726. // Global Info Seg
  14727.  
  14728. typedef struct _GINFOSEG {
  14729.     ULONG   time;            //    time in seconds
  14730.     ULONG   msecs;            //    milliseconds
  14731.     UCHAR   hour;            //    hours
  14732.     UCHAR   minutes;            //    minutes
  14733.     UCHAR   seconds;            //    seconds
  14734.     UCHAR   hundredths;            //    hundredths
  14735.     USHORT  timezone;            //    minutes from UTC
  14736.     USHORT  cusecTimerInterval;        //    timter interval, .0001 secs
  14737.     UCHAR   day;            //    day of month
  14738.     UCHAR   month;            //    month, 1-12
  14739.     USHORT  year;            //    year
  14740.     UCHAR   weekday;            //    day of week, 0=Sunday, 1=Monday...
  14741.     UCHAR   uchMajorVersion;        //    major version number
  14742.     UCHAR   uchMinorVersion;        //    minor version number
  14743.     UCHAR   chRevisionLetter;        //    rev level
  14744.     UCHAR   sgCurrent;            //    current foreground session
  14745.     UCHAR   sgMax;            //    max number of sessions
  14746.     UCHAR   cHugeShift;            //    shift count for huge elements
  14747.     UCHAR   fProtectModeOnly;        //    protect mode only
  14748.     USHORT  pidForeground;        //    pid of last process in foreground
  14749.     UCHAR   fDynamicSched;        //    dynamic variation flag
  14750.     UCHAR   csecMaxWait;        //    max wait in seconds
  14751.     USHORT  cmsecMinSlice;        //    min timeslice in milliseconds
  14752.     USHORT  cmsecMaxSlice;        //    max timeslice in milliseconds
  14753.     USHORT  bootdrive;            //    boot drive (0=a, 1=b...)
  14754.     UCHAR   amecRAS[32];        //    system trace major code flag bits
  14755.     UCHAR   csgWindowableVioMax;    //    max number of VIO sessions
  14756.     UCHAR   csgPMMax;            //    max number of PM sessions
  14757. } GINFOSEG;
  14758. typedef GINFOSEG far *PGINFOSEG;
  14759.  
  14760. // local info seg
  14761.  
  14762. typedef struct _LINFOSEG {
  14763.     PID     pidCurrent;            //    current process id
  14764.     PID     pidParent;            //    process id of parent
  14765.     USHORT  prtyCurrent;        //    priroty of current thread
  14766.     TID     tidCurrent;            //    thread id of current thread
  14767.     USHORT  sgCurrent;            //    current session id
  14768.     UCHAR   rfProcStatus;        //    process status
  14769.     UCHAR   dummy1;            //    reserved
  14770.     USHORT  fForeground;        //    current process is in foreground
  14771.     UCHAR   typeProcess;        //    process type
  14772.     UCHAR   dummy2;            //    reserved
  14773.     SEL     selEnvironment;        //    selector of environment
  14774.     USHORT  offCmdLine;            //    command line offset
  14775.     USHORT  cbDataSegment;        //    length of data segment
  14776.     USHORT  cbStack;            //    stack size
  14777.     USHORT  cbHeap;            //    heap size
  14778.     USHORT  hmod;            //    module handle of application
  14779.     SEL     selDS;            //    data segment handle of application
  14780. } LINFOSEG;
  14781.  
  14782. typedef LINFOSEG far *PLINFOSEG;
  14783.  
  14784. typedef struct _REGSTACK {          // stack usgae structure
  14785.     USHORT  usStruct;            // set to 14 before using
  14786.      USHORT  usFlags;        // 0x01 means that the interrupt proc
  14787.                                 // enables interrupts. All others resvd
  14788.      USHORT  usIRQ;            // IRQ of interrupt handler
  14789.      USHORT  usStackCLI;        // # of stack bytes with interrupts off
  14790.      USHORT  usStackSTI;        // # of stack bytes with interrupts on
  14791.      USHORT  usStackEOI;        // number of bytes needed after EOI
  14792.      USHORT  usNest;        // max number of nested levels
  14793.      } REGSTACK;
  14794.  
  14795. typedef REGSTACK near *PREGSTACK;
  14796.  
  14797. // page list struct
  14798.  
  14799. typedef struct _PAGELIST {
  14800.     ULONG pl_Physaddr;
  14801.      ULONG pl_cb;
  14802.      } PAGELIST;
  14803. typedef PAGELIST far *PPAGELIST;
  14804.  
  14805. // RPstatus bit values
  14806.  
  14807. #define RPERR   0x8000              //  error occurred, err in RPstatus
  14808. #define RPDEV   0x4000              //  error code defined by driver
  14809. #define RPBUSY  0x0200              //  device is busy
  14810. #define RPDONE  0x0100              //  driver done with request packet
  14811.  
  14812. // error codes returned in RPstatus
  14813.  
  14814. #define ERROR_WRITE_PROTECT         0x0000
  14815. #define ERROR_BAD_UNIT              0x0001
  14816. #define ERROR_NOT_READY             0x0002
  14817. #define ERROR_BAD_COMMAND           0x0003
  14818. #define ERROR_CRC                   0x0004
  14819. #define ERROR_BAD_LENGTH            0x0005
  14820. #define ERROR_SEEK                  0x0006
  14821. #define ERROR_NOT_DOS_DISK          0x0007
  14822. #define ERROR_SECTOR_NOT_FOUND      0x0008
  14823. #define ERROR_OUT_OF_PAPER          0x0009
  14824. #define ERROR_WRITE_FAULT           0x000A
  14825. #define ERROR_READ_FAULT            0x000B
  14826. #define ERROR_GEN_FAILURE           0x000C
  14827. #define ERROR_DISK_CHANGE           0x000D
  14828. #define ERROR_WRONG_DISK            0x000F
  14829. #define ERROR_UNCERTAIN_MEDIA       0x0010
  14830. #define ERROR_CHAR_CALL_INTERRUPTED 0x0011
  14831. #define ERROR_NO_MONITOR_SUPPORT    0x0012
  14832. #define ERROR_INVALID_PARAMETER     0x0013
  14833. #define ERROR_DEVICE_IN_USE         0x0014
  14834.  
  14835. // driver request codes  B=block, C=character
  14836.  
  14837. #define RPINIT          0x00        //  BC
  14838. #define RPMEDIA_CHECK   0x01        //  B
  14839. #define RPBUILD_BPB     0x02        //  B
  14840. #define RPREAD          0x04        //  BC
  14841. #define RPREAD_NO_WAIT  0x05        //   C
  14842. #define RPINPUT_STATUS  0x06        //   C
  14843. #define RPINPUT_FLUSH   0x07        //   C
  14844. #define RPWRITE         0x08        //  BC
  14845. #define RPWRITE_VERIFY  0x09        //  BC
  14846. #define RPOUTPUT_STATUS 0x0a        //   C
  14847. #define RPOUTPUT_FLUSH  0x0b        //   C
  14848. #define RPOPEN          0x0d        //  BC
  14849. #define RPCLOSE         0x0e        //  BC
  14850. #define RPREMOVABLE     0x0f        //  B
  14851. #define RPIOCTL         0x10        //  BC
  14852. #define RPRESET         0x11        //  B
  14853. #define RPGET_DRIVE_MAP 0x12        //  B
  14854. #define RPSET_DRIVE_MAP 0x13        //  B
  14855. #define RPDEINSTALL     0x14        //   C
  14856. #define RPPARTITIONABLE 0x16        //  B
  14857. #define RPGET_FIXED_MAP 0x17        //  B
  14858. #define RPSHUTDOWN      0x1c        //  BC
  14859. #define RPGET_DRIVER_CAPS 0x1d      //  B
  14860.  
  14861. // check for monitor call in DosOpen/DosClose
  14862.  
  14863. #define MON_OPEN_STATUS   0x08      // open from DosMonOpen
  14864. #define MON_CLOSE_STATUS  0x08      // close from DosMonClose
  14865.  
  14866. // media descriptor byte
  14867.  
  14868. #define MDB_REMOVABLE     0x04      //  1=removable
  14869. #define MDB_EIGHT_SECTORS 0x02      //  1=8 sectors per track
  14870. #define MDB_DOUBLE_SIDED  0x01      //  1=double-sided media
  14871.  
  14872. // return codes from MediaCheck
  14873.  
  14874. #define MC_MEDIA_UNCHANGED 0x01
  14875. #define MC_MEDIA_CHANGED   0xFF
  14876. #define MC_MEDIA_UNSURE    0x00
  14877.  
  14878. // event numbers for SendEvent
  14879.  
  14880. #define EVENT_SM_MOUSE   0x00       // session switch via mouse
  14881. #define EVENT_CTRLBRK    0x01       // control break
  14882. #define EVENT_CTRLC      0x02       // control C
  14883. #define EVENT_CTRLNUMLK  0x03       // control num lock
  14884. #define EVENT_CTRLPRTSC  0x04       // control printscreen
  14885. #define EVENT_SHFTPRTSC  0x05       // shift printscreen
  14886. #define EVENT_SM_KBD     0x06       // session switch hot key
  14887.  
  14888. // defines for 1.x movedata function
  14889.  
  14890. #define   MOVE_PHYSTOPHYS   0       // move bytes from phys to phys memory
  14891. #define   MOVE_PHYSTOVIRT   1       // move bytes from phys to virt memory
  14892. #define   MOVE_VIRTTOPHYS   2       // move bytes from virt to phys memory
  14893. #define   MOVE_VIRTTOVIRT   3       // move bytes from virt to virt memory
  14894.  
  14895. // Micro Channel specific
  14896.  
  14897. int NP GetLIDEntry (USHORT, USHORT, USHORT, FPUSHORT);
  14898. int NP FreeLIDEntry (USHORT);
  14899. int NP ABIOSCall (USHORT, USHORT, FARPOINTER);
  14900. int NP ABIOSComm (USHORT, FARPOINTER);
  14901. int NP GetDeviceBlock(USHORT, FARPOINTER);
  14902.  
  14903. // special routines
  14904.  
  14905. void NP INT3  (void);
  14906. void NP Enable  (void);
  14907. void NP Disable  (void);
  14908. void NP Abort  (void);
  14909. int  NP SegLimit (SEL, OFF far *);
  14910. int  NP MoveBytes (FARPOINTER,FARPOINTER,FLAG);
  14911. int  NP MoveData (FARPOINTER, FARPOINTER, USHORT, USHORT);
  14912.  
  14913. // system services and misc.
  14914.  
  14915. int  NP GetDOSVar (USHORT, FPFARPOINTER);
  14916. int  NP SendEvent (USHORT, USHORT);
  14917. void NP SchedClockAddr (PFARPOINTER);
  14918. int  NP AttachDD (PSTRING, PATTACHAREA);
  14919. int  NP InternalError(PSTRING,USHORT);
  14920. int  NP SaveMessage(FPSTRING);
  14921. int  NP ProtToReal(void);
  14922. int  NP RealToProt(void);
  14923. int  NP SetROMVector(USHORT,PFUNCTION,PFUNCTION,FARPOINTER);
  14924.  
  14925. // process mgmt
  14926.  
  14927. void NP Yield  (void);
  14928. void NP TCYield  (void);
  14929. int  NP Block  (ULONG, ULONG, USHORT, FARPOINTER);
  14930. void NP Run  (ULONG);
  14931. void NP DevDone  (PREQPACKET);
  14932. int  NP VideoPause(USHORT);
  14933.  
  14934. // memory management
  14935.  
  14936. int  NP AllocPhys (ULONG, USHORT, PPHYSADDR);
  14937. int  NP FreePhys (PHYSADDR);
  14938. int  NP VerifyAccess (SEL, OFF, USHORT, USHORT);
  14939. int  NP LockSeg  (SEL, USHORT, USHORT, PLHANDLE);
  14940. int  NP UnLockSeg (LHANDLE);
  14941.  
  14942. // address conversion
  14943.  
  14944. int  NP AllocGDTSelector(USHORT, FARPOINTER);
  14945. int  NP PhysToGDTSelector(PHYSADDR, USHORT, SEL, PERRCODE);
  14946. int  NP VirtToPhys (FARPOINTER, PPHYSADDR);
  14947. int  NP PhysToUVirt (PHYSADDR, USHORT, USHORT, FARPOINTER);
  14948. int  NP PhysToVirt (PHYSADDR, USHORT, USHORT, FARPOINTER);
  14949. int  NP UnPhysToVirt (void);
  14950.  
  14951. // request packet queue stuff
  14952.  
  14953. int  NP AllocReqPacket (USHORT, PPREQPACKET);
  14954. void NP FreeReqPacket (PREQPACKET);
  14955. void NP PushReqPacket (PQHEAD, PREQPACKET);
  14956. void NP SortReqPacket (PQHEAD, PREQPACKET);
  14957. int  NP PullReqPacket (PQHEAD, PPREQPACKET);
  14958. int  NP PullParticular  (PQHEAD, PREQPACKET);
  14959.  
  14960. // driver semaphores
  14961.  
  14962. int  NP SemHandle (LHANDLE, FLAG, PLHANDLE);
  14963. int  NP SemRequest (LHANDLE, ULONG, PERRCODE);
  14964. void NP SemClear (LHANDLE);
  14965.  
  14966. // circular character queues
  14967.  
  14968. void NP QueueInit (PCHARQUEUE);
  14969. void NP QueueFlush (PCHARQUEUE);
  14970. int  NP QueueWrite (PCHARQUEUE, UCHAR);
  14971. int  NP QueueRead (PCHARQUEUE, FPUCHAR);
  14972.  
  14973. // interrupt stuff
  14974.  
  14975. int  NP SetIRQ  (USHORT, PFUNCTION, USHORT);
  14976. int  NP UnSetIRQ (USHORT);
  14977. int  NP EOI  (USHORT);
  14978. void NP ClaimInterrupt(void);
  14979. void NP RefuseInterrupt(void);
  14980. int  NP RegisterStackUsage(PREGSTACK);
  14981.  
  14982. // timer stuff
  14983.  
  14984. int  NP SetTimer (PFUNCTION);
  14985. int  NP ResetTimer (PFUNCTION);
  14986. int  NP TickCount (PFUNCTION, USHORT);
  14987.  
  14988. // device monitors
  14989.  
  14990. int  NP MonCreate (PSHANDLE, FARPOINTER, FARPOINTER, PERRCODE);
  14991. int  NP Register (SHANDLE, USHORT, PID, FARPOINTER, OFF, PERRCODE);
  14992. int  NP MonWrite (SHANDLE, POINTER, USHORT, USHORT, ULONG, PERRCODE);
  14993. int  NP MonFlush (SHANDLE, PERRCODE);
  14994. int  NP DeRegister (SHANDLE, PID, PERRCODE);
  14995.  
  14996. // 2.x  specific
  14997.  
  14998. int  NP RegisterPDD(FPUCHAR,FPFUNCTION);
  14999. int  NP RegisterBeep(FPFUNCTION);
  15000. int  NP Beep(USHORT,USHORT);
  15001. int  NP FreeGDTSelector(USHORT);
  15002. int  NP PhysToGDTSel(PHYSADDR,ULONG,SEL,USHORT,FPUSHORT);
  15003. int  NP VMLock(LINADDR,ULONG,LINADDR,LINADDR,ULONG,FPULONG);
  15004. int  NP VMUnlock(LHANDLE);
  15005. int  NP VMAlloc(LINADDR,ULONG,ULONG,PLINADDR);
  15006. int  NP VMFree(PHYSADDR);
  15007. int  NP VMProcessToGlobal(LINADDR,ULONG,ULONG,PLINADDR);
  15008. int  NP VMGlobalToProcess(LINADDR,ULONG,ULONG,PLINADDR);
  15009. int  NP VirtToLin(FARPOINTER,PLINADDR);
  15010. int  NP LinToGDTSelector(SEL,LINADDR,ULONG);
  15011. int  NP GetDescInfo(SEL,FPUSHORT,FPULONG,FPULONG);
  15012. int  NP LinToPageList(LINADDR,ULONG,LINADDR,FPULONG);
  15013. int  NP PageListToLin(ULONG,LINADDR,PLINADDR);
  15014. int  NP PageListToGDTSelector(SEL,ULONG,LINADDR,USHORT,FPUSHORT);
  15015. int  NP RegisterTmrDD(FPFUNCTION,FPFARPOINTER,FPFARPOINTER);
  15016. int  NP AllocCtxHook(OFF,ULONG,PLHANDLE);
  15017. int  NP FreeCtxHook(LHANDLE);
  15018. int  NP ArmCtxHook(ULONG,LHANDLE,ULONG);
  15019. int  NP VMSetMem(LINADDR,ULONG,ULONG);
  15020. int  NP OpenEventSem(LHANDLE);
  15021. int  NP CloseEventSem(LHANDLE);
  15022. int  NP PostEventSem(LHANDLE);
  15023. int  NP ResetEventSem(LHANDLE,LINADDR);
  15024. int  NP DynamicAPI(FARPOINTER,USHORT,USHORT,FPUSHORT);
  15025.  
  15026. // these are the only API's available to the driver at Init time
  15027.  
  15028. #define APIENTRY far pascal
  15029.  
  15030. USHORT APIENTRY DosBeep(USHORT, USHORT);
  15031. USHORT APIENTRY DosCaseMap(USHORT, FARPOINTER, FARPOINTER);
  15032. USHORT APIENTRY DosChgFilePtr(SHANDLE, long, USHORT, FARPOINTER);
  15033. USHORT APIENTRY DosClose(SHANDLE);
  15034. USHORT APIENTRY DosDelete(FARPOINTER, ULONG);
  15035. USHORT APIENTRY DosDevConfig(FARPOINTER, USHORT, USHORT);
  15036. USHORT APIENTRY DosDevIOCtl(FARPOINTER, FARPOINTER, USHORT, USHORT, USHORT);
  15037. USHORT APIENTRY DosFindClose(SHANDLE);
  15038. USHORT APIENTRY DosFindFirst(FARPOINTER, FARPOINTER, USHORT, FARPOINTER,
  15039.                              USHORT, FARPOINTER, ULONG);
  15040. USHORT APIENTRY DosFindNext(SHANDLE, FARPOINTER, USHORT, FARPOINTER);
  15041. USHORT APIENTRY DosGetEnv(FARPOINTER, FARPOINTER);
  15042. USHORT APIENTRY DosGetMessage(FARPOINTER, USHORT, FARPOINTER, USHORT,
  15043.                               USHORT, FARPOINTER, FARPOINTER);
  15044. USHORT APIENTRY DosOpen(FARPOINTER, FARPOINTER, FARPOINTER, ULONG,
  15045.                         USHORT, USHORT, USHORT, ULONG);
  15046. USHORT APIENTRY DosPutMessage(SHANDLE, USHORT, FARPOINTER);
  15047. USHORT APIENTRY DosQCurDir(USHORT, FARPOINTER, FARPOINTER);
  15048. USHORT APIENTRY DosQCurDisk(FARPOINTER, FARPOINTER);
  15049. USHORT APIENTRY DosQFileInfo(SHANDLE, USHORT, FARPOINTER, USHORT);
  15050. USHORT APIENTRY DosQFileMode(FARPOINTER, FARPOINTER, ULONG);
  15051. USHORT APIENTRY DosRead(SHANDLE, FARPOINTER, USHORT, FARPOINTER);
  15052. USHORT APIENTRY DosWrite(SHANDLE, FARPOINTER, USHORT, FARPOINTER);
  15053.  
  15054. // end of DRVLIB.H
  15055.  
  15056.  
  15057. ΓòÉΓòÉΓòÉ 23.6. Skeleton Strategy Section ΓòÉΓòÉΓòÉ
  15058.  
  15059. int main(PREQPACKET rp, int dev)
  15060.  
  15061. {
  15062. switch(rp->RPcommand) {
  15063.  
  15064.     case RPINIT&colon.         // 0x00
  15065.  
  15066.        // init called by kernel
  15067.  
  15068.        return Init(rp);
  15069.  
  15070.     case RPREAD&colon.         // 0x04
  15071.  
  15072.        return (RPDONE);
  15073.  
  15074.     case RPWRITE&colon.        //  0x08
  15075.  
  15076.        return (RPDONE);
  15077.  
  15078.     case RPINPUT_FLUSH&colon.  // 0x07
  15079.  
  15080.        return (RPDONE);
  15081.  
  15082.     case RPOUTPUT_FLUSH&colon. // 0x0b
  15083.  
  15084.        return (RPDONE);
  15085.  
  15086.     case RPOPEN&colon.         // 0x0d
  15087.  
  15088.        return (RPDONE);
  15089.  
  15090.     case RPCLOSE&colon.        // 0x0e
  15091.  
  15092.        return (RPDONE);
  15093.  
  15094.     case RPIOCTL&colon.        // 0x10
  15095.  
  15096.        switch (rp->s.IOCtl.function)
  15097.        {
  15098.           case 0x00&colon.      // our function def 1
  15099.              return (RPDONE);
  15100.  
  15101.           case 0x01&colon.      // our function def 2
  15102.              return (RPDONE);
  15103.        }
  15104.  
  15105.     // deinstall request
  15106.  
  15107.     case RPDEINSTALL&colon.    // 0x14
  15108.        return(RPDONE | RPERR | ERROR_BAD_COMMAND);
  15109.  
  15110.     // all other commands are ignored
  15111.  
  15112.     default&colon.
  15113.  
  15114.        return(RPDONE);
  15115.  
  15116.     }
  15117. }
  15118.  
  15119.  
  15120. ΓòÉΓòÉΓòÉ 23.7. Sample IOCtl Call, 16-Bit ΓòÉΓòÉΓòÉ
  15121.  
  15122. if (DosDevIOCtl(&data_buf,&parm_buf,cat,func,dhandle))
  15123.     error;
  15124.  
  15125.  
  15126. ΓòÉΓòÉΓòÉ 23.8. Sample IOCtl Call, 32-Bit ΓòÉΓòÉΓòÉ
  15127.  
  15128. if (DosDevIOCtl(&data_buf,&parm_buf,cat,func,dhandle, ,,,,,))
  15129.       error;
  15130.  
  15131.  
  15132. ΓòÉΓòÉΓòÉ 23.9. Sample Interrupt Handler ΓòÉΓòÉΓòÉ
  15133.  
  15134. // 82050 interrupt handler
  15135.  
  15136. void interrupt_handler ()
  15137. {
  15138.     int  rupt_dev;
  15139.     int  source;
  15140.     int  cmd_b;
  15141.     int  st_b;
  15142.     int  port;
  15143.     int  temp;
  15144.     int  rxlevel;
  15145.  
  15146.  
  15147.     port=UART_PORT_ADDRESS;
  15148.     outp((port+2),0x20);    // switch to bank 1
  15149.     source = getsrc ();     // get vector
  15150.     switch (source)
  15151.     {
  15152.  
  15153.     // optional timer service routine
  15154.  
  15155.     case timer :
  15156.  
  15157.         st_b=inp (port+3);  // dec transmit cnt
  15158.         if ( ThisReadRP == 0) // nobody waiting
  15159.             break;
  15160.         ThisReadRP->RPstatus=(RPDONE | RPERR | ERROR_NOT_READY);
  15161.         Run ((ULONG)  ThisWriteRP);// run thread
  15162.         ThisWriteRP=0;
  15163.         break;
  15164.  
  15165.     case txm   :
  15166.     case txf   :
  15167.  
  15168.         // spurious write interrupt
  15169.  
  15170.         if ( ThisWriteRP == 0)
  15171.         {
  15172.           temp=inp(port+2);
  15173.           break;
  15174.         }
  15175.  
  15176.         // keep transmitting until no data left
  15177.  
  15178.         if  (!(QueueRead(&tx_queue,&outchar)))
  15179.         {
  15180.            outp((port), outchar);
  15181.            tickcount=MIN_TIMEOUT;
  15182.            break;
  15183.         }
  15184.  
  15185.         // done writing, run blocked thread
  15186.  
  15187.         tickcount=MIN_TIMEOUT;
  15188.         disable_write();
  15189.         ThisWriteRP->RPstatus = (RPDONE);
  15190.         Run ((ULONG)  ThisWriteRP);
  15191.         ThisWriteRP=0;
  15192.         break;
  15193.  
  15194.     case ccr   :
  15195.  
  15196.         // control character, treat as normal
  15197.  
  15198.         inchar=inp(port+5);
  15199.  
  15200.     case rxf   :
  15201.  
  15202.         // rx fifo service routine
  15203.  
  15204.         if ( ThisReadRP == 0)
  15205.            inchar=inp (port); // get character
  15206.         else
  15207.         {
  15208.         temp=inp(port+4);
  15209.         rxlevel=(temp & 0x70) / 0x10;
  15210.  
  15211.         // empty out chip FIFO
  15212.  
  15213.         while (rxlevel !=0) {
  15214.  
  15215.           inchar=inp (port); // get character
  15216.           rxlevel--;
  15217.           tickcount=MIN_TIMEOUT;
  15218.  
  15219.           // write input data to queue
  15220.  
  15221.           if(QueueWrite(&rx_queue,inchar))
  15222.  
  15223.             // error, queue must be full
  15224.  
  15225.           {
  15226.             ThisReadRP->RPstatus = (RPDONE|RPERR|ERROR_GEN_FAILURE);
  15227.             Run ((ULONG) ThisReadRP);
  15228.             ThisReadRP=0;
  15229.             break;
  15230.           }
  15231.           com_error_word |= inp(port+5);
  15232.  
  15233.         } // while rxlevel
  15234.      } // else
  15235.   } // switch (source)
  15236.   EOI(irq);
  15237. }
  15238.  
  15239.  
  15240. ΓòÉΓòÉΓòÉ 23.10. Sample Timer Handler ΓòÉΓòÉΓòÉ
  15241.  
  15242. void timer_handler()
  15243. {
  15244.   if (ThisReadRP == 0)
  15245.         return;
  15246.  
  15247.   tickcount--;
  15248.   if(tickcount == 0)  {
  15249.     ThisReadRP->RPstatus=(RPDONE);
  15250.     Run ((ULONG) ThisReadRP);
  15251.     ThisReadRP=0L;
  15252.     tickcount=MIN_TIMEOUT;
  15253.     }
  15254. }
  15255.  
  15256.  
  15257. ΓòÉΓòÉΓòÉ 23.11. Simple OS/2 Parallel Physical Device Driver ΓòÉΓòÉΓòÉ
  15258.  
  15259. /*
  15260.    This driver supports DosOpen, DosClose, DosRead, DosWrite
  15261.    and IOCtl 0x91 codes 1, 2 and 3. All other driver calls and
  15262.    IOCtls are ignored (returns ERROR_BAD_COMMAND).
  15263.  
  15264.    The driver also uses these #defs
  15265.  
  15266.    #define  DIGIO_CAT    0x91         driver category
  15267.    #define  DIGIO_BASE   0x2c0        base port address
  15268.    #define  DIGIO_OUTPUT DIGIO_BASE   output port
  15269.    #define  DIGIO_INPUT  DIGIO_BASE+1 input port
  15270.    #define  DIGIO_CONFIG DIGIO_BASE+3 initialization port
  15271.  
  15272.    1. Open the driver with:
  15273.  
  15274.       if ((RetCode=DosOpen("DIGIO$",
  15275.          &digio_handle,
  15276.          &ActionTaken,
  15277.          FileSize,
  15278.          FileAttribute,
  15279.          FILE_OPEN,
  15280.          OPEN_SHARE_DENYNONE | OPEN_FLAGS_FAIL_ON_ERROR
  15281.          | OPEN_ACCESS_READWRITE,Reserved)) !=0)
  15282.             printf("\nopen error = %d",RetCode);
  15283.  
  15284.    2. Output byte to the output port (base +0) with this IOCtl:
  15285.  
  15286.       DosDevIOCtl(NULL,&char,1,0x91,digio_handle);
  15287.  
  15288.       or with this standard request:
  15289.  
  15290.       DosWrite(digio_handle,&char,1,&bytes_written;
  15291.  
  15292.    3. Read data from the input port (base + 1) with this IOCtl.
  15293.       The driver will block until the bit in specified in the
  15294.       mask is set:
  15295.  
  15296.       DosDevIOCtl(&char,NULL,2,0x91,digio_handle);
  15297.  
  15298.    4. Read data from the input port (base + 1) with this IOCtl.
  15299.       This IOCtl returns immediately with the status:
  15300.  
  15301.       DosDevIOCtl(&char,NULL,3,0x91,digio_handle);
  15302.  
  15303.       or with this standard driver request:
  15304.  
  15305.       DosRead(digio_handle,&char,1,&bytes_read;
  15306.  
  15307. */
  15308.  
  15309. #include "drvlib.h"
  15310. #include "digio.h"
  15311.  
  15312. extern void STRATEGY();       // name of strat rout. in drvstart
  15313. extern void TIMER_HANDLER();  // timer handler in drvstart
  15314.  
  15315. DEVICEHDR devhdr = {
  15316.     (void far *) 0xFFFFFFFF,  // link
  15317.     (DAW_CHR | DAW_OPN | DAW_LEVEL1),// attribute word
  15318.     (OFF) STRATEGY,           // &strategy
  15319.     (OFF) 0,                  // &IDC routine
  15320.     "DIGIO$  "                // name/#units
  15321. };
  15322.  
  15323. FPFUNCTION  DevHlp=0;         // pointer to DevHlp entry point
  15324. UCHAR       opencount = 0;    // keeps track of open's
  15325. USHORT      savepid=0;        // save thread pid
  15326. LHANDLE     lock_seg_han;     // handle for locking appl. seg
  15327. PHYSADDR    appl_buffer=0;    // address of caller's buffer
  15328. ERRCODE     err=0;            // error return
  15329. ULONG       ReadID=0L;        // current read pointer
  15330. USHORT      num_rupts=0;      // count of interrupts
  15331. USHORT      temp_char;        // temp character for in-out
  15332. void        far *ptr;         // temp far pointer
  15333. FARPOINTER  appl_ptr=0;       // pointer to application buffer
  15334. char        input_char,output_char; // temp character storage
  15335. char        input_mask;       // mask for input byte
  15336.  
  15337. // messages
  15338.  
  15339. char     CrLf[]= "\r\n";
  15340. char     InitMessage1[] = " 8 bit Digital I/O ";
  15341. char     InitMessage2[] = " driver installed\r\n";
  15342. char     FailMessage[]  = " driver failed to install.\r\n";
  15343.  
  15344. // common entry point for calls to Strategy routines
  15345.  
  15346. int main(PREQPACKET rp)
  15347. {
  15348.   void far *ptr;
  15349.   PLINFOSEG liptr;             // pointer to global info seg
  15350.   int i;
  15351.  
  15352.   switch(rp->RPcommand)
  15353.   {
  15354.   case RPINIT:                 // 0x00
  15355.  
  15356.         // init called by kernel in protected mode
  15357.  
  15358.         return Init(rp);
  15359.  
  15360.   case RPREAD:                 // 0x04
  15361.  
  15362.         rp->s.ReadWrite.count = 0; // in case we fail
  15363.  
  15364.         input_char = inp(DIGIO_INPUT);// get data
  15365.  
  15366.         if (PhysToVirt( (ULONG) rp->s.ReadWrite.buffer,
  15367.            1,0,&appl_ptr))
  15368.              return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15369.  
  15370.         if (MoveBytes((FARPOINTER)&input_char,appl_ptr,1))
  15371.              return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15372.  
  15373.         rp->s.ReadWrite.count = 1; // one byte read
  15374.         return (RPDONE);
  15375.  
  15376.   case RPWRITE:                // 0x08
  15377.  
  15378.         rp->s.ReadWrite.count = 0;
  15379.  
  15380.         if (PhysToVirt( (ULONG) rp->s.ReadWrite.buffer,
  15381.            1,0,&appl_ptr))
  15382.              return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15383.  
  15384.         if (MoveBytes(appl_ptr,(FARPOINTER)&output_char,1))
  15385.              return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15386.  
  15387.         outp (DIGIO_OUTPUT,output_char); // send byte
  15388.  
  15389.         rp->s.ReadWrite.count = 1; // one byte written
  15390.         return (RPDONE);
  15391.  
  15392.   case RPOPEN:                 // 0x0d open driver
  15393.  
  15394.         // get current process id
  15395.  
  15396.         if (GetDOSVar(2,&ptr))
  15397.             return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  15398.  
  15399.         // get process info
  15400.  
  15401.         liptr = *((PLINFOSEG far *) ptr);
  15402.  
  15403.         // if this device never opened, can be opened by anyone
  15404.  
  15405.         if (opencount == 0)      // first time this dev opened
  15406.         {
  15407.             opencount=1;         // bump open counter
  15408.             savepid = liptr->pidCurrent; // save current PID
  15409.         }
  15410.         else
  15411.             {
  15412.             if (savepid != liptr->pidCurrent) // another proc
  15413.                 return (RPDONE | RPERR | ERROR_NOT_READY);//err
  15414.             ++opencount;         // bump counter, same pid
  15415.         }
  15416.         return (RPDONE);
  15417.  
  15418.   case RPCLOSE:                // 0x0e DosClose,ctl-C, kill
  15419.  
  15420.         // get process info of caller
  15421.  
  15422.         if (GetDOSVar(2,&ptr))
  15423.             return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  15424.  
  15425.         // get process info from os/2
  15426.  
  15427.         liptr= *((PLINFOSEG far *) ptr); // ptr to linfoseg
  15428.  
  15429.  
  15430.         // make sure that process attempting to close this device
  15431.         // is the one that originally opened it and the device was
  15432.         // open in the first place.
  15433.  
  15434.         if (savepid != liptr->pidCurrent || opencount == 0)
  15435.             return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  15436.  
  15437.         --opencount;             // close counts down open cntr
  15438.          return (RPDONE);        // return 'done' status
  15439.  
  15440.   case RPIOCTL:                // 0x10
  15441.  
  15442.         //The function code in an IOCtl packet has the high bit set
  15443.         //for the DIGIO$ board. We return all others with the done
  15444.         //bit set so we don't have to handle things like the 5-48
  15445.         //code page IOCtl
  15446.  
  15447.         if (rp->s.IOCtl.category != DIGIO_CAT)// other IOCtls
  15448.             return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  15449.  
  15450.         switch (rp->s.IOCtl.function)
  15451.         {
  15452.  
  15453.         case 0x01:               // write byte to digio port
  15454.  
  15455.           // verify caller owns this buffer area
  15456.  
  15457.           if(VerifyAccess(
  15458.           SELECTOROF(rp->s.IOCtl.parameters), // selector
  15459.           OFFSETOF(rp->s.IOCtl.parameters),   // offset
  15460.           1,                                  // 1 byte
  15461.           0) )                                // read only
  15462.               return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15463.  
  15464.           if(MoveBytes(rp->s.IOCtl.parameters,(FARPOINTER)&output_char,1))
  15465.               return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15466.  
  15467.           outp(DIGIO_OUTPUT,output_char);     //send to digio
  15468.           return (RPDONE);
  15469.  
  15470.         case 0x02:               // read byte w/wait from port
  15471.  
  15472.           // verify caller owns this buffer area
  15473.  
  15474.           if(VerifyAccess(
  15475.           SELECTOROF(rp->s.IOCtl.buffer), // selector
  15476.           OFFSETOF(rp->s.IOCtl.buffer),   // offset
  15477.           1,                              // 1 bytes)
  15478.           0))                             // read only
  15479.              return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15480.  
  15481.           // lock the segment down temp
  15482.  
  15483.           if(LockSeg(
  15484.           SELECTOROF(rp->s.IOCtl.buffer), // selector
  15485.           1,                              // lock forever
  15486.           0,                              // wait for seg loc
  15487.           (PLHANDLE) &lock_seg_han))      // handle returned
  15488.              return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15489.  
  15490.           if(MoveBytes(rp->s.IOCtl.parameters,(FARPOINTER)&input_mask,1))
  15491.               return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15492.  
  15493.           // wait for switch to be pressed
  15494.  
  15495.           ReadID = (ULONG)rp;             // block ID
  15496.           if (Block(ReadID,-1L,0,&err))
  15497.             if (err == 2)
  15498.               return(RPDONE | RPERR | ERROR_CHAR_CALL_INTERRUPTED);
  15499.  
  15500.           // move data to users buffer
  15501.  
  15502.           if(MoveBytes((FARPOINTER)&input_char,rp->s.IOCtl.buffer,1))
  15503.               return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  15504.  
  15505.           // unlock segment
  15506.  
  15507.           if(UnLockSeg(lock_seg_han))
  15508.               return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  15509.  
  15510.           return (RPDONE);
  15511.  
  15512.         case 0x03:               // read byte immed digio port
  15513.  
  15514.           // verify caller owns this buffer area
  15515.  
  15516.           if(VerifyAccess(
  15517.           SELECTOROF(rp->s.IOCtl.buffer), // selector
  15518.           OFFSETOF(rp->s.IOCtl.buffer),   // offset
  15519.           4,                              // 4 bytes
  15520.           0))                             // read only
  15521.               return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15522.  
  15523.           input_char = inp(DIGIO_INPUT);  // get data
  15524.  
  15525.           if(MoveBytes((FARPOINTER)&input_char,rp->s.IOCtl.buffer,1))
  15526.               return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  15527.  
  15528.           return (RPDONE);
  15529.  
  15530.       default:
  15531.           return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  15532.       }
  15533.  
  15534.       // don't allow deinstall
  15535.  
  15536.   case RPDEINSTALL:            // 0x14
  15537.       return(RPDONE | RPERR | ERROR_BAD_COMMAND);
  15538.  
  15539.       // all other commands are flagged as bad
  15540.  
  15541.   default:
  15542.       return(RPDONE | RPERR | ERROR_BAD_COMMAND);
  15543.  
  15544.   }
  15545. }
  15546.  
  15547. timr_handler()
  15548. {
  15549.  
  15550.    if (ReadID != 0)
  15551.    {
  15552.       // read data from port
  15553.  
  15554.       input_char = inp(DIGIO_INPUT );// get data
  15555.  
  15556.       if ((input_char && input_mask) !=0)
  15557.       {
  15558.         Run (ReadID);
  15559.         ReadID=0L;
  15560.       }
  15561.    }
  15562. }
  15563.  
  15564. // Device Initialization Routine
  15565.  
  15566. int Init(PREQPACKET rp)
  15567. {
  15568.     // store DevHlp entry point
  15569.  
  15570.     DevHlp = rp->s.Init.DevHlp;
  15571.  
  15572.     // install timer handler
  15573.  
  15574.     if(SetTimer((PFUNCTION)TIMER_HANDLER)) {
  15575.  
  15576.       // if we failed, effectively deinstall driver with cs+ds=0
  15577.  
  15578.       DosPutMessage(1, 8, devhdr.DHname);
  15579.       DosPutMessage(1,strlen(FailMessage),FailMessage);
  15580.       rp->s.InitExit.finalCS = (OFF) 0;
  15581.       rp->s.InitExit.finalDS = (OFF) 0;
  15582.       return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  15583.       }
  15584.  
  15585.     // configure 8255 parallel chip
  15586.  
  15587.     outp (DIGIO_CONFIG,0x91);
  15588.  
  15589.     // output initialization message
  15590.  
  15591.     DosPutMessage(1, 2, CrLf);
  15592.     DosPutMessage(1, 8, devhdr.DHname);
  15593.     DosPutMessage(1, strlen(InitMessage1), InitMessage1);
  15594.     DosPutMessage(1, strlen(InitMessage2), InitMessage2);
  15595.  
  15596.     // send back our code and data end values to os/2
  15597.  
  15598.     if (SegLimit(HIUSHORT((void far *) Init),
  15599.       &rp->s.InitExit.finalCS) || SegLimit(HIUSHORT((void far *)
  15600.       InitMessage2), &rp->s.InitExit.finalDS))
  15601.         Abort();
  15602.     return(RPDONE);
  15603. }
  15604.  
  15605.  
  15606. ΓòÉΓòÉΓòÉ 23.12. C Startup Routine for Parallel Device Driver ΓòÉΓòÉΓòÉ
  15607.  
  15608. ;
  15609. ; C Startup routine for parallel device driver
  15610. ;
  15611.    EXTRN   _main:near
  15612.    EXTRN   _timr_handler:near
  15613.    PUBLIC  _STRATEGY
  15614.    PUBLIC  __acrtused
  15615.    PUBLIC  _TIMER_HANDLER
  15616.  
  15617. _DATA      segment  word public 'DATA'
  15618. _DATA      ends
  15619.  
  15620. CONST      segment  word public 'CONST'
  15621. CONST      ends
  15622.  
  15623. _BSS       segment  word public 'BSS'
  15624. _BSS       ends
  15625.  
  15626. DGROUP     group  CONST, _BSS, _DATA
  15627.  
  15628. _TEXT      segment  word public 'CODE'
  15629.  
  15630.            assume cs:_TEXT, ds:DGROUP, es:NOTHING, ss:NOTHING
  15631.            .286
  15632.  
  15633. _STRATEGY  proc far
  15634. __acrtused:   ;to satisfy C
  15635.  
  15636. start:
  15637.            push es  ; &reqpacket high part
  15638.            push bx  ; &reqpacket low part
  15639.            call _main
  15640.            pop bx
  15641.            pop es
  15642.            mov word ptr es:[bx+3],ax  ; plug in status word
  15643.            ret
  15644. _STRATEGY  endp
  15645. ;
  15646. _TIMER_HANDLER proc  far
  15647. ;
  15648.            pusha   ;save flags, regs
  15649.            push ds
  15650.            push es  ;make up for the 'almost all' push
  15651.            call _timr_handler ;handle interrupts
  15652.            pop es
  15653.            pop ds
  15654.            popa   ;restore everything and
  15655.            ret   ;bail out
  15656. ;
  15657. _TIMER_HANDLER endp
  15658.  
  15659.  
  15660. _TEXT      ends
  15661.            end
  15662.  
  15663.  
  15664. ΓòÉΓòÉΓòÉ 23.13. Parallel Device Driver Include File ΓòÉΓòÉΓòÉ
  15665.  
  15666. // digio.h memory map for os/2 device driver
  15667.  
  15668.  
  15669. #define  DIGIO_CAT    0x91         // category for DosDevIOCtl
  15670. #define  DIGIO_BASE   0x2c0        // board address
  15671. #define  DIGIO_OUTPUT DIGIO_BASE   // output port
  15672. #define  DIGIO_INPUT  DIGIO_BASE+1 // input port
  15673. #define  DIGIO_CONFIG DIGIO_BASE+3 // initialization port
  15674.  
  15675.  
  15676. ΓòÉΓòÉΓòÉ 23.14. Parallel Device Driver Make File ΓòÉΓòÉΓòÉ
  15677.  
  15678. digio.sys: drvstart.obj digio.obj
  15679.      link /nod /noi /map drvstart+digio,digio.sys,digio,\
  15680. c:\c6\lib\os2+c:\c6\lib\slibcep+c:\drvlib\drvlib\drvlib,digio.def
  15681.      mapsym digio
  15682.  
  15683. drvstart.obj: drvstart.asm
  15684.  masm -Mx -e -t -L -N drvstart;
  15685.  
  15686. digio.obj: digio.c drvlib.h digio.h
  15687.  cl -c -Asnw -Gs -G2 -Fc -Zl -Zp -Ox digio.c
  15688.  
  15689.  
  15690. ΓòÉΓòÉΓòÉ 23.15. Parallel Device Driver DEF File ΓòÉΓòÉΓòÉ
  15691.  
  15692. LIBRARY DIGIO$
  15693. PROTMODE
  15694.  
  15695.  
  15696. ΓòÉΓòÉΓòÉ 23.16. Sample OS/2 Serial Device Driver ΓòÉΓòÉΓòÉ
  15697.  
  15698. // file sample.c sample OS/2 serial device driver
  15699.  
  15700. #include "drvlib.h"
  15701. #include "uart.h"
  15702. #include "sample.h"
  15703.  
  15704. extern void near STRAT();     // name of strat rout.
  15705. extern void near TIMER();     // timer handler
  15706. extern int  near INT_HNDLR(); // interrupt hand
  15707.  
  15708. DEVICEHDR devhdr = {
  15709.  (void far *) 0xFFFFFFFF,     // link
  15710.  (DAW_CHR | DAW_OPN | DAW_LEVEL1),// attribute
  15711.  (OFF) STRAT,                 // &strategy
  15712.  (OFF) 0,                     // &IDCroutine
  15713.  "DEVICE1 "
  15714.   };
  15715.  
  15716. CHARQUEUE   rx_queue;      // receiver queue
  15717. CHARQUEUE   tx_queue;      // transmitter queue
  15718. FPFUNCTION  Device_Help=0; // for DevHlp calls
  15719. LHANDLE     lock_seg_han;  // handle for locking
  15720. PHYSADDR    appl_buffer=0; // address of caller
  15721. PREQPACKET  p=0L;          // Request Packet ptr
  15722. ERRCODE     err=0;         // error return
  15723. void        far *ptr;      // temp far pointer
  15724. DEVICEHDR   *hptr;         // pointer to Device
  15725. USHORT      i;             // general counter
  15726. UARTREGS    uart_regs;     // uart registers
  15727. ULONG       WriteID=0L;    // ID for write Block
  15728. ULONG       ReadID=0L;     // ID for read Block
  15729. PREQPACKET  ThisReadRP=0L; // for read Request
  15730. PREQPACKET  ThisWriteRP=0L;// for write Request
  15731. char        inchar,outchar;// temp chars
  15732. USHORT      baud_rate;     // current baud rate
  15733. unsigned    int savepid;   // PID of driver own
  15734. UCHAR       opencount;     // number of times
  15735. ULONG       tickcount;     // for timeouts
  15736. unsigned    int com_error_word; // UART status
  15737. USHORT      port;          // port variable
  15738. USHORT      temp_bank;     // holds UART bank
  15739. QUEUE       rqueue;        // receive queue info
  15740.  
  15741. void near init();
  15742. void near enable_write();
  15743. void near disable_write();
  15744. void near set_dlab();
  15745. void near reset_dlab();
  15746. void near config_82050();
  15747.  
  15748. char   IntFailMsg[] = " interrupt handler failed to install.\r\n";
  15749. char   MainMsg[] = " OS/2 Serial Device Driver V1.0 installed.\r\n";
  15750.  
  15751. // common entry point to strat routines
  15752.  
  15753. int main(PREQPACKET rp, int dev )
  15754. {
  15755.    void far *ptr;
  15756.    int far *pptr;
  15757.    PLINFOSEG liptr;    // pointer to local info
  15758.    int i;
  15759.    ULONG addr;
  15760.  
  15761.    switch(rp->RPcommand)
  15762.     {
  15763.     case RPINIT:       // 0x00
  15764.  
  15765.         // init called by kernel in prot mode
  15766.  
  15767.         return Init(rp,dev);
  15768.  
  15769.     case RPOPEN:       // 0x0d
  15770.  
  15771.         // get current processes id
  15772.  
  15773.         if (GetDOSVar(2,&ptr))
  15774.             return (RPDONE|RPERR|ERROR_BAD_COMMAND);
  15775.  
  15776.         // get process info
  15777.  
  15778.         liptr = *((PLINFOSEG far *) ptr);
  15779.  
  15780.         // if this device never opened
  15781.  
  15782.         if (opencount == 0) // 1st time dev op'd
  15783.         {
  15784.             ThisReadRP=0L;
  15785.             ThisWriteRP=0L;
  15786.             opencount=1;  // set open counter
  15787.             savepid = liptr->pidCurrent; // PID
  15788.             QueueInit(&rx_queue);// init driver
  15789.             QueueInit(&tx_queue);
  15790.         }
  15791.         else
  15792.             {
  15793.             if (savepid != liptr->pidCurrent)
  15794.                 return (RPDONE | RPERR | RPBUSY );
  15795.             ++opencount;       // bump counter
  15796.         }
  15797.         return (RPDONE);
  15798.  
  15799.     case RPCLOSE:        // 0x0e
  15800.  
  15801.         // get process info of caller
  15802.  
  15803.         if (GetDOSVar(2,&ptr))
  15804.             return (RPDONE|RPERR|ERROR_BAD_COMMAND); // no info
  15805.  
  15806.         // get process info from os/2
  15807.  
  15808.         liptr= *((PLINFOSEG far *) ptr); // PID
  15809.         if (savepid != liptr->pidCurrent ||
  15810.            opencount == 0)
  15811.         return (RPDONE|RPERR|ERROR_BAD_COMMAND);
  15812.         --opencount;   // close counts down open
  15813.  
  15814.         if (ThisReadRP !=0 && opencount == 0) {
  15815.             Run((ULONG) ThisReadRP); // dangling
  15816.             ThisReadRP=0L;
  15817.         }
  15818.         return (RPDONE);     // return 'done'
  15819.  
  15820.     case RPREAD:             // 0x04
  15821.  
  15822.         //  Try to read a character
  15823.  
  15824.         ThisReadRP = rp;
  15825.         if (opencount == 0)// drvr was closed
  15826.         {
  15827.             rp->s.ReadWrite.count = 0;  // EOF
  15828.             return(RPDONE);
  15829.         }
  15830.         com_error_word=0;// start off no errors
  15831.         ReadID = (ULONG) rp;
  15832.         if (Block(ReadID, -1L, 0, &err))
  15833.             if (err == 2)       // interrupted
  15834.                return(RPDONE|RPERR|ERROR_CHAR_CALL_INTERRUPTED);
  15835.  
  15836.         if (rx_queue.qcount == 0) {
  15837.            rp->s.ReadWrite.count=0;
  15838.            return (RPDONE|RPERR|ERROR_NOT_READY);
  15839.            }
  15840.  
  15841.         i=0;
  15842.         do {
  15843.           if (Movedata(&inchar,
  15844.           (FARPOINTER) (rp->s.ReadWrite.buffer+i),
  15845.           1,2))
  15846.             return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  15847.             }
  15848.         while (++i < rp->s.ReadWrite.count
  15849.             && !QueueRead(&rx_queue,&inchar));
  15850.         rp->s.ReadWrite.count = i;
  15851.         QueueInit(&rx_queue);
  15852.         return(rp->RPstatus);
  15853.  
  15854.     case RPWRITE:        // 0x08
  15855.  
  15856.         ThisWriteRP = rp;
  15857.  
  15858.         // transfer characters from user buffer
  15859.  
  15860.         addr=rp->s.ReadWrite.buffer;// get addr
  15861.         for (i = rp->s.ReadWrite.count; i; --i,++addr)
  15862.         {
  15863.           if (Movedata((FARPOINTER)addr,
  15864.               &outchar,1,1))
  15865.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  15866.  
  15867.           if (QueueWrite(&tx_queue,outchar))
  15868.               return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  15869.           }
  15870.         WriteID = (ULONG) rp;
  15871.         enable_write();
  15872.  
  15873.         if (Block(WriteID, -1L, 0, &err))
  15874.             if (err == 2)   // interrupted
  15875.                 return(RPDONE|RPERR|ERROR_CHAR_CALL_INTERRUPTED);
  15876.  
  15877.         tickcount=MIN_TIMEOUT; // reset timeout
  15878.         QueueInit(&tx_queue);
  15879.         return (rp->RPstatus);
  15880.  
  15881.     case RPINPUT_FLUSH:      // 0x07
  15882.  
  15883.         QueueFlush(&rx_queue);
  15884.         return (RPDONE);
  15885.  
  15886.     case RPOUTPUT_FLUSH:     // 0x0b
  15887.  
  15888.         QueueFlush(&tx_queue);
  15889.         return (RPDONE);
  15890.  
  15891.     case RPIOCTL:            // 0x10
  15892.  
  15893.         if (!((rp->s.IOCtl.category == SAMPLE_CAT)
  15894.            || (rp->s.IOCtl.category == 0x01)))
  15895.               return (RPDONE);
  15896.  
  15897.         switch (rp->s.IOCtl.function)
  15898.         {
  15899.         case 0x41:    // set baud rate
  15900.         // set baud rate to 1.2, 2.4, 9.6, 19.2
  15901.         // verify caller owns the buffer area
  15902.  
  15903.         if(VerifyAccess(
  15904.          SELECTOROF(rp->s.IOCtl.parameters),
  15905.          OFFSETOF(rp->s.IOCtl.parameters),
  15906.          2,             // two bytes
  15907.          1) )           // read/write
  15908.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  15909.  
  15910.          // lock the segment down temp
  15911.  
  15912.          if(LockSeg(
  15913.          SELECTOROF(rp->s.IOCtl.parameters),
  15914.          0,          // lock for < 2 sec
  15915.          0,          // wait for seg lock
  15916.          (PLHANDLE) &lock_seg_han)) // handle
  15917.              return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  15918.  
  15919.          // get physical address of buffer
  15920.          if (VirtToPhys(
  15921.          (FARPOINTER) rp->s.IOCtl.parameters,
  15922.          (FARPOINTER) &appl_buffer))
  15923.              return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  15924.  
  15925.          // move data to local driver buffer
  15926.  
  15927.          if(MoveData(
  15928.          (FARPOINTER) appl_buffer,  // source
  15929.          &baud_rate,      // destination
  15930.          2,               // 2 bytes
  15931.          1))              // phys to virt
  15932.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  15933.  
  15934.          if (UnPhysToVirt()) // release selector
  15935.                 return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  15936.  
  15937.          // unlock segment
  15938.  
  15939.          if(UnLockSeg(lock_seg_han))
  15940.               return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  15941.  
  15942.          switch (baud_rate)
  15943.             {
  15944.             case 1200:
  15945.  
  15946.                 uart_regs.Bal=0xe0;
  15947.                 uart_regs.Bah=0x01;
  15948.                 break;
  15949.  
  15950.             case 2400:
  15951.  
  15952.                 uart_regs.Bal=0xf0;
  15953.                 uart_regs.Bah=0x00;
  15954.                 break;
  15955.  
  15956.             case 9600:
  15957.  
  15958.                 uart_regs.Bal=0x3c;
  15959.                 uart_regs.Bah=0x00;
  15960.                 break;
  15961.  
  15962.             case 19200:
  15963.  
  15964.                 uart_regs.Bal=0x1e;
  15965.                 uart_regs.Bah=0x00;
  15966.                 break;
  15967.  
  15968.             case 38400:
  15969.  
  15970.                 uart_regs.Bal=0x0f;
  15971.                 uart_regs.Bah=0x00;
  15972.                 break;
  15973.  
  15974. error:
  15975.             return (RPDONE|RPERR|ERROR_BAD_COMMAND);
  15976.  
  15977.             }
  15978.             init();      // reconfigure uart
  15979.             return (RPDONE);
  15980.  
  15981.         case 0x68:       // get number of chars
  15982.  
  15983.             // verify caller owns the buffer
  15984.  
  15985.             if(VerifyAccess(
  15986.             SELECTOROF(rp->s.IOCtl.buffer),
  15987.             OFFSETOF(rp->s.IOCtl.buffer),
  15988.             4,            // 4 bytes
  15989.             1) )          // read/write
  15990.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  15991.  
  15992.             // lock the segment down temp
  15993.  
  15994.             if(LockSeg(
  15995.             SELECTOROF(rp->s.IOCtl.buffer),
  15996.             0,           // lock for < 2 sec
  15997.             0,           // wait for seg lock
  15998.             (PLHANDLE) &lock_seg_han)) // handle
  15999.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  16000.  
  16001.             // get physical address of buffer
  16002.  
  16003.             if (VirtToPhys(
  16004.             (FARPOINTER) rp->s.IOCtl.buffer,
  16005.             (FARPOINTER) &appl_buffer))
  16006.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  16007.  
  16008.             rqueue.cch=rx_queue.qcount;
  16009.             rqueue.cb=rx_queue.qsize;
  16010.  
  16011.             // move data to local driver buffer
  16012.  
  16013.             if(Movedata(
  16014.             &rx_queue,   // source
  16015.             (FARPOINTER) appl_buffer, // dest
  16016.             4,           // 4 bytes
  16017.             2))          // virt to phys
  16018.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  16019.  
  16020.             if (UnPhysToVirt())
  16021.                 return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  16022.  
  16023.             // unlock segment
  16024.  
  16025.             if(UnLockSeg(lock_seg_han))
  16026.                 return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  16027.  
  16028.             return (RPDONE);
  16029.  
  16030.         case 0x6d:    // get COM error info
  16031.  
  16032.             // verify caller owns the buffer
  16033.  
  16034.             if(VerifyAccess(
  16035.             SELECTOROF(rp->s.IOCtl.buffer),
  16036.             OFFSETOF(rp->s.IOCtl.buffer),
  16037.             2,        // two bytes
  16038.             1) )      // read/write
  16039.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  16040.  
  16041.             // lock the segment down temp
  16042.  
  16043.             if(LockSeg(
  16044.             SELECTOROF(rp->s.IOCtl.buffer),
  16045.             0,        // lock for < 2 sec
  16046.             0,        // wait for seg lock
  16047.             (PLHANDLE) &lock_seg_han)) // handle
  16048.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  16049.  
  16050.             // get physical address of buffer
  16051.  
  16052.             if (VirtToPhys(
  16053.             (FARPOINTER) rp->s.IOCtl.buffer,
  16054.             (FARPOINTER) &appl_buffer))
  16055.                return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  16056.  
  16057.             // move data to application buffer
  16058.  
  16059.             if(Movedata(
  16060.             &com_error_word, // source
  16061.             (FARPOINTER) appl_buffer, // dest
  16062.             2,        // 2 bytes
  16063.             2))       // virt to phys
  16064.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  16065.  
  16066.             if (UnPhysToVirt())
  16067.                 return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  16068.  
  16069.             // unlock segment
  16070.  
  16071.             if(UnLockSeg(lock_seg_han))
  16072.                 return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  16073.  
  16074.             return (RPDONE);
  16075.  
  16076.         default:
  16077.             return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  16078.         }
  16079.  
  16080.         // don't allow deinstall
  16081.  
  16082.     case RPDEINSTALL:  // 0x14
  16083.         return(RPDONE|RPERR|ERROR_BAD_COMMAND);
  16084.  
  16085.     // all other commands are ignored
  16086.  
  16087.     default:
  16088.         return(RPDONE);
  16089.  
  16090.     }
  16091. }
  16092.  
  16093. void enable_write()
  16094.  
  16095. // enable write interrupts on uart
  16096.  
  16097. {
  16098.     int  port;
  16099.     int  reg_val;
  16100.  
  16101.     port=UART_PORT_ADDRESS;
  16102.     reg_val=inp(port+2) & 0x60;
  16103.     set_bank(00);
  16104.     outp((port+1),inp(port+1) | 0x12);
  16105.     outp((port+2),reg_val);
  16106.  
  16107. }
  16108. void disable_write()
  16109.  
  16110. // turn off write interrupts on uart
  16111.  
  16112. {
  16113.     int  port;
  16114.     int  reg_val;
  16115.  
  16116.     port=UART_PORT_ADDRESS;
  16117.     reg_val=inp(port+2) & 0x60;
  16118.     set_bank(00);
  16119.     outp((port+1),inp(port+1) & 0xed);
  16120.     outp((port+2),reg_val);
  16121.  
  16122. }
  16123.  
  16124. void init ()
  16125.  
  16126. // intializes software and configures 82050
  16127.  
  16128. {
  16129.     config_82050 ();    // Configure 82050
  16130.     set_bank(01);
  16131. }
  16132.  
  16133. void config_82050()
  16134.  
  16135. //  Configure the 82050
  16136.  
  16137. {
  16138.     int  port;
  16139.     int inval;
  16140.  
  16141.     Disable();         // disable interrupts
  16142.     port=UART_PORT_ADDRESS;
  16143.  
  16144.     // set stick bit
  16145.  
  16146.     set_bank(01);              // stick bit
  16147.     outp((port+7),0x10);       // reset port
  16148.     outp ((port+1), uart_regs.Txf);// stick bit
  16149.  
  16150.     set_bank (02);         // general config
  16151.     outp ((port + 4), uart_regs.Imd);//auto rupt
  16152.     outp ((port + 7), uart_regs.Rmd);
  16153.     outp ((port + 5), uart_regs.Acr1);// cntl-z
  16154.     outp ((port + 3), uart_regs.Tmd);// no 9 bit
  16155.     outp ((port + 1), uart_regs.Fmd);// rx fifo
  16156.     outp ((port + 6), uart_regs.Rie);// enable
  16157.  
  16158.     set_bank (03);      // modemconfiguration
  16159.  
  16160.     outp ((port + 0), uart_regs.Clcf);// clock
  16161.     set_dlab (03);      //
  16162.     outp ((port + 0), uart_regs.Bbl);// BRGB lsb
  16163.     outp ((port + 1), uart_regs.Bbh);// BRGB msb
  16164.     reset_dlab (03);            //
  16165.     outp ((port + 3), uart_regs.Bbcf);// BRGB
  16166.     outp ((port + 6), uart_regs.Tmie);// timer b
  16167.  
  16168.     set_bank (00);              // general cfg
  16169.     outp ((port + 1), uart_regs.Ger);// enable
  16170.     outp ((port + 3), uart_regs.Lcr);// 8 bit
  16171.     outp ((port + 7), uart_regs.Acr0);// CR
  16172.     outp ((port + 4), uart_regs.Mcr_0);// no DTR
  16173.     set_dlab (00);              //
  16174.     outp ((port + 0), uart_regs.Bal);// BRGA lsb
  16175.     outp ((port + 1), uart_regs.Bah);// BRGA msb
  16176.     reset_dlab (00);
  16177.     set_bank(01);
  16178.  
  16179.     Enable();                       // turn on
  16180. }
  16181.  
  16182. void set_dlab (bank)
  16183.  
  16184. //  Set DLAB bit to allow access to divisior registers
  16185.  
  16186. int bank;
  16187. {
  16188.     int  inval;
  16189.     int  port;
  16190.  
  16191.     port=UART_PORT_ADDRESS;
  16192.     set_bank (00);
  16193.     inval=inp(port +3);
  16194.     inval =inval | 0x80;     // set dlab in LCR
  16195.     outp ((port+3),inval);
  16196.     set_bank (bank);
  16197. }
  16198.  
  16199. getsrc()
  16200.  
  16201. {
  16202.     int   v,src;
  16203.     int   port;
  16204.  
  16205.     port=UART_PORT_ADDRESS; // get base address
  16206.     v=inp(port+2);          // get data
  16207.     src=v & 0x0e;           // mask bits
  16208.     src=src/2;              // divide by 2
  16209.     return(src);            // and pass it back
  16210. }
  16211.  
  16212. set_bank(bank_num)
  16213.  
  16214. // set bank of 82050 uart
  16215.  
  16216. int  bank_num;
  16217.  
  16218. {
  16219.     int reg_val;
  16220.     int   port;
  16221.  
  16222.     reg_val=bank_num*0x20;  // select bank numb
  16223.     port=UART_PORT_ADDRESS; // get real port
  16224.     outp(port+gir_addr,reg_val); // output
  16225. }
  16226.  
  16227. void reset_dlab (bank)
  16228.  
  16229. //  Reset DLAB bit of LCR
  16230.  
  16231. int bank;
  16232.  
  16233. {
  16234.     int  inval;
  16235.     int  port;
  16236.  
  16237.     port=UART_PORT_ADDRESS;
  16238.     set_bank (00);
  16239.     inval=inp (port +3);
  16240.     inval = (inval & 0x7f);  // dlab = 0 in LCR
  16241.     outp ((port+3),inval);
  16242.     set_bank (bank);
  16243. }
  16244.  
  16245. // 82050 interrupt handler
  16246.  
  16247. void interrupt_handler ()
  16248. {
  16249.     int  rupt_dev;
  16250.     int  source;
  16251.     int  cmd_b;
  16252.     int  st_b;
  16253.     int  port;
  16254.     int  temp;
  16255.     int  rxlevel;
  16256.  
  16257.  
  16258.     port=UART_PORT_ADDRESS;
  16259.     outp((port+2),0x20); // switch to bank 1
  16260.     source = getsrc ();  // get vector
  16261.     switch (source)
  16262.     {
  16263.  
  16264.     // optional timer service routine
  16265.  
  16266.     case timer :
  16267.  
  16268.         st_b=inp (port+3); // dec transmit count
  16269.         if ( ThisReadRP == 0) // nobody waiting
  16270.             break;
  16271.         ThisReadRP->RPstatus=(RPDONE|RPERR|ERROR_NOT_READY);
  16272.         Run ((ULONG)  ThisWriteRP);// run thread
  16273.         ThisWriteRP=0;
  16274.         break;
  16275.  
  16276.     case txm   :
  16277.     case txf   :
  16278.  
  16279.         // spurious write interrupt
  16280.  
  16281.         if ( ThisWriteRP == 0) {
  16282.             temp=inp(port+2);
  16283.             break;
  16284.         }
  16285.  
  16286.         // keep transmitting until no data left
  16287.  
  16288.         if  (!(QueueRead(&tx_queue,&outchar)))
  16289.         {
  16290.              outp((port), outchar);
  16291.              tickcount=MIN_TIMEOUT;
  16292.              break;
  16293.         }
  16294.  
  16295.         // done writing, run blocked thread
  16296.  
  16297.         tickcount=MIN_TIMEOUT;
  16298.         disable_write();
  16299.         ThisWriteRP->RPstatus = (RPDONE);
  16300.         Run ((ULONG)  ThisWriteRP);
  16301.         ThisWriteRP=0;
  16302.         break;
  16303.  
  16304.     case ccr   :
  16305.  
  16306.         // control character, treat as normal
  16307.  
  16308.         inchar=inp(port+5);
  16309.  
  16310.     case rxf   :
  16311.  
  16312.         // rx fifo service routine
  16313.  
  16314.         if ( ThisReadRP == 0)
  16315.             inchar=inp (port); // get character
  16316.         else
  16317.         {
  16318.         temp=inp(port+4);
  16319.         rxlevel=(temp & 0x70) / 0x10;
  16320.  
  16321.          // empty out chip FIFO
  16322.  
  16323.          while (rxlevel !=0) {
  16324.  
  16325.            inchar=inp (port); // get character
  16326.            rxlevel--;
  16327.            tickcount=MIN_TIMEOUT;
  16328.  
  16329.            // write input data to queue
  16330.  
  16331.            if(QueueWrite(&rx_queue,inchar))
  16332.  
  16333.              // error, queue must be full
  16334.  
  16335.              {
  16336.              ThisReadRP->RPstatus=(RPDONE|RPERR|ERROR_GEN_FAILURE);
  16337.              Run ((ULONG) ThisReadRP);
  16338.              ThisReadRP=0;
  16339.              break;
  16340.              }
  16341.            com_error_word |= inp(port+5);
  16342.  
  16343.         } // while rxlevel
  16344.      } // else
  16345.   } // switch (source)
  16346. }
  16347. void timer_handler()
  16348. {
  16349.   if (ThisReadRP == 0)
  16350.         return;
  16351.  
  16352.   tickcount--;
  16353.   if(tickcount == 0)  {
  16354.     ThisReadRP->RPstatus=(RPDONE);
  16355.     Run ((ULONG) ThisReadRP);
  16356.     ThisReadRP=0L;
  16357.     tickcount=MIN_TIMEOUT;
  16358.     }
  16359. }
  16360.  
  16361. // Device Initialization Routine
  16362.  
  16363. int Init(PREQPACKET rp, int dev)
  16364. {
  16365.     register char far *p;
  16366.  
  16367.     // store DevHlp entry point
  16368.  
  16369.     Device_Help = rp->s.Init.DevHlp;
  16370.  
  16371.     // install interrupt hook in vector
  16372.  
  16373.     if (SetTimer((PFUNCTION)TIMER))
  16374.                 goto fail;
  16375.  
  16376.     rx_queue.qsize=QUEUE_SIZE;
  16377.     tx_queue.qsize=QUEUE_SIZE; // init queue
  16378.     init();                    // init the port
  16379.     tickcount=MIN_TIMEOUT;     // set timeout
  16380.  
  16381.     if(SetIRQ(5,(PFUNCTION)INT_HNDLR,0)) {
  16382.  
  16383.      // if we failed, deinstall driver cs+ds=0
  16384. fail:
  16385.      DosPutMessage(1, 8, devhdr.DHname);
  16386.      DosPutMessage (1,strlen(IntFailMsg),IntFailMsg);
  16387.      rp->s.InitExit.finalCS = (OFF) 0;
  16388.      rp->s.InitExit.finalDS = (OFF) 0;
  16389.      return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  16390.      }
  16391.  
  16392. // output initialization message
  16393.  
  16394. DosPutMessage(1, 8, devhdr.DHname);
  16395. DosPutMessage(1, strlen(MainMsg), MainMsg);
  16396.  
  16397. // send back our cs and ds values to os/2
  16398.  
  16399. if (SegLimit(HIUSHORT((void far *) Init),&rp->s.InitExit.finalCS)
  16400.     || SegLimit(HIUSHORT((void far *) MainMsg),
  16401.     &rp->s.InitExit.finalDS))
  16402.      Abort();
  16403.    return(RPDONE);
  16404. }
  16405.  
  16406.  
  16407. ΓòÉΓòÉΓòÉ 23.17. Serial Device Driver Make File ΓòÉΓòÉΓòÉ
  16408.  
  16409. sample.sys: drvstart.obj sample.obj drvlib.lib
  16410.  link /nod /noi /map drvstart+sample,sample.sys,sample,\
  16411. c:\c6\lib\os2+c:\c6\lib\slibcep+c:\drvlib\drvlib\drvlib,sample.def
  16412.  mapsym sample
  16413.  
  16414. drvstart.obj: drvstart.asm
  16415.  masm -Mx -t -L -N drvstart;
  16416.  
  16417. sample.obj: sample.c drvlib.h sample.h uart.h
  16418.  cl -c -Asnw -Gs -G2 -Fc -Zl -Zp -Ox sample.c
  16419.  
  16420.  
  16421. ΓòÉΓòÉΓòÉ 23.18. Serial Device Driver DEF File ΓòÉΓòÉΓòÉ
  16422.  
  16423. LIBRARY SAMPLE
  16424. PROTMODE
  16425.  
  16426.  
  16427. ΓòÉΓòÉΓòÉ 23.19. Sample C Callable DevHlp Interface ΓòÉΓòÉΓòÉ
  16428.  
  16429. ;  DevHlp 0x35
  16430. ;  this routine releases the logical ID (LID)
  16431. ;
  16432. ;  C Calling Sequence:
  16433. ;  if (FreeLIDEntry (USHORT id) ) err
  16434. ;
  16435.            include drvlib.inc
  16436. ;
  16437.            public  FREELIDENTRY
  16438.  
  16439.            extrn  _DevHlp:dword
  16440.            assume CS: _TEXT
  16441. _TEXT      segment word public 'CODE'
  16442.  
  16443. FREELIDENTRY  proc near
  16444.  
  16445.            push  bp
  16446.            mov   bp,sp
  16447.            mov   ax,[bp+4] ; logical ID
  16448.            mov   dl,DevHlp_FreeLIDEntry
  16449.            call  [_DevHlp]
  16450.            jc    error           ; error from device help
  16451.            xor   ax,ax           ; no errors
  16452.            pop   bp
  16453.            ret   2               ; fix up the stack
  16454. error:
  16455.            mov   ax,1            ; return error for C
  16456.            pop   bp
  16457.            ret   2               ; fix up stack and return
  16458.  
  16459. FREELIDENTRY  endp
  16460. _TEXT      ends
  16461.            end
  16462.  
  16463.  
  16464. ΓòÉΓòÉΓòÉ 23.20. C Callable Debugger Breakpoint ΓòÉΓòÉΓòÉ
  16465.  
  16466. ;  int3.asm
  16467. ;
  16468. ;  this is NOT a DevHlp, but merely a simple way to break the
  16469. ;  KDB at a specified point
  16470. ;
  16471. ;  C calling sequence:
  16472. ;  INT3();
  16473. ;
  16474.            .286
  16475.            public  INT3
  16476.            assume   CS: _TEXT
  16477. _TEXT      segment word public 'CODE'
  16478. INT3       proc near
  16479.  
  16480.            int 3
  16481.            ret
  16482.  
  16483. INT3       endp
  16484. _TEXT      ends
  16485.            end
  16486.  
  16487.  
  16488. ΓòÉΓòÉΓòÉ 23.21. Data Transfer Routine ΓòÉΓòÉΓòÉ
  16489.  
  16490. ;  movebyte.asm  OS/2 Version 2.2
  16491. ;
  16492. ;  this routine transfers data to and from the device driver
  16493. ;
  16494. ;  C Calling Sequence:
  16495. ;  if (MoveBytes(far &From,far &To,USHORT Lenth))  err
  16496. ;
  16497.            .286
  16498.            include  drvlib.inc
  16499.  
  16500.            public   MOVEBYTES
  16501.            extrn    _DevHlp:dword
  16502.            assume   CS:_TEXT
  16503. _TEXT      segment  word public 'CODE'
  16504.  
  16505. MOVEBYTES proc near
  16506.  
  16507.            push  bp
  16508.            mov   bp,sp
  16509.            pushf              ; save flags
  16510.            push  di           ; save segment regs
  16511.            push  si           ; and others we use
  16512.            push  es
  16513.            push  ds
  16514.            mov   cx,[bp+4]    ; length
  16515.            or    cx,cx        ; exit if zero
  16516.            mov   ax,1         ; set for bad parameter
  16517.            jz    get_out
  16518.            lds   si,[bp+10]   ; from
  16519.            les   di,[bp+6]    ; to
  16520.            cld
  16521.            test  cx,3         ; can we optimize?
  16522.            jz    double_move  ; yep
  16523.            test  cx,1         ; if even number of bytes, save a
  16524.            jz    wordmove     ; little time by doing a word move
  16525.            rep   movsb
  16526.            jmp   short finish ; done
  16527.  
  16528. double_move:
  16529.            shr   cx,2
  16530.            rep   movsd        ; blast it
  16531.            jmp   short finish; done
  16532.  
  16533. wordmove:
  16534.  
  16535.            shr   cx,1         ; half the number of bytes
  16536.            rep   movsw
  16537.  
  16538. finish:
  16539.            xor   ax,ax
  16540.  
  16541. get_out:
  16542.            pop   ds
  16543.            pop   es
  16544.            pop   si           ; restore regs
  16545.            pop   di
  16546.            popf               ;restore flags
  16547.            pop   bp
  16548.            ret   10           ; fix up stack
  16549.  
  16550. MOVEBYTES  endp
  16551. _TEXT      ends
  16552.            end
  16553.  
  16554.  
  16555. ΓòÉΓòÉΓòÉ 23.22. Sample DMA Routines ΓòÉΓòÉΓòÉ
  16556.  
  16557. // DMA Channel data structure
  16558.  
  16559. typedef struct _DMACh
  16560. {
  16561.    UCHAR  Filler;             // force all fields aligned
  16562.                               // boundaries
  16563.    UCHAR  PageSelect;         // page select
  16564.    USHORT BaseAddress;        // base address
  16565.    USHORT WordCount;          // word count
  16566. } DMACh;
  16567.  
  16568. // DMA Channel 5
  16569.  
  16570. #define DMA_PAGE_SELECT_5     0x8B
  16571. #define DMA_BASE_ADDRESS_5    0xC4
  16572. #define DMA_WORD_COUNT_5      0xC6
  16573.  
  16574. // DMA Channel 6
  16575.  
  16576. #define DMA_PAGE_SELECT_6     0x89
  16577. #define DMA_BASE_ADDRESS_6    0xC8
  16578. #define DMA_WORD_COUNT_6      0xCA
  16579.  
  16580. // DMA Channel 7
  16581. #define DMA_PAGE_SELECT_7     0x8A
  16582. #define DMA_BASE_ADDRESS_7    0xCC
  16583. #define DMA_WORD_COUNT_7      0xCE
  16584.  
  16585. // Other DMA Registers
  16586.  
  16587. #define DMA_REFRESH_CHANNEL   0x8F
  16588. #define DMA_MASK_REGISTER     0xD4
  16589. #define DMA_MODE_REGISTER     0xD6
  16590. #define DMA_BYTE_POINTER_FLIPFLOP   0xD8
  16591. #define DMA_MASTER_RESET      0xDA
  16592. #define DMA_RESET_MASK_REGISTER   0xDC
  16593.  
  16594. // DMA Mode Flag Bit Definitions
  16595.  
  16596. #define DMA_WRITE 0x04        // write transfer
  16597. #define DMA_READ  0x08        // read transfer
  16598. #define DMA_AUTOINIT 0x10     // autoinit enabled
  16599. #define DMA_DECREMENT 0x20    // address dec selected
  16600. #define DMA_SINGLE 0x40       // SINGLE mode selected
  16601. #define DMA_BLOCK 0x80        // BLOCK mode selected
  16602. #define DMA_CASCADE 0xC0      // CASCADE mode selected
  16603.  
  16604.  
  16605. USHORT  SetupDMA(USHORT channel)
  16606.     {
  16607.     if(DMAChannelBusy(channel))
  16608.        return (DMA_CHANNEL_BUSY);
  16609.     MaskDMA(channel);
  16610.     SetDMAMode(channel,DMA_SINGLE | DMA_READ);
  16611.     InitDMA(channel,(UCHAR) DMACh.PageSelect,
  16612.       (USHORT) DMACh.BaseAddress,
  16613.       (USHORT) DMACh.WordCount);
  16614.     UnmaskDMA(channel);
  16615.     return (DMA_COMPLETE);
  16616.     }
  16617.  
  16618.  
  16619. void MaskDMA(USHORT channel)
  16620. {
  16621. UCHAR channel_mask;
  16622.  
  16623. // output a channel specific value to mask a DMA channel
  16624.  
  16625. switch (channel) {
  16626.  
  16627.     case 5:
  16628.       channel_mask = 5;
  16629.       break;
  16630.  
  16631.     case 6:
  16632.       channel_mask = 6;
  16633.       break;
  16634.  
  16635.     case 7:
  16636.       channel_mask = 7;
  16637.       break;
  16638.       }
  16639.   out8reg(DMA_MASK_REGISTER,channel_mask);
  16640. }
  16641.  
  16642.  
  16643. void SetDMAMode(USHORT channel,UCHAR mode)
  16644. {
  16645. unsigned char mode_byte;
  16646.  
  16647. // output a channel specific value to unmask a DMA channel
  16648.  
  16649. switch (channel) {
  16650.  
  16651.    case 5:
  16652.        mode_byte = mode | 0x01;
  16653.        break;
  16654.  
  16655.    case 6:
  16656.        mode_byte = mode | 0x02;
  16657.        break;
  16658.  
  16659.    case 7:
  16660.        mode_byte = mode | 0x03;
  16661.        break;
  16662.       }
  16663.    out8reg(DMA_MODE_REGISTER,mode_byte);
  16664. }
  16665.  
  16666.  
  16667. void InitDMA(USHORT channel,UCHAR page,USHORT address,
  16668.             USHORT count)
  16669. {
  16670. // set up page select, addr, and cnt for specified channel
  16671.  
  16672. switch (channel) {
  16673.  
  16674.    case 5:
  16675.       out8reg(DMA_PAGE_SELECT_5,page);
  16676.       out16reg(DMA_BASE_ADDRESS_5,address);
  16677.       out16reg(DMA_WORD_COUNT_5,count);
  16678.       break;
  16679.  
  16680.    case 6:
  16681.       out8reg(DMA_PAGE_SELECT_6,page);
  16682.       out16reg(DMA_BASE_ADDRESS_6,address);
  16683.       out16reg(DMA_WORD_COUNT_6,count);
  16684.       break;
  16685.  
  16686.    case 7:
  16687.       out8reg(DMA_PAGE_SELECT_7,page);
  16688.       out16reg(DMA_BASE_ADDRESS_7,address);
  16689.       out16reg(DMA_WORD_COUNT_7,count);
  16690.       break;
  16691.       }
  16692. }
  16693.  
  16694.  
  16695. void UnmaskDMA(USHORT channel)
  16696. {
  16697. unsigned char unmask_byte;
  16698.  
  16699. // output a channel specific value to unmask a DMA channel
  16700.  
  16701. switch (channel) {
  16702.  
  16703. case 5:
  16704.     unmask_byte = 1;
  16705.     break;
  16706.  
  16707. case 6:
  16708.     unmask_byte = 2;
  16709.     break;
  16710.  
  16711. case 7:
  16712.     unmask_byte = 3;
  16713.     break;
  16714.     }
  16715.  out8reg(DMA_MASK_REGISTER,unmask_byte);
  16716. }
  16717.  
  16718.  
  16719. USHORT DMAChannelBusy(USHORT ch)
  16720. {
  16721.  
  16722.   UCHAR ch_status;
  16723.   USHORT rc;
  16724.  
  16725. // returns 0 if not busy, 1 if busy
  16726.  
  16727.    ch_status = inp (DMA_STATUS_REG47)
  16728.    rc = 0;
  16729.    switch(ch) {
  16730.  
  16731.       case 5:
  16732.          if (ch_status & 0x20)
  16733.          rc = 1;
  16734.          break;
  16735.  
  16736.       case 6:
  16737.          if (ch_status & 0x40)
  16738.          rc = 1;
  16739.          break;
  16740.  
  16741.       case 7:
  16742.          if (ch_status & 0x80)
  16743.          rc = 1;
  16744.          break
  16745.       }
  16746.    return (rc);
  16747. }
  16748.  
  16749.  
  16750. ; out16reg(port,word);
  16751. ;
  16752. ; write a 16-bit value to a DMA register by issuing two
  16753. ; consecutive writes to an 8-bit register
  16754. ;
  16755.       .286
  16756.  
  16757.            include mmap.inc
  16758.  
  16759. _TEXT      SEGMENT BYTE PUBLIC 'CODE'
  16760. _TEXT      ENDS
  16761.  
  16762.            assume CS: _TEXT
  16763.  
  16764. _TEXT SEGMENT
  16765.  
  16766. _out16reg  proc near
  16767.  
  16768.            public _out16reg
  16769.  
  16770.            cli
  16771.            push  bp
  16772.            mov   bp,sp        ;set up base pointer
  16773.            pusha              ;save regs
  16774.            pushf              ;and flags
  16775.            push  es
  16776.            push  ds
  16777.  
  16778. ;make sure that first write goes to low byte of register
  16779.  
  16780.            mov   dx,DMA_BYTE_POINTER_FLIPFLOP
  16781.            mov   al,0         ;reset byte pointer
  16782.            out   dx,al
  16783.            jmp   $+2          ;register delay
  16784.            jmp   $+2
  16785.            mov   dx,word ptr [bp+4] ;output port address
  16786.            mov   al,byte ptr [bp+6] ;byte to be output
  16787.            out   dx,al        ;output low byte
  16788.            jmp   $+2
  16789.            jmp   $+2
  16790.            mov   al,byte ptr [bp+7];byte to be output
  16791.            out   dx,al        ;output high byte
  16792.            jmp   $+2
  16793.            jmp   $+2
  16794.            pop   ds           ;restore registers
  16795.            pop   es
  16796.            popf
  16797.            popa
  16798.            pop   bp
  16799.            sti
  16800.            ret
  16801.  
  16802. _out16reg  endp
  16803. _text      ends
  16804.            end
  16805.  
  16806.  
  16807. ; out8reg(port,byte)
  16808. ;
  16809. ; write a simple 8 bit register with interrupts off
  16810.  
  16811.            .286
  16812.  
  16813.            include mmap.inc
  16814.  
  16815. _TEXT      SEGMENT BYTE PUBLIC 'CODE'
  16816. _TEXT      ENDS
  16817.  
  16818.            assume CS: _TEXT
  16819.  
  16820. _TEXT SEGMENT
  16821.  
  16822. _out8reg   proc near
  16823.  
  16824.            public  _out8reg
  16825.  
  16826.            cli
  16827.            push   bp
  16828.            mov    bp,sp       ;set up base pointer
  16829.            pusha              ;save regs
  16830.            pushf   ;and flags
  16831.            push   es
  16832.            push   ds
  16833.            mov    dx,word ptr [bp+4] ;output register address
  16834.            mov    al,byte ptr [bp+6] ;byte to be output
  16835.            out    dx,al       ;output low byte
  16836.            jmp    $+2
  16837.            jmp    $+2
  16838.            pop    ds          ;restore registers
  16839.            pop    es
  16840.            popf
  16841.            popa
  16842.            pop    bp
  16843.            sti
  16844.            ret
  16845.  
  16846. _out8reg   endp
  16847. _text      ends
  16848.            end
  16849.  
  16850.            title _word_dma
  16851.            .286P
  16852.            .model  small
  16853.            include  bsedos.inc
  16854. ;
  16855. ; dma set up and execute routine
  16856. ;
  16857. ; calling sequence:
  16858. ;
  16859. ; word_dma(USHORT operation, 1=write, 2=read         [bp+4]
  16860. ;    USHORT channel,    5, 6 or 7                    [bp+6]
  16861. ;    USHORT count,      0-65535 (0=1 word)           [bp+8]
  16862. ;    ULONG address,     far to/from address          [bp+10,12]
  16863. ;    USHORT auto,       0 for single, 1 for auto     [bp+14]
  16864. ;    USHORT init)       0 no auto init, 1 auto init  [bp+16]
  16865. ;
  16866. _text      segment public 'CODE'
  16867.            assume  cs:_text,ds:NOTHING
  16868.            public  _word_dma
  16869.  
  16870. _word_dma  proc   near
  16871.            push   bp          ;
  16872.            mov    bp,sp       ;current frame pointer
  16873.            cli                ;disable rupts during dma setup
  16874.            push   bx
  16875.            push   dx
  16876.            mov    ax,[bp+6]   ;get channel number
  16877.            sub    ax,4        ;minus 4 for second controller
  16878.            mov    bx,[bp+4]   ;get mode byte and make command
  16879.            shl    bx,2        ;make valid mode bits
  16880.            or     ax,bx
  16881.            mov    bx,[bp+14]  ;or in initialize bit
  16882.            cmp    bx,0        ;autoinitialize selected?
  16883.            jz     output      ;no
  16884.            or     ax,010h     ;yes, add in autoinitialize bit
  16885. output:
  16886.            mov    bx,[bp+16]  ;block or single mode?
  16887.            or     ax,40h      ;default single
  16888.            cmp    bx,0
  16889.            jz     single      ;single mode
  16890.            and    ax,0bfh     ;make block mode
  16891.            or     ax,080h
  16892. single:
  16893.            out    0d8h,al     ;set the first/last flip flop
  16894.            jmp    short $+2   ;small delay
  16895.            out    0d6h,al     ;output the mode byte
  16896.            mov    dx,[bp+6]   ;get channel number
  16897.            sub    dx,4        ;minus 4 for second controller
  16898.            mov    ax,08ah     ;set page register
  16899.            add    ax,dx       ;
  16900.            push   dx          ;save port temp
  16901.            mov    dx,ax       ;put page register address in dx
  16902.            mov    ax,ds       ;high page address
  16903.            out    dx,al       ;do it
  16904.            pop    dx
  16905.            rol    dx,2        ;times 4 for proper address
  16906.            add    dx,0c0h     ;this is port address
  16907.            mov    ax,[bp+10]  ;low offset address
  16908.            out    dx,al
  16909.            jmp    short $+2
  16910.            mov    al,ah       ;now high part
  16911.            out    dx,al       ;do it
  16912.            jmp    short $+2
  16913.            add    dx,2        ;formulate count address
  16914.            mov    ax,[bp+8]   ;put low and
  16915.            out    dx,al       ;high count to controller
  16916.            jmp    short $+2
  16917.            mov    al,ah
  16918.            out    dx,al
  16919.            jmp    short $+2
  16920.            sti                ;re-enable interrupts
  16921.            mov    ax,4        ;request dma transfer
  16922.            or     ax,[bp+6]   ;add in channel number
  16923.            out    0d2h,al     ;request dma transfer
  16924.            jmp    short $+2
  16925.            pop    dx
  16926.            pop    bx
  16927.            pop    bp
  16928.            ret
  16929. ;
  16930. _word_dma  endp
  16931. _text      ends
  16932.            end
  16933.  
  16934.  
  16935. ΓòÉΓòÉΓòÉ 23.23. Obtaining POS Register Contents ΓòÉΓòÉΓòÉ
  16936.  
  16937. USHORT get_POS(USHORT slot_num,USHORT far *card_ID,UCHAR far *pos_regs)
  16938. {
  16939. USHORT rc, i, lid;
  16940.  
  16941. if (GetLIDEntry(0x10, 0, 1, &lid))  // POS LID
  16942.     return (1);
  16943.  
  16944. // Get the size of the LID request block
  16945.  
  16946. ABIOS_l_blk.f_parms.req_blk_len=sizeof(struct lid_block_def);
  16947. ABIOS_l_blk.f_parms.LID = lid;
  16948. ABIOS_l_blk.f_parms.unit = 0;;
  16949. ABIOS_l_blk.f_parms.function = GET_LID_BLOCK_SIZE;
  16950. ABIOS_l_blk.f_parms.ret_code = 0x5a5a;
  16951. ABIOS_l_blk.f_parms.time_out = 0;
  16952.  
  16953. if (ABIOSCall(lid,0,(void far *)&ABIOS_l_blk))
  16954.     return (1);
  16955.  
  16956. lid_blk_size = ABIOS_l_blk.s_parms.blk_size;
  16957.  
  16958. // Fill POS regs with 0 and card ID with -1
  16959.  
  16960. *card_ID = 0xFFFF;
  16961. for (i=0; i<NUM_POS_BYTES; i++) { pos_regs[i] =
  16962.     0x00; };
  16963.  
  16964. // Get the POS registers and card ID for slot
  16965.  
  16966. ABIOS_r_blk.f_parms.req_blk_len = lid_blk_size;
  16967. ABIOS_r_blk.f_parms.LID = lid;
  16968. ABIOS_r_blk.f_parms.unit = 0;;
  16969. ABIOS_r_blk.f_parms.function = READ_POS_REGS_CARD;
  16970. ABIOS_r_blk.f_parms.ret_code = 0x5a5a;
  16971. ABIOS_r_blk.f_parms.time_out = 0;
  16972.  
  16973. ABIOS_r_blk.s_parms.slot_num = (UCHAR)slot_num & 0x0F;
  16974. ABIOS_r_blk.s_parms.pos_buf = (void far * ) pos_regs;
  16975. ABIOS_r_blk.s_parms.card_ID = 0xFFFF;
  16976. if (ABIOSCall(lid,0,(void far *)&ABIOS_r_blk))
  16977.      rc = 1;
  16978. else {
  16979.      *card_ID = ABIOS_r_blk.s_parms.card_ID;
  16980.      rc = 0;
  16981.      }
  16982. FreeLIDEntry(lid);
  16983. return(rc);
  16984. }
  16985.  
  16986.  
  16987. ΓòÉΓòÉΓòÉ 23.24. ABIOS Specific Include File ΓòÉΓòÉΓòÉ
  16988.  
  16989. // ABIOS specific includes
  16990.  
  16991.  
  16992. #define  POS_BASE          0x100    // MCA adapter base
  16993. #define  NUM_POS_BYTES        64    // maximum num POS bytes
  16994. #define  MAX_NUM_SLOTS         8    // model 80 8 slots
  16995. #define  POS_PORT           0x96    // use this to enable POS
  16996. #define  POS_BASE          0x100    // all POS regs start here
  16997.  
  16998. // Constants used by ABIOS calls
  16999.  
  17000. #define GET_LID_BLOCK_SIZE  0x01    // ABIOS command
  17001. #define POS_LID             0x10    // get POS LID from ABIOS
  17002. #define READ_POS_REGS_RAM   0x0B    // read POS from NVRAM
  17003. #define WRITE_POS_REGS_RAM  0x0C    // write NVRAM POS data
  17004. #define READ_POS_REGS_CARD  0x0D    // read POS data from card
  17005. #define WRITE_POS_REGS_CARD 0x0E    // write POS data to card
  17006.  
  17007. // ABIOS request function parameters
  17008.  
  17009. typedef struct function_parms_def
  17010. {
  17011.    USHORT    req_blk_len;           // length, must be init.
  17012.    USHORT    LID;                   // the LID
  17013.    USHORT    unit;                  // unit within a LID
  17014.    USHORT    function;              // category of request
  17015.    USHORT    resvd1;                // reserved
  17016.    USHORT    resvd2;                // reserved
  17017.    USHORT    ret_code;              // return code
  17018.    USHORT    time_out;              // timeout in seconds
  17019. } function_parms_type;
  17020.  
  17021. typedef struct service_parms_def
  17022. {
  17023.    UCHAR     slot_num;              // 10h slot number
  17024.    UCHAR     resvd3;                // 11h reserved
  17025.    USHORT    card_ID;               // 12h card ID
  17026.    USHORT    resvd4;                // 14h reserved
  17027.    UCHAR     far *pos_buf;          // 16h address of buffer
  17028.    USHORT    resvd5;                // 1Ah reserved
  17029.    USHORT    resvd6;                // 1Ch reserved
  17030.    UCHAR     resvd7[40];            // 1Eh work area
  17031. } service_parms_type;
  17032.  
  17033. // LID request parameters
  17034.  
  17035. typedef struct lid_service_parms_def
  17036. {
  17037.    UCHAR     irpt_level;            // 10h interrupt level
  17038.    UCHAR     arb_level;             // 11h arbitration level
  17039.    USHORT    device_id;             // 12h device ID
  17040.    USHORT    unit_count;            // 14h count of units
  17041.    USHORT    flags;                 // 16h LID flags
  17042.    USHORT    blk_size;              // 18h req blk length
  17043.    USHORT    secnd_id;              // 1Ah secondary dev ID
  17044.    USHORT    resvd6;                // 1Ch reserved
  17045.    USHORT    resvd7;                // 1Eh reserved
  17046. } lid_service_parms_type;
  17047.  
  17048. // complete request block
  17049.  
  17050. typedef struct req_block_def
  17051. {
  17052.    function_parms_type f_parms;
  17053.    service_parms_type  s_parms;
  17054. } REQBLK;
  17055.  
  17056. // complete LID block
  17057.  
  17058. typedef struct lid_block_def
  17059. {
  17060.    function_parms_type     f_parms;
  17061.    lid_service_parms_type  s_parms;
  17062. } LIDBLK;
  17063.  
  17064. // card struct, contains ID and POS reg data
  17065.  
  17066. typedef struct card_def
  17067. {
  17068.   USHORT     card_ID;               // ID of the card slot
  17069.   UCHAR      pos_regs[NUM_POS_BYTES];
  17070. } CARD;
  17071.  
  17072.  
  17073. ΓòÉΓòÉΓòÉ 23.25. IOPL Routine For 16-Bit and 32-Bit Applications ΓòÉΓòÉΓòÉ
  17074.  
  17075. ;
  17076. ; Sample IOPL segment
  17077. ;
  17078.             PUBLIC  IN_PORT
  17079.             PUBLIC  OUT_PORT
  17080.  
  17081.            .model large
  17082.            .286P
  17083.  
  17084. _IOSEG     segment  word public USE16 'CODE'
  17085.  
  17086.  assume    CS: _IOSEG, DS: DGROUP, SS: DGROUP
  17087.            .286P
  17088. ;
  17089. IN_PORT    proc    far
  17090. ;
  17091.            push   bp          ;set up stack frame
  17092.            mov    bp,sp       ;save bp
  17093.            push   dx          ;save dx
  17094.            mov    dx,[bp+6]   ;get port address
  17095.            in     ax,dx       ;do input
  17096.            pop    dx          ;restore regs
  17097.            pop    bp          ;return in ax
  17098.            ret    2           ;remove from IOPL stack
  17099. ;
  17100. IN_PORT    endp
  17101.  
  17102. OUT_PORT   proc   far
  17103. ;
  17104.            push   bp          ;set up stack frame
  17105.            mov    bp,sp       ;save it
  17106.            push   ax          ;save ax
  17107.            push   dx          ;and dx
  17108.            mov    ax,[bp+6]   ;get data
  17109.            mov    dx,[bp+8]   ;get port
  17110.            out    dx,al       ;do output
  17111.            pop    dx          ;restore regs
  17112.            pop    ax
  17113.            pop    bp
  17114.            ret    4           ;remove off local stack
  17115. ;
  17116. OUT_PORT   endp
  17117. _IOSEG     ends
  17118.            end
  17119.  
  17120.  
  17121. ΓòÉΓòÉΓòÉ 23.26. IOPL Routine Make File ΓòÉΓòÉΓòÉ
  17122.  
  17123. ioseg.dll: ioseg.obj
  17124.      link /MAP /NOI /NOD ioseg,ioseg.dll,ioseg,d:\lib\llibcdll+\
  17125. os2286,ioseg.def
  17126.  
  17127. ioseg.obj: ioseg.asm
  17128.      masm ioseg.asm;
  17129.  
  17130.  
  17131. ΓòÉΓòÉΓòÉ 23.27. IOPL Routine DEF File ΓòÉΓòÉΓòÉ
  17132.  
  17133. LIBRARY
  17134. PROTMODE
  17135. STACKSIZE 8192
  17136. SEGMENTS
  17137.    _IOSEG IOPL
  17138. EXPORTS
  17139.    IN_PORT   1
  17140.    OUT_PORT  2
  17141.  
  17142.  
  17143. ΓòÉΓòÉΓòÉ 23.28. IOPL Test Program, 16-Bit ΓòÉΓòÉΓòÉ
  17144.  
  17145. //
  17146. //  testio.c - test IOPL functions
  17147. //
  17148.  
  17149. #define INCL_DOS
  17150. #include <os2.h>
  17151.  
  17152. #define INPUT_PORT  0x2f8
  17153. #define OUTPUT_PORT 0x2f8
  17154. #define TEST_DATA   0x41
  17155.  
  17156. extern far pascal in_port();
  17157. extern far pascal out_port();
  17158.  
  17159. int main()
  17160. {
  17161.   USHORT in_stuff;
  17162.  
  17163.   in_stuff = in_port (INPUT_PORT);
  17164.   out_port (OUTPUT_PORT,TEST_DATA);
  17165.  
  17166. }
  17167.  
  17168.  
  17169. ΓòÉΓòÉΓòÉ 23.29. IOPL Test Program Make File, 16-Bit ΓòÉΓòÉΓòÉ
  17170.  
  17171. testio.exe: testio.obj ioseg.obj
  17172.  link /CO /nod /noe /noi /map testio+ioseg,testio.exe,testio,\
  17173. c:\c6\lib\os2+c:\c6\lib\llibcep,testio.def
  17174.  
  17175. testio.obj: testio.c
  17176.  cl -c -AL -G2 testio.c
  17177.  
  17178. ioseg.obj: ioseg.asm
  17179.         masm /MX /T ioseg.asm;
  17180.  
  17181.  
  17182. ΓòÉΓòÉΓòÉ 23.30. IOPL Test Program DEF File, 16-Bit ΓòÉΓòÉΓòÉ
  17183.  
  17184. NAME TESTIO
  17185. STACKSIZE 8192
  17186. SEGMENTS
  17187.     _IOSEG  IOPL
  17188. EXPORTS
  17189.     IN_PORT 1
  17190.     OUT_PORT 2
  17191. PROTMODE
  17192.  
  17193.  
  17194. ΓòÉΓòÉΓòÉ 23.31. IOPL Test Program, 32-Bit ΓòÉΓòÉΓòÉ
  17195.  
  17196. /*
  17197.   testio.c - test IOPL functions
  17198. */
  17199.  
  17200. #define INCL_DOS
  17201. #include <os2.h>
  17202.  
  17203. #define INPUT_PORT  0x2f8
  17204. #define OUTPUT_PORT 0x2f8
  17205. #define TEST_DATA   0x41
  17206.  
  17207. extern USHORT _Far16 _Pascal in_port(USHORT);
  17208. extern void _Far16 _Pascal out_port(USHORT,USHORT);
  17209.  
  17210. int main(vide)
  17211. {
  17212.   USHORT in_stuff;
  17213.  
  17214.   in_stuff = in_port (INPUT_PORT);
  17215.   out_port (OUTPUT_PORT,TEST_DATA);
  17216.  
  17217. }
  17218.  
  17219.  
  17220. ΓòÉΓòÉΓòÉ 23.32. IOPL Test Program Make File, 32-Bit ΓòÉΓòÉΓòÉ
  17221.  
  17222. all: ioseg.lib testio32.exe
  17223.  
  17224. ioseg.lib: ioseg.def
  17225.   implib /nologo ioseg.lib ioseg.def
  17226.  
  17227. testio32.exe: testio32.obj ioseg.obj
  17228.  link386 /noi /map /pm:vio testio32,,testio32,ioseg,testio32
  17229.  
  17230. testio32.obj: testio32.c
  17231.  icc -c -Q -Gd testio32.c
  17232.  
  17233.  
  17234. ΓòÉΓòÉΓòÉ 23.33. IOPL Test Program DEF File, 32-Bit ΓòÉΓòÉΓòÉ
  17235.  
  17236. NAME TESTIO32
  17237. PROTMODE
  17238.  
  17239.  
  17240. ΓòÉΓòÉΓòÉ 23.34. Device Driver For Memory-Mapped Adapters ΓòÉΓòÉΓòÉ
  17241.  
  17242. //   OS/2 Device Driver for memory mapped I/O
  17243. //
  17244. //                Steve Mastrianni
  17245. //                15 Great Oak Lane
  17246. //                Unionville, CT 06085
  17247. //                (203) 693-0404 voice
  17248. //                (203) 693-9042 data
  17249. //                CI$ 71501,1652
  17250. //                BIX smastrianni
  17251. //
  17252. //   This driver is loaded in the config.sys file with the DEVICE=
  17253. //   statement. For ISA configuration, the first parameter to the "DEVICE="
  17254. //   is the board base memory address in hex.
  17255. //
  17256. //   This driver also returns a boolean to the calling application to
  17257. //   inform it of the bus type (Micro Channel or ISA).
  17258. //
  17259. //   All numbers are in hex. For MCA configuration, the board address
  17260. //   is read from the board POS regs. The POS regs data is specific for
  17261. //   each adapter, so the address calculations here may not work with
  17262. //   your specific adapter. Refer to the hardware tech reference for the
  17263. //   particular adapter to determine where and how the address appears
  17264. //   in the POS registers.
  17265. //
  17266. //
  17267. //   This driver allows the application I/O to run in Ring 2 with IOPL.
  17268. //   The CONFIG.SYS files *must* contain the IOPL=YES statement.
  17269. //
  17270. //   This driver supports 4 IOCtls, Category 0x90.
  17271. //
  17272. //   IOCtl 0x01 test for MCA or ISA bus
  17273. //   IOCtl 0x02 gets and returns a selector to fabricated board memory
  17274. //   IOCtl 0x03 gets the value of a selected POS register
  17275. //   IOCtl 0x04 gets the board address that the driver found
  17276. //
  17277. //   The driver is made by using the make file mmap.mak.
  17278.  
  17279. #include "drvlib.h"
  17280. #include "mmap.h"
  17281.  
  17282. extern void near STRATEGY();        // name of strat rout. in DDSTART
  17283.  
  17284. DEVICEHDR devhdr =
  17285. {
  17286.         (void far *) 0xFFFFFFFF,    // link
  17287.         (DAW_CHR | DAW_OPN | DAW_LEVEL1),// attribute
  17288.         (OFF) STRATEGY,             // &strategy
  17289.         (OFF) 0,                    // &IDCroutine
  17290.         "MMAP$   "
  17291. };
  17292.  
  17293. FPFUNCTION  DevHlp=0;               // storage area for DevHlp calls
  17294. LHANDLE     lock_seg_han;           // handle for locking appl. segment
  17295. PHYSADDR    appl_buffer=0;          // address of caller's buffer
  17296. PREQPACKET  p=0L;                   // pointer to request packet
  17297. ERRCODE     err=0;                  // error return
  17298. void        far *ptr;               // temp far pointer
  17299. USHORT      i,j;                    // general counters
  17300. PHYSADDR    board_address;          // base board address
  17301. USHORT      opencount;              // count of DosOpens
  17302. USHORT      savepid;                // save the caller's PID
  17303. USHORT      cntr = 0;               // misc counter
  17304. USHORT      bus = 0;                // default ISA bus
  17305. REQBLK      ABIOS_r_blk;            // ABIOS request block
  17306. LIDBLK      ABIOS_l_blk;            // ABIOS LID block
  17307. USHORT      lid_blk_size;           // size of LID block
  17308. CARD        card[MAX_NUM_SLOTS+1];  // array for IDs and POS reg values
  17309. CARD        *pcard;                 // pointer to card array
  17310. USHORT      matches = 0;            // match flag for card ID
  17311. POS_STRUCT  pos_struct;             // struct to get POS reg
  17312. ADDR_STRUCT addr_struct;            // struct for passing addresses
  17313. USHORT      chunk1,chunk2;          // temp variables for address calc
  17314.  
  17315. char     arguments[64]={0};         // save command line args in dgroup
  17316. char     NoMatchMsg[]  = " no match for selected Micro Channel card ID found.\r\n";
  17317. char     MainMsgMCA[]  = "\r\nOS/2 Micro Channel memory-mapped driver installed.\r\n";
  17318. char     MainMsgISA[]  = "\r\nOS/2 ISA bus memory-mapped driver installed.\r\n";
  17319.  
  17320. // prototypes
  17321.  
  17322. int      hex2bin(char c);
  17323. USHORT   get_POS();
  17324. UCHAR    get_pos_data();
  17325. UCHAR    nget_pos_data();
  17326.  
  17327. // common entry point for calls to Strategy routines
  17328.  
  17329. int main(PREQPACKET rp )
  17330. {
  17331.     void far *ptr;
  17332.     int far *pptr;
  17333.     PLINFOSEG liptr;                // pointer to local info seg
  17334.     int i;
  17335.     ULONG addr;
  17336.     USHORT in_data;
  17337.  
  17338.     switch(rp->RPcommand)
  17339.     {
  17340.     case RPINIT:                    // 0x00
  17341.  
  17342.         // init called by kernel in protected mode ring 3 with IOPL
  17343.  
  17344.         return Init(rp);
  17345.  
  17346.     case RPOPEN:                    // 0x0d
  17347.  
  17348.         // get current processes id
  17349.  
  17350.         if (GetDOSVar(2,&ptr))
  17351.             return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  17352.  
  17353.         // get process info
  17354.  
  17355.         liptr = *((PLINFOSEG far *) ptr);
  17356.  
  17357.         // if this device never opened, can be opened by any process
  17358.  
  17359.         if (opencount == 0)    // first time this device opened
  17360.         {
  17361.             opencount=1;                 // set open counter
  17362.             savepid = liptr->pidCurrent; // save current process id
  17363.         }
  17364.         else
  17365.             {
  17366.             if (savepid != liptr->pidCurrent) // another proc tried to open
  17367.                 return (RPDONE | RPERR | RPBUSY ); // so return error
  17368.             ++opencount;            // bump counter, same pid
  17369.         }
  17370.         return (RPDONE);
  17371.  
  17372.     case RPCLOSE:                   // 0x0e
  17373.  
  17374.         // get process info of caller
  17375.  
  17376.         if (GetDOSVar(2,&ptr))
  17377.             return (RPDONE | RPERR | ERROR_BAD_COMMAND); // no info
  17378.  
  17379.         // get process info from os/2
  17380.  
  17381.         liptr= *((PLINFOSEG far *) ptr); // ptr to process info seg
  17382.  
  17383.         //
  17384.         // make sure that process attempting to close this device
  17385.         // one that originally opened it and the device was open in
  17386.         // first place.
  17387.         //
  17388.  
  17389.         if (savepid != liptr->pidCurrent || opencount == 0)
  17390.             return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  17391.  
  17392.         // if an LDT selector was allocated, free it
  17393.  
  17394.         PhysToUVirt(board_address,0x8000,2,
  17395.                    (FARPOINTER) &addr_struct.mapped_addr);
  17396.  
  17397.         --opencount;                // close counts down open counter
  17398.         return (RPDONE);            // return 'done' status to caller
  17399.  
  17400.     case RPREAD:                    // 0x04
  17401.  
  17402.         return(RPDONE);
  17403.  
  17404.     case RPWRITE:                   // 0x08
  17405.  
  17406.         return (RPDONE);
  17407.  
  17408.     case RPIOCTL:                   // 0x10
  17409.  
  17410.         if (rp->s.IOCtl.category != OUR_CAT) // only our category
  17411.             return (RPDONE);
  17412.  
  17413.         switch (rp->s.IOCtl.function)
  17414.         {
  17415.  
  17416.          // this IOCtl returns the bus type. If the type is Micro Channel
  17417.          // the return is 0xff01. If ISA, the return is ff00
  17418.  
  17419.          case 0x01:                  // check if MCA or ISA
  17420.             return (RPDONE | RPERR | bus);
  17421.  
  17422.         // this IOCtl maps an adapter memory to an LDT selector:offset,
  17423.         // and sends it to the application for direct application reads
  17424.         // and writes
  17425.  
  17426.         case 0x02:                  // send memory-mapped addr to app
  17427.  
  17428.             // verify caller owns this buffer area
  17429.  
  17430.             if(VerifyAccess(
  17431.             SELECTOROF(rp->s.IOCtl.buffer), // selector
  17432.             OFFSETOF(rp->s.IOCtl.buffer),   // offset
  17433.             8,                              // 8 bytes
  17434.             1) )                            // read write
  17435.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17436.  
  17437.             // lock the segment down temp
  17438.  
  17439.             if(LockSeg(
  17440.             SELECTOROF(rp->s.IOCtl.buffer), // selector
  17441.             0,                              // lock < 2 sec
  17442.             0,                              // wait for seg lock
  17443.             (PLHANDLE) &lock_seg_han))      // handle returned
  17444.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17445.  
  17446.            // map the board address to an LDT entry
  17447.  
  17448.            if ( PhysToUVirt(board_address,0x8000,1,
  17449.               (FARPOINTER) &addr_struct.mapped_addr))
  17450.                return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17451.  
  17452.            // move data to users buffer
  17453.  
  17454.            if(MoveBytes(
  17455.            &addr_struct,                   // source
  17456.            rp->s.IOCtl.buffer,             // dest
  17457.            8))                             // 8 bytes
  17458.                return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17459.  
  17460.            // unlock segment
  17461.  
  17462.            if(UnLockSeg(lock_seg_han))
  17463.                return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  17464.  
  17465.            return (RPDONE);
  17466.  
  17467.         // this IOCtl demonstrates how an application program can get the
  17468.         // contents of a Micro Channel Adapter's POS registers
  17469.  
  17470.         case 0x03:                  // get pos reg data
  17471.  
  17472.             // verify caller owns this buffer area
  17473.  
  17474.             if(VerifyAccess(
  17475.             SELECTOROF(rp->s.IOCtl.buffer), // selector
  17476.             OFFSETOF(rp->s.IOCtl.buffer),   // offset
  17477.             6,                              // 6 bytes
  17478.             1) )                            // read write
  17479.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17480.  
  17481.             // lock the segment down temp
  17482.  
  17483.             if(LockSeg(
  17484.             SELECTOROF(rp->s.IOCtl.buffer), // selector
  17485.             0,                              // lock < 2 sec
  17486.             0,                              // wait for seg lock
  17487.             (PLHANDLE) &lock_seg_han))      // handle returned
  17488.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17489.  
  17490.             // move slot data to driver buffer
  17491.  
  17492.             if(MoveBytes(
  17493.             (FARPOINTER) appl_buffer,       // source
  17494.             &pos_struct,                    // for pos data
  17495.             6))                             // 6 bytes
  17496.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17497.  
  17498.             pos_struct.data = get_pos_data(pos_struct.slot,pos_struct.reg);
  17499.  
  17500.             // move POS reg data to users buffer
  17501.  
  17502.             if(MoveBytes(
  17503.             &pos_struct,                    // for pos data
  17504.             (FARPOINTER) appl_buffer,       // source
  17505.             6))                             // 6 bytes
  17506.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17507.  
  17508.             // unlock segment
  17509.  
  17510.             if(UnLockSeg(lock_seg_han))
  17511.  
  17512.                 return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  17513.  
  17514.             return (RPDONE);
  17515.  
  17516.         // this IOCtl is essentially the same as 0x02, except the
  17517.         // user virtual address is mapped to a linear address in the
  17518.         // process address range and then sent to the application. This
  17519.         // saves the SelToFlat and FlatToSel each time the pointer is
  17520.         // referenced.
  17521.  
  17522.         case 0x04:                  // 32-bit memory-mapped addr to app
  17523.  
  17524.             // verify caller owns this buffer area
  17525.  
  17526.             if(VerifyAccess(
  17527.             SELECTOROF(rp->s.IOCtl.buffer), // selector
  17528.             OFFSETOF(rp->s.IOCtl.buffer),   // offset
  17529.             8,                              // 8 bytes
  17530.             1) )                            // read write
  17531.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17532.  
  17533.             // lock the segment down temp
  17534.  
  17535.             if(LockSeg(
  17536.             SELECTOROF(rp->s.IOCtl.buffer), // selector
  17537.             0,                              // lock < 2 sec
  17538.             0,                              // wait for seg lock
  17539.             (PLHANDLE) &lock_seg_han))      // handle returned
  17540.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17541.  
  17542.            // map the board address to an LDT entry
  17543.            // we could have used VMAlloc
  17544.  
  17545.            if ( PhysToUVirt(board_address,0x8000,1,
  17546.               (FARPOINTER) &addr_struct.mapped_addr))
  17547.                return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17548.  
  17549.            // now convert it to a linear address
  17550.  
  17551.            if (VirtToLin((FARPOINTER)addr_struct.mapped_addr,
  17552.                         (PLINADDR)&addr_struct.mapped_addr))
  17553.                  return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17554.  
  17555.            // move data to users buffer
  17556.  
  17557.            if(MoveBytes(
  17558.            &addr_struct,                   // source
  17559.            rp->s.IOCtl.buffer,             // dest
  17560.            8))                             // 8 bytes
  17561.                return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  17562.  
  17563.            // unlock segment
  17564.  
  17565.            if(UnLockSeg(lock_seg_han))
  17566.                return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  17567.  
  17568.            return (RPDONE);
  17569.  
  17570.         } // switch (rp->s.IOCtl.function
  17571.  
  17572.     case RPDEINSTALL:               // 0x14
  17573.  
  17574.         return(RPDONE | RPERR | ERROR_BAD_COMMAND);
  17575.  
  17576.         // all other commands are ignored
  17577.  
  17578.     default:
  17579.         return(RPDONE);
  17580.  
  17581.     }
  17582. }
  17583.  
  17584. int  hex2bin(char c)
  17585. {
  17586.  if(c < 0x3a)
  17587.    return (c - 48);
  17588.  else
  17589.    return (( c & 0xdf) - 55);
  17590. }
  17591.  
  17592. // read all the POS register data into a structure
  17593.  
  17594. USHORT get_POS(USHORT slot_num,USHORT far *card_ID,UCHAR far *pos_regs)
  17595. {
  17596. USHORT rc, i, lid;
  17597.  
  17598.     if (GetLIDEntry(0x10, 0, 1, &lid)) // get LID for POS
  17599.         return (1);
  17600.  
  17601.     // Get the size of the LID request block
  17602.  
  17603.     ABIOS_l_blk.f_parms.req_blk_len = sizeof(struct lid_block_def);
  17604.     ABIOS_l_blk.f_parms.LID = lid;
  17605.     ABIOS_l_blk.f_parms.unit = 0;;
  17606.     ABIOS_l_blk.f_parms.function = GET_LID_BLOCK_SIZE;
  17607.     ABIOS_l_blk.f_parms.ret_code = 0x5a5a;
  17608.     ABIOS_l_blk.f_parms.time_out = 0;
  17609.  
  17610.     if (ABIOSCall(lid,0,(void far *)&ABIOS_l_blk))
  17611.         return (1);
  17612.  
  17613.     lid_blk_size = ABIOS_l_blk.s_parms.blk_size; // Get the block size
  17614.  
  17615.     // Fill POS regs and card ID with FF in case this does not work
  17616.  
  17617.     *card_ID = 0xFFFF;
  17618.     for (i=0; i<NUM_POS_BYTES; i++) { pos_regs[i] = 0x00; };
  17619.  
  17620.     // Get the POS registers and card ID for the commanded slot
  17621.  
  17622.     ABIOS_r_blk.f_parms.req_blk_len = lid_blk_size;
  17623.     ABIOS_r_blk.f_parms.LID = lid;
  17624.     ABIOS_r_blk.f_parms.unit = 0;;
  17625.     ABIOS_r_blk.f_parms.function = READ_POS_REGS_CARD;
  17626.     ABIOS_r_blk.f_parms.ret_code = 0x5a5a;
  17627.     ABIOS_r_blk.f_parms.time_out = 0;
  17628.  
  17629.     ABIOS_r_blk.s_parms.slot_num = (UCHAR)slot_num & 0x0F;
  17630.     ABIOS_r_blk.s_parms.pos_buf = (void far *)pos_regs;
  17631.     ABIOS_r_blk.s_parms.card_ID = 0xFFFF;
  17632.  
  17633.     if (ABIOSCall(lid,0,(void far *)&ABIOS_r_blk))
  17634.        rc = 1;
  17635.      else {                                       // Else
  17636.        *card_ID = ABIOS_r_blk.s_parms.card_ID;   //    Set the card ID value
  17637.        rc = 0;
  17638.       }
  17639.     FreeLIDEntry(lid);
  17640.     return(rc);
  17641.  
  17642. }
  17643.  
  17644. UCHAR get_pos_data (int slot, int reg)
  17645. {
  17646.    UCHAR pos;
  17647.    CARD *cptr;
  17648.  
  17649.    cptr = &card[slot-1];            // set pointer to beg of card array
  17650.    if (reg == 0)                    // card ID
  17651.       pos = LOUSHORT(cptr->card_ID);
  17652.    else
  17653.      if ( reg == 1)
  17654.       pos = HIUSHORT(cptr->card_ID);
  17655.    else
  17656.       pos = cptr->pos_regs[reg-2];  // POS data register
  17657.    return (pos);
  17658. }
  17659.  
  17660. // Device Initialization Routine
  17661.  
  17662. int Init(PREQPACKET rp)
  17663. {
  17664.   USHORT lid;
  17665.  
  17666.   register char far *p;
  17667.  
  17668.   // store DevHlp entry point
  17669.  
  17670.   DevHlp = rp->s.Init.DevHlp;  // save DevHlp entry point
  17671.  
  17672.   if (!(GetLIDEntry(0x10, 0, 1, &lid))) // get LID for POS regs
  17673.   {
  17674.     FreeLIDEntry(lid);
  17675.  
  17676.     // Micro Channel (tm) setup section
  17677.  
  17678.     bus = 1;                      // MCA bus
  17679.  
  17680.     // Get the POS data and card ID for each of 8 possible slots
  17681.  
  17682.     for (i=0;i <= MAX_NUM_SLOTS; i++)
  17683.        get_POS(i+1,(FARPOINTER)&card[i].card_ID,(FARPOINTER)card[i].pos_regs);
  17684.  
  17685.     matches = 0;
  17686.     for (i=0, pcard = card; i <= MAX_NUM_SLOTS; i++, pcard++)
  17687.     {
  17688.        if (pcard->card_ID == TARGET_ID)
  17689.        {
  17690.          matches = 1;
  17691.          break;
  17692.        }
  17693.     }
  17694.  
  17695.     if (matches == 0)            // at least one board found
  17696.     {
  17697.       DosPutMessage(1, 8, devhdr.DHname);
  17698.       DosPutMessage(1,strlen(NoMatchMsg),NoMatchMsg);
  17699.       rp->s.InitExit.finalCS = (OFF) 0;
  17700.       rp->s.InitExit.finalDS = (OFF) 0;
  17701.       return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  17702.     }
  17703.  
  17704.     // calculate the board address from the POS regs
  17705.  
  17706.     board_address = ((unsigned long) get_pos_data(i+1, 4) << 16) |
  17707.       ((unsigned long)(get_pos_data(i+1, 3) & 1) << 15);
  17708.   }
  17709.  
  17710.   else
  17711.  
  17712.   {
  17713.  
  17714.     // ISA bus setup
  17715.  
  17716.     bus = 0;                      // ISA bus
  17717.  
  17718.     // get parameters, IRQ (not used yet), port addr and base mem addr
  17719.  
  17720.     for (p = rp->s.Init.args; *p && *p != ' ';++p);// skip driver name
  17721.     for (; *p == ' '; ++p);       // skip blanks following driver name
  17722.     if (*p)
  17723.     {
  17724.       board_address=0;           // i/o port address
  17725.       for (; *p != '\0'; ++p)    // get board address
  17726.       board_address = (board_address << 4) + (hex2bin(*p));
  17727.       addr_struct.board_addr = board_address;
  17728.     }
  17729.   }
  17730.  
  17731.   if (bus)
  17732.      DosPutMessage(1,strlen(MainMsgMCA),MainMsgMCA);
  17733.   else
  17734.      DosPutMessage(1,strlen(MainMsgISA),MainMsgISA);
  17735.  
  17736.   // send back our cs and ds end values to os/2
  17737.  
  17738.   if (SegLimit(HIUSHORT((void far *) Init), &rp->s.InitExit.finalCS) ||
  17739.     SegLimit(HIUSHORT((void far *) MainMsgISA), &rp->s.InitExit.finalDS))
  17740.       Abort();
  17741.  
  17742.   Beep(300,500);
  17743.   return (RPDONE);
  17744.  
  17745. }
  17746.  
  17747.  
  17748. ΓòÉΓòÉΓòÉ 23.35. Memory-Mapped Device Driver DEF File ΓòÉΓòÉΓòÉ
  17749.  
  17750. LIBRARY PAC
  17751. PROTMODE
  17752.  
  17753.  
  17754. ΓòÉΓòÉΓòÉ 23.36. Memory-Mapped Device Driver Make File ΓòÉΓòÉΓòÉ
  17755.  
  17756. #  makefile for memory mapped driver
  17757.  
  17758. mmap.sys: ddstart.obj mmap.obj
  17759.  link /nod /noi /map ddstart+mmap,mmap.sys,mmap,c:\c6\lib\os2+\
  17760. c:\lib\slibcep+c:\drvlib\drvlib\drvlib,mmap.def
  17761.         mapsym mmap
  17762.  
  17763. ddstart.obj: ddstart.asm
  17764.  masm -Mx -t -L -N ddstart;
  17765.  
  17766. mmap.obj: mmap.c drvlib.h mmap.h
  17767.  cl -Fa -c -Asnw -Gs -G2 -Zl -Zp -Ox mmap.c
  17768.  
  17769.  
  17770. ΓòÉΓòÉΓòÉ 23.37. Memory-Mapped Device Driver Header File ΓòÉΓòÉΓòÉ
  17771.  
  17772. /*
  17773.   include file for memory-mapped driver
  17774. */
  17775.  
  17776. #define  OUR_CAT  0x91               /* category for DosDevIOCtl */
  17777. #define  MEMSIZE  32800              /* 32 K bytes per adapter   */
  17778. #define  POS_BASE 0x100              /* MCA adapter base         */
  17779. #define  TARGET_ID 0x6CFD            /* adapter ID               */
  17780. #define  NUM_POS_BYTES 64
  17781. #define  MAX_NUM_SLOTS 8
  17782. #define  MAX_DEV_NUMS 8
  17783. #define  MAX_NUM_DSPS 5
  17784. #define  READY  0xFFFF               /* dsp read                 */
  17785. #define  POS_PORT 0x96
  17786. #define  POS_BASE 0x100
  17787.  
  17788. /* Constants used by ABIOS calls */
  17789.  
  17790. #define GET_LID_BLOCK_SIZE 0x01
  17791. #define POS_LID            0x10
  17792. #define READ_POS_REGS      0x0B
  17793. #define READ_POS_REGS_RAM  0x0B
  17794. #define READ_POS_REGS_CARD 0x0D
  17795.  
  17796. typedef struct _POS_STRUCT
  17797. {
  17798.    USHORT slot;
  17799.    USHORT   reg;
  17800.    USHORT   data;
  17801.  } POS_STRUCT;
  17802. typedef POS_STRUCT far *PPOS_STRUCT;
  17803.  
  17804. typedef struct _ADDR_STRUCT
  17805. {
  17806.    void     far *mapped_addr;
  17807.    ULONG    board_addr;
  17808.  } ADDR_STRUCT;
  17809. typedef ADDR_STRUCT far *PADDR_STRUCT;
  17810.  
  17811. typedef struct function_parms_def
  17812. {
  17813.    USHORT    req_blk_len;
  17814.    USHORT    LID;
  17815.    USHORT    unit;
  17816.    USHORT    function;
  17817.    USHORT    resvd1;
  17818.    USHORT    resvd2;
  17819.    USHORT    ret_code;
  17820.    USHORT    time_out;
  17821. } function_parms_type;
  17822.  
  17823. typedef struct service_parms_def
  17824. {
  17825.    UCHAR     slot_num;        /* 10h */
  17826.    UCHAR     resvd3;          /* 11h */
  17827.    USHORT    card_ID;         /* 12h */
  17828.    USHORT    resvd4;          /* 14h */
  17829.    UCHAR     far *pos_buf;    /* 16h */
  17830.    USHORT    resvd5;          /* 1Ah */
  17831.    USHORT    resvd6;          /* 1Ch */
  17832.    UCHAR     resvd7[40];      /* 1Eh */
  17833. } service_parms_type;
  17834.  
  17835. typedef struct lid_service_parms_def
  17836. {
  17837.    UCHAR     irpt_level;      /* 10h */
  17838.    UCHAR     arb_level;       /* 11h */
  17839.    USHORT    device_id;       /* 12h */
  17840.    USHORT    unit_count;      /* 14h */
  17841.    USHORT    flags;           /* 16h */
  17842.    USHORT    blk_size;        /* 18h */
  17843.    USHORT    secnd_id;        /* 1Ah */
  17844.    USHORT    resvd6;          /* 1Ch */
  17845.    USHORT    resvd7;          /* 1Eh */
  17846. } lid_service_parms_type;
  17847.  
  17848. typedef struct req_block_def
  17849. {
  17850.    function_parms_type f_parms;
  17851.    service_parms_type  s_parms;
  17852. } REQBLK;
  17853.  
  17854. typedef struct lid_block_def
  17855. {
  17856.    function_parms_type     f_parms;
  17857.    lid_service_parms_type  s_parms;
  17858. } LIDBLK;
  17859.  
  17860. typedef struct card_def
  17861. {
  17862.   USHORT     card_ID;        /* ID of the card in this slot */
  17863.   UCHAR      pos_regs[NUM_POS_BYTES];
  17864. } CARD;
  17865.  
  17866.  
  17867. ΓòÉΓòÉΓòÉ 23.38. Memory-Mapped Device Driver Test Program - 16-Bit ΓòÉΓòÉΓòÉ
  17868.  
  17869. #define      INCL_DOSFILEMGR
  17870. #define      INCL_DOS
  17871. #define      INCL_DOSDEVICES
  17872. #define      INCL_DOSDEVIOCTL
  17873. #include     <os2.h>
  17874. #include     <stdio.h>
  17875. #include     "test.h"
  17876. HFILE        driver_handle=0;
  17877. USHORT       err;
  17878. UCHAR        far *myptr=0;
  17879. USHORT       ActionTaken;
  17880. USHORT       rc;
  17881. ULONG        FileSize=0;
  17882. USHORT       FileAttribute;
  17883. ULONG        Reserved=0L;
  17884. UCHAR        Data1[8]={0};
  17885. UCHAR        Data2=0;
  17886. PADDR_STRUCT paddr_ptr;
  17887.  
  17888. void main()
  17889. {
  17890.  
  17891.   // open the driver
  17892.  
  17893.   if ((rc = DosOpen("MMAP$   ",
  17894.       &driver_handle,
  17895.       &ActionTaken,
  17896.       FileSize,
  17897.       FileAttribute,
  17898.       FILE_OPEN,
  17899.       OPEN_SHARE_DENYNONE | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_ACCESS_READWRITE,
  17900.       Reserved)) !=0)
  17901.       {
  17902.         printf("\nDosOpen failed, error = %d",rc);
  17903.   DosExit(EXIT_PROCESS,0);
  17904.       }
  17905.  
  17906.   printf ("Bus Type              = ");
  17907.  
  17908.   rc = DosDevIOCtl(&Data1,&Data2,0x01,OUR_CAT,driver_handle);
  17909.  
  17910.   if (rc & 0x01)
  17911.     printf ("Micro Channel (tm)\n");
  17912.   else
  17913.     printf ("ISA\n");
  17914.  
  17915.   if (rc = DosDevIOCtl(&Data1,&Data2,0x02,OUR_CAT,driver_handle))
  17916.   {
  17917.      printf ("DevIOCtl failed, error code = %d\n",rc);
  17918.    DosExit(EXIT_PROCESS,0);
  17919.   }
  17920.  
  17921.   // pointer to data buffer
  17922.  
  17923.   paddr_ptr = (PADDR_STRUCT) Data1;
  17924.  
  17925.   printf ("Memory Mapped Address = %p\nPhysical Address      = %lx\n",
  17926.   paddr_ptr->mapped_addr,paddr_ptr->board_addr);
  17927.  
  17928.   myptr = (void far *) paddr_ptr->mapped_addr;
  17929.  
  17930.   printf ("First Byte Of Adapter = %x\n",*myptr);
  17931.  
  17932.   // close driver
  17933.  
  17934.   DosClose(driver_handle);
  17935. }
  17936.  
  17937.  
  17938. ΓòÉΓòÉΓòÉ 23.39. Memory-Mapped Test Program Header File - 16-Bit ΓòÉΓòÉΓòÉ
  17939.  
  17940. //  include file for test.c
  17941.  
  17942. #define  OUR_CAT  0x91               // category for DosDevIOCtl
  17943. #define  DRIVER_BASE 0xD8000         // board address
  17944. #define  BASE_LENGTH 0x1000          // length of memory map
  17945.  
  17946. typedef struct _ADDR_STRUCT
  17947. {
  17948.   void     far *mapped_addr;
  17949.   ULONG    board_addr;
  17950. } ADDR_STRUCT;
  17951. typedef ADDR_STRUCT far *PADDR_STRUCT;
  17952.  
  17953.  
  17954. ΓòÉΓòÉΓòÉ 23.40. Memory-Mapped Test Program Def File - 16-Bit ΓòÉΓòÉΓòÉ
  17955.  
  17956. protmode
  17957.  
  17958.  
  17959. ΓòÉΓòÉΓòÉ 23.41. Memory-Mapped Test Program Make File - 16-Bit ΓòÉΓòÉΓòÉ
  17960.  
  17961. test.exe: test.obj
  17962.      link test,test,test,+c:\c6\lib\os2+c:\c6\lib\llibcep,,test.def
  17963.  
  17964. test.obj: test.c
  17965.      cl -AL -G2 -c test.c
  17966.  
  17967.  
  17968. ΓòÉΓòÉΓòÉ 23.42. Memory-Mapped Test Program - 32-Bit, 16-Bit Pointers ΓòÉΓòÉΓòÉ
  17969.  
  17970. #define INCL_DOS
  17971. #include <os2.h>
  17972.  
  17973. #define  EABUF       0L
  17974. #define  OUR_CAT  0x91L
  17975. #define  BUS_TYPE 0x01L
  17976. #define  GET_PTR  0x02L
  17977. #define  GET_POS  0x03L
  17978.  
  17979. typedef struct _ADDR_STRUCT
  17980. {
  17981.   void     * _Seg16 mapped_addr; /* 16:16 pointer to adapter     */
  17982.   ULONG    board_addr;
  17983. } ADDR_STRUCT;
  17984.  
  17985. typedef ADDR_STRUCT *PADDR_STRUCT;
  17986.  
  17987. char     buf[100] = {0};
  17988. USHORT   BytesRead;
  17989. ULONG    ActionTaken;            /* for file opens                */
  17990. APIRET   rc;                     /* return code for driver open   */
  17991. ULONG    FileSize=0;             /* NULL file size                */
  17992. ULONG    FileAttribute;          /* attribute bits                */
  17993. HFILE    handle=0;
  17994. UCHAR    parmbuf [20];
  17995. UCHAR    databuf[20];
  17996. ULONG    plength,dlength;
  17997. PADDR_STRUCT paddr_ptr;
  17998. UCHAR    * _Seg16 myptr;
  17999.  
  18000. main()
  18001. {
  18002.     rc = DosOpen("MMAP$   ",
  18003.     &handle,
  18004.     &ActionTaken,
  18005.     FileSize,
  18006.     FileAttribute,
  18007.     OPEN_ACTION_OPEN_IF_EXISTS,
  18008.     OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT,
  18009.     EABUF);
  18010.       if (rc)
  18011.       {
  18012.         printf("\nDosOpen failed, error = %ld",rc);
  18013.         DosExit(EXIT_PROCESS,0);    /* exit gracefully            */
  18014.       }
  18015.  
  18016.     printf ("Bus Type              = ");
  18017.  
  18018.     rc = DosDevIOCtl(handle,OUR_CAT,BUS_TYPE,0,0L,&plength,databuf,8L,&dlength);
  18019.  
  18020.     if (rc & 0x01)
  18021.         printf ("Micro Channel (tm)\n");
  18022.     else
  18023.         printf ("ISA\n");
  18024.  
  18025.     rc = DosDevIOCtl(handle,OUR_CAT,GET_PTR,0,0L,&plength,databuf,8L,&dlength);
  18026.  
  18027.     if (rc)
  18028.     {
  18029.       printf ("DevIOCtl failed, error code = %ld\n",rc);
  18030.       DosExit(EXIT_PROCESS,0);
  18031.     }
  18032.  
  18033.     paddr_ptr = (PADDR_STRUCT) databuf;
  18034.  
  18035.     printf ("Memory Mapped Address = %p\nPhysical Address      = %lx\n",
  18036.       paddr_ptr->mapped_addr,paddr_ptr->board_addr);
  18037.  
  18038.     myptr = paddr_ptr->mapped_addr;
  18039.  
  18040.     printf ("First Byte Of Adapter = %x\n",*myptr);
  18041.  
  18042.     DosClose(handle);
  18043. }
  18044.  
  18045.  
  18046. ΓòÉΓòÉΓòÉ 23.43. Memory-Mapped Test Program DEF File - 32-Bit ΓòÉΓòÉΓòÉ
  18047.  
  18048. name test32
  18049. protmode
  18050.  
  18051.  
  18052. ΓòÉΓòÉΓòÉ 23.44. Memory-Mapped Test Program Make File - 32-Bit ΓòÉΓòÉΓòÉ
  18053.  
  18054. test32.exe: test32.obj
  18055.      link386 /MAP /NOI /PM:vio test32,test32,test32,,,test32.def
  18056.  
  18057. test32.obj: test32.c
  18058.      icc /c /Gt+ test32.c
  18059.  
  18060.  
  18061. ΓòÉΓòÉΓòÉ 23.45. Memory-Mapped Test Program - 32-Bit, 32-Bit Pointers ΓòÉΓòÉΓòÉ
  18062.  
  18063. #define INCL_DOS
  18064. #include <os2.h>
  18065.  
  18066. #define  EABUF       0L
  18067. #define  OUR_CAT  0x91L
  18068. #define  BUS_TYPE 0x01L
  18069. #define  GET_PTR  0x02L
  18070. #define  GET_POS  0x03L
  18071. #define  GET_LIN  0x04L
  18072.  
  18073. typedef struct _ADDR_STRUCT
  18074. {
  18075.   void     *mapped_addr; /* pointer to adapter memory */
  18076.   ULONG    board_addr;
  18077. } ADDR_STRUCT;
  18078. typedef ADDR_STRUCT *PADDR_STRUCT;
  18079.  
  18080.  
  18081. char     buf[100] = {0};
  18082. USHORT   BytesRead;
  18083. ULONG    ActionTaken;          /* for file opens               */
  18084. APIRET   rc;                   /* return code for driver open  */
  18085. ULONG    FileSize=0;           /* NULL file size               */
  18086. ULONG    FileAttribute;        /* attribute bits               */
  18087. HFILE    handle=0;
  18088. UCHAR    parmbuf [20];
  18089. UCHAR    databuf[20];
  18090. ULONG    plength,dlength;
  18091. PADDR_STRUCT paddr_ptr;
  18092. UCHAR    *myptr;
  18093.  
  18094. main()
  18095. {
  18096.     rc = DosOpen("MMAP$   ",
  18097.     &handle,
  18098.     &ActionTaken,
  18099.     FileSize,
  18100.     FileAttribute,
  18101.     OPEN_ACTION_OPEN_IF_EXISTS,
  18102.     OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT,
  18103.     EABUF);
  18104.       if (rc)
  18105.       {
  18106.         printf("\nDosOpen failed, error = %ld",rc);
  18107.         DosExit(EXIT_PROCESS,0);    /* exit gracefully                     */
  18108.       }
  18109.  
  18110.     printf ("Bus Type              = ");
  18111.  
  18112.     rc = DosDevIOCtl(handle,OUR_CAT,BUS_TYPE,0,0L,&plength,databuf,8L,&dlength);
  18113.  
  18114.     if (rc & 0x01)
  18115.   printf ("Micro Channel (tm)\n");
  18116.     else
  18117.         printf ("ISA\n");
  18118.  
  18119.     rc = DosDevIOCtl(handle,OUR_CAT,GET_LIN,0,0L,&plength,databuf,8L,&dlength);
  18120.  
  18121.     if (rc)
  18122.     {
  18123.       printf ("DevIOCtl failed, error code = %ld\n",rc);
  18124.       DosExit(EXIT_PROCESS,0);
  18125.     }
  18126.  
  18127.     paddr_ptr = (PADDR_STRUCT) databuf;
  18128.  
  18129.     printf ("Memory Mapped Address = %p\nPhysical Address      = %lx\n",
  18130.     paddr_ptr->mapped_addr,paddr_ptr->board_addr);
  18131.  
  18132.     myptr = paddr_ptr->mapped_addr;
  18133.  
  18134.     printf ("First Byte Of Adapter = %x\n",*myptr);
  18135.  
  18136.     DosClose(handle);
  18137.  
  18138. }
  18139.  
  18140.  
  18141. ΓòÉΓòÉΓòÉ 23.46. Memory-Mapped Test Program DEF File - 32-Bit ΓòÉΓòÉΓòÉ
  18142.  
  18143. protmode
  18144.  
  18145.  
  18146. ΓòÉΓòÉΓòÉ 23.47. Memory-Mapped Test Program Make File - 32-Bit ΓòÉΓòÉΓòÉ
  18147.  
  18148. test32a.exe: test32a.obj
  18149.      link386 /MAP /NOI /PM:vio test32a,test32a,test32a,,,test32a.def
  18150.  
  18151. test32a.obj: test32a.c
  18152.      icc /c /Gt+ test32a.c
  18153.  
  18154.  
  18155. ΓòÉΓòÉΓòÉ 23.48. Macros ΓòÉΓòÉΓòÉ
  18156.  
  18157. SelToFlat MACRO
  18158. ;;
  18159. ;; where AX = selector
  18160. ;;       BX = offset
  18161. ;;
  18162. ;; exit with EAX = linear address
  18163. ;;
  18164.     shl eax,0dh
  18165.     and eax,01fff0000h
  18166.     mov ax,bx
  18167. ;;
  18168. ENDM
  18169.  
  18170. FlatToSel MACRO
  18171. ;;
  18172. ;; where EAX = linear address
  18173. ;;
  18174. ;; exit with AX = selector, BX = offset
  18175. ;;
  18176.     mov bx,ax
  18177.     shr eax,0dh
  18178.     or  ax,0x7h
  18179. ;;
  18180. ENDM
  18181.  
  18182.  
  18183. ΓòÉΓòÉΓòÉ 24. Appendix D - OEMHLP and TESTCFG ΓòÉΓòÉΓòÉ
  18184.  
  18185. OEMHLP 
  18186.  
  18187. The OEMHLP interface was originally designed to assist Original Equipment 
  18188. Manufacturers (OEM's) in adapting the OS/2 operating system to their hardware. 
  18189. Prior to OS/2 2.0, OS/2 1.x was built specifically for a particular OEM 
  18190. machine.  If an OEM wanted the OS/2 operating system to run on their machine, 
  18191. they would have to build a modified version of the OS/2 operating system to 
  18192. sell under their logo.  Having a pre-existing interface helped speed the 
  18193. adaptation of OS/2 to their hardware. However, IBM realized that in order to 
  18194. sell OS/2 2.0 to the largest possible number of users, that OS/2 2.0 had to 
  18195. work on the majority of OEM hardware without any modifications.  OS/2 2.0 was 
  18196. designed to meet this goal, and IBM currently tests the OS/2 operating system 
  18197. on a wide variety of OEM hardware and configurations to ensure continued 
  18198. compatibility. 
  18199.  
  18200. The OEMHLP interface began as a simple interface for obtaining information in 
  18201. real mode and passing it on to protect-mode applications and PDDs, and evolved 
  18202. into a dedicated PDD.  Protect-mode applications and PDDs cannot access BIOS 
  18203. through the INT interface, yet they sometimes need information from the BIOS. 
  18204. The OEMHLP interface was extended to allow access to necessary BIOS 
  18205. information.  The OEMHLP device support supports several IOCtls for aiding 
  18206. device driver writers. These IOCtls can be found in Table D-1. 
  18207.  
  18208. Using the OEMHLP device driver, a device driver can use INT 15h calls from the 
  18209. initialization code to determine if a particular EISA adapter is present and to 
  18210. set up that particular adapter.  The following example code in Figure D-1 
  18211. illustrates how you would use the OEMHLP device driver to determine if a 
  18212. particular EISA adapter is present. 
  18213.  
  18214. USHORT FindMyEISACard(void)
  18215. {
  18216.   HFILE filehandle;
  18217.   USHORT action;
  18218.   EISAFunctionInfo.efi_SubFunc = OEM_GET_SLOT_INFO; /* Get Slot  */
  18219.   EISAFunctionInfo.efi_Slot    = 0;                 /* Slot 0    */
  18220.   if (rc = DosOpen("OEMHLP$",
  18221.                    &filehandle,
  18222.                    &action,
  18223.                    0L,
  18224.                    0,
  18225.                    1,
  18226.                    0x40,
  18227.                    0L))
  18228.       return 1;
  18229.  
  18230.   for(index=1;index<CFG_MAX_EISA_SLOTS;index++)   // For each slot
  18231.   {
  18232.     EISAFunctionInfo.efi_Slot    = (UCHAR) index; // Slot Number
  18233.     EISASlotInfo.esi_CardID  = 0;                 // Reset Card ID
  18234.     if (rc = DosDevIOCtl((PVOID)&EISASlotInfo,    // Data Packet
  18235.                          (PVOID)&EISAFunctionInfo,// Parm Packet
  18236.                          (USHORT)OEMHLP_QUERYEISACONFIG,
  18237.                          (USHORT)OEMHLP_CATEGORY,
  18238.                          (HFILE)filehandle))
  18239.         return 1;
  18240.     /*
  18241.        If IOCtl successful and slot has adapter, then store away
  18242.        the adapter ID, otherwise mark as empty with a zero.
  18243.     */
  18244.     if(EISASlotInfo.esi_Error==0)
  18245.     {
  18246.       if (EISASlotInfo.esi_CardID == MYCARDID)
  18247.       DosClose(filehandle);
  18248.       return 0;
  18249.     }
  18250.   }
  18251.   DosClose(filehandle);
  18252.   return(NOTFOUND);
  18253. }
  18254. Example D-1. Locating An EISA Bus Adapter Using OEMHLP 
  18255.  
  18256. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  18257. ΓöéFunctionΓöéDescription                             Γöé
  18258. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18259. Γöé00h     ΓöéQuery OEM Adaptation Information        Γöé
  18260. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18261. Γöé01h     ΓöéQuery Machine Information               Γöé
  18262. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18263. Γöé02h     ΓöéQuery Display Combination Code          Γöé
  18264. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18265. Γöé03h     ΓöéReturn Video Fonts                      Γöé
  18266. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18267. Γöé04h     ΓöéQuery EISA Configuration Information    Γöé
  18268. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18269. Γöé05h     ΓöéQuery ROM BIOS Information              Γöé
  18270. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18271. Γöé06h     ΓöéQuery Miscellaneous Video Information   Γöé
  18272. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18273. Γöé07h     ΓöéQuery Video Adapter                     Γöé
  18274. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18275. Γöé08h     ΓöéQuery SVGA Information                  Γöé
  18276. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18277. Γöé0Ah     ΓöéQuery Memory Information                Γöé
  18278. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18279. Γöé0Bh     ΓöéQuery DQMS Information                  Γöé
  18280. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  18281. Table D-1. OEMHLP Supported IOCtl Calls 
  18282.  
  18283. FUNCTION 00h - Query OEM Adaptation Information 
  18284.  
  18285. This function returns information about a specific OEM adaptation of the OS/2 
  18286. operating system. 
  18287.  
  18288. Data Packet Format 
  18289.  
  18290. typedef struct _DataPacket
  18291. {
  18292.   UCHAR OEMName[20!;
  18293.   UCHAR OS2Revision[10!;
  18294. }  DataPacket;
  18295.  
  18296. OEMName        - If this is a non-IBM-logo'ed version of the OS/2 operating 
  18297.                system and additional OEMHLP functions have been added, the OEM 
  18298.                Name field contains the ASCIIZ name of the OEM. 
  18299.  
  18300. OS2Revision    - The OS/2 version number, stored as an ASCIIZ string. 
  18301.  
  18302. Comments 
  18303.  
  18304. OEM's may add nonstandard OEMHLP IOCtls to the OS/2 operating system if they 
  18305. sell the OS/2 operating system under their logo.  Programs that use these 
  18306. IOCtls will only work with that OEM's adaptation of the OS/2 operating system 
  18307. and, as such, should issue the Query OEM Adaptation Information IOCtl routine 
  18308. and verify the OEM Name. 
  18309.  
  18310. FUNCTION 01h - Query OEM Machine Information 
  18311.  
  18312. Data Packet Format 
  18313.  
  18314. typedef struct _DataPacket
  18315. {
  18316.   UCHAR Manufacturer[20!;
  18317.   UCHAR ModelNumber[10!;
  18318.   UCHAR RomRevisionNumber[10!;
  18319. } DataPacket;
  18320.  
  18321. Manufacturer          - ASCIIZ name of manufacturer 
  18322.  
  18323. ModelNumber           - ASCIIZ machine model number from ROM (if available) 
  18324.  
  18325. RomRevisionNumber     - ASCIIZ ROM revision number 
  18326.  
  18327. Comments 
  18328.  
  18329. This function will attempt to find the name of the manufacturer, the machine 
  18330. model number, and the ROM revision number.  If the machine cannot be 
  18331. identified, the fields returned in the Data Packet are set to NULLs. 
  18332.  
  18333. FUNCTION 02h - Query Display Combination Code 
  18334.  
  18335. Data Packet Format 
  18336.  
  18337. typedef struct _DataPacket
  18338. {
  18339.   BYTE DisplayCode;
  18340. } DataPacket;
  18341.  
  18342. This function returns the display combination code. 
  18343.  
  18344. DisplayCode  - binary display combination code returned from INT 10h (AH = 1Ah) 
  18345.  
  18346. Comments 
  18347.  
  18348. This function returns the display combination code, as returned from INT 10h 
  18349. (AH=1Ah).  If this INT 10h function is not supported by the BIOS, then 0 will 
  18350. be returned. 
  18351.  
  18352. Pointers returned by this IOCtl are real-mode addresses and must be converted 
  18353. to protect-mode addresses before being used by protect-mode applications and 
  18354. device drivers. 
  18355.  
  18356. See the IBM Personal System/2 and Personal Computer BIOS Interface Technical 
  18357. Reference or the technical reference manual for your personal computer for more 
  18358. information on the display combination codes returned from INT 10h (AH=1Ah). 
  18359.  
  18360. FUNCTION 03h - Return Pointers To Video Fonts 
  18361.  
  18362. Data Packet Format 
  18363.  
  18364. typedef struct _DataPacket
  18365. {
  18366.   FARPOINTER P8X14;
  18367.   FARPOINTER P8X8;
  18368.   FARPOINTER PT8X8;
  18369.   FARPOINTER P9X14;
  18370.   FARPOINTER P8X16;
  18371.   FARPOINTER P9X16;
  18372. } DataPacket;
  18373.  
  18374. This function returns an array of 16:16 pointers to the ROM video fonts, as 
  18375. returned by the INT 10h, AX=1130h. 
  18376.  
  18377. P8X14     - 16:16 pointer to 8 x 14 ROM font 
  18378.  
  18379. P8X8      - 16:16 pointer to 8 x 8 ROM font 
  18380.  
  18381. PT8X8     - 16:16 pointer to 8 x 8 ROM font (top) 
  18382.  
  18383. P9X14     - 16:16 pointer to 9 x 14 ROM font 
  18384.  
  18385. P8X16     - 16:16 pointer to 8 x 16 ROM font 
  18386.  
  18387. P9X16     - 16:16 pointer to 9 x 16 ROM font 
  18388.  
  18389. Comments 
  18390.  
  18391. See the IBM Personal System/2 and Personal Computer BIOS Interface Technical 
  18392. Reference or the technical reference manual for your personal computer for more 
  18393. information on the video font pointers returned from INT 10h (AX=1130h). 
  18394.  
  18395. FUNCTION 04h - Query EISA Configuration Information 
  18396.  
  18397. Data Packet Format (subfunction 0) 
  18398.  
  18399. typedef struct _DataPacket
  18400. {
  18401.   BYTE ReturnByte;
  18402.   BYTE Flags;
  18403.   BYTE MajorRevision;
  18404.   BYTE MinorRevision;
  18405.   USHORT Checksum;
  18406.   BYTE DeviceFunc;
  18407.   BYTE FuncInfo;
  18408.   ULONG CardID;
  18409. } DataPacket;
  18410.  
  18411. ReturnByte      - return code from BIOS 
  18412.  
  18413. Flags           - binary value returned from BIOS 
  18414.  
  18415. MajorRevision   - binary value returned from BIOS 
  18416.  
  18417. MinorRevision   - binary value returned from BIOS 
  18418.  
  18419. Checksum        - binary value returned from BIOS 
  18420.  
  18421. DevFunc         - binary value returned from BIOS 
  18422.  
  18423. FuncInfo        - binary value returned from BIOS 
  18424.  
  18425. CardID          - binary EISA card ID returned from BIOS 
  18426.  
  18427. Data Packet Format (subfunction 1) 
  18428.  
  18429. typedef struct _DataPacket
  18430. {
  18431.   BYTE  ReturnByte;
  18432.   UCHAR ConfigDataBlock[320!;
  18433.   } DataPacket;
  18434.  
  18435. ConfigDataBlock - EISA Configuration Data Block 
  18436.  
  18437. Parameter Packet Format 
  18438.  
  18439. typedef struct _ParmPacket
  18440. {
  18441.   BYTE SubFuncNum;
  18442.   BYTE SlotNum;
  18443.   BYTE FuncNum;
  18444. } ParmPacket;
  18445.  
  18446. SubFuncNum    - the EISA subfunction to perform (0=Query EISA slot information, 
  18447.               1=Query EISA function information). 
  18448.  
  18449. SlotNum       - binary EISA slot number (planar = 0) 
  18450.  
  18451. FuncNum       - binary EISA function to issue 
  18452.  
  18453. This function routes selected EISA function calls to the EISA BIOS. 
  18454.  
  18455. Comments 
  18456.  
  18457. See the technical reference manual for your personal computer for more 
  18458. information on EISA functions and returned values. 
  18459.  
  18460. FUNCTION 05h - Query ROM BIOS Information 
  18461.  
  18462. Parameter Packet Format 
  18463.  
  18464. typedef struct _ParmPacket
  18465. {
  18466.   USHORT Model;
  18467.   USHORT Submodel;
  18468.   USHORT BIOSRevLevel;
  18469.   USHORT Flags;
  18470. } ParmPacket;
  18471.  
  18472. Return ROM BIOS Information. 
  18473.  
  18474. Model               - binary machine model byte zero extened 
  18475.  
  18476. Submodel            - binary machine submodel byte zero extended 
  18477.  
  18478. BIOSRevisionLevel   - binary machine submodel byte zero extened 
  18479.  
  18480. Flags               - binary value, ABIOS present (bit 0=1), all other bits 
  18481.                     reserved 
  18482.  
  18483. Comments 
  18484.  
  18485. Version 2.0 of the OS/2 operating system does not support RAM-loaded ABIOS 
  18486. machines.  Version 2.0 of the OS/2 operating system returns bit 0 set to zero 
  18487. on machines with RAM-loaded ABIOS. 
  18488.  
  18489. Version 2.1 of the OS/2 operating system supports RAM-loaded ABIOS machines. 
  18490. Version 2.1 of the OS/2 operating system returns bit 0 set to one on machines 
  18491. with RAM-loaded ABIOS. 
  18492.  
  18493. FUNCTION 06h - Query Miscellaneous Video Information 
  18494.  
  18495. Data Packet Format 
  18496.  
  18497. typedef struct _DataPacket
  18498. {
  18499.   BYTE VideoStateInfo;
  18500. } DataPacket;
  18501.  
  18502. Return miscellaneous video state information. 
  18503.  
  18504. Bit 7   - reserved 
  18505.  
  18506. Bit 6   - P70 video adapter active 
  18507.  
  18508. Bit 5   - video attribute bit (0=background intensity, 2=blinking) 
  18509.  
  18510. Bit 4   - cursor emulation active 
  18511.  
  18512. Bit 3   - mode set default palette loading disabled 
  18513.  
  18514. Bit 2   - monochrome display attached 
  18515.  
  18516. Bit 1   - summing active 
  18517.  
  18518. Bit 0   - all modes on all displays active 
  18519.  
  18520. Comments 
  18521.  
  18522. Bit 0 and bit 4 are always 0 for the IBM PS/2 Model 8530.  See the IBM Personal 
  18523. System/2 and Personal Computer BIOS Interface Technical Reference or the 
  18524. technical reference manual for your personal computer for more information on 
  18525. the miscellaneous video state information returned from INT 10h (AX=1B00h). 
  18526.  
  18527. FUNCTION 07h - Query Video Adapter 
  18528.  
  18529. Data Packet Format 
  18530.  
  18531. typedef struct _DataPacket
  18532. {
  18533.   BYTE AdapterType;
  18534. } DataPacket;
  18535.  
  18536. Returns the video adapter type. 
  18537.  
  18538. Bit 0     - MPA 
  18539.  
  18540. Bit 1     - CGA 
  18541.  
  18542. Bit 2     - EGA 
  18543.  
  18544. Bit 3     -  VGA 
  18545.  
  18546. Bits 4-7  - reserved 
  18547.  
  18548. FUNCTION 08h - Query SVGA Information 
  18549.  
  18550. Data Packet Format 
  18551.  
  18552. typedef struct _DataPacket
  18553. {
  18554.   USHORT AdapterType;
  18555.   USHORT ChipType;
  18556.   ULONG  VideoMemory;
  18557. } DataPacket;
  18558.  
  18559. Returns SVGA video information. 
  18560.  
  18561. AdapterType    - binary video adapter type (see Table D-2) 
  18562.  
  18563. ChipType       - binary value of video chipset (see Table D-2) 
  18564.  
  18565. VideoMemory    - number of bytes of video RAM 
  18566.  
  18567. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  18568. ΓöéManufacturer   ΓöéChip SetΓöéAdapter TypeΓöéChip TypeΓöé
  18569. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18570. ΓöéIndeterminate  Γöé        Γöé0           Γöé0        Γöé
  18571. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18572. ΓöéHeadland       ΓöéHT205   Γöé1           Γöé1        Γöé
  18573. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18574. Γöé               ΓöéHT206   Γöé1           Γöé2        Γöé
  18575. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18576. Γöé               ΓöéHT209   Γöé1           Γöé3        Γöé
  18577. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18578. ΓöéTrident        Γöé8800    Γöé2           Γöé1        Γöé
  18579. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18580. Γöé               Γöé8900    Γöé2           Γöé2        Γöé
  18581. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18582. ΓöéTseng          ΓöéET3000  Γöé3           Γöé1        Γöé
  18583. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18584. Γöé               ΓöéET4000  Γöé3           Γöé2        Γöé
  18585. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18586. ΓöéWestern DigitalΓöéPVGA1A  Γöé4           Γöé1        Γöé
  18587. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18588. Γöé               ΓöéWD90C00 Γöé4           Γöé2        Γöé
  18589. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18590. Γöé               ΓöéWD90C11 Γöé4           Γöé3        Γöé
  18591. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18592. Γöé               ΓöéWD90C30 Γöé4           Γöé4        Γöé
  18593. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18594. ΓöéATI            Γöé18800   Γöé5           Γöé1        Γöé
  18595. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18596. Γöé               Γöé28800   Γöé5           Γöé2        Γöé
  18597. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18598. ΓöéIBM            ΓöéVGA256C Γöé6           Γöé1        Γöé
  18599. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18600. ΓöéCirrus Logic   ΓöéGD5422  Γöé7           Γöé1        Γöé
  18601. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18602. Γöé               ΓöéGD5424  Γöé7           Γöé2        Γöé
  18603. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  18604. Γöé               ΓöéGD5426  Γöé7           Γöé3        Γöé
  18605. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  18606. Table D-2. Video Chip Set Information 
  18607.  
  18608. FUNCTION 09h - Query Memory Information 
  18609.  
  18610. Data Packet Format 
  18611.  
  18612. typedef struct _DataPacket
  18613. {
  18614.   USHORT LowMemorySize;
  18615.   USHORT HighMemorySize;
  18616. } DataPacket;
  18617.  
  18618. LowMemorySize - the amount of RAM available below the 1MB region. 
  18619.  
  18620. HighMemorySize - the amount of RAM available above the 1MB region. 
  18621.  
  18622. This function returns the amount of RAM available on the machine. 
  18623.  
  18624. Comments 
  18625.  
  18626. The number of KB in high memory is a DWORD field for Version 2.1 of the OS/2 
  18627. operating system.  Previous versions of the OS/2 operating system used a WORD 
  18628. field.  Applications should query the version of the OS/2 operating system to 
  18629. determine the size of the data packet required. This can be done by issuing an 
  18630. OEMHELP category 80 IOCtl function 00H, or issuing a GetDosVar DevHlp with 
  18631. index=1 and looking at the MajorVersion and MinorVersion. 
  18632.  
  18633. FUNCTION 0ah - Query/Set XGA DMQS Information 
  18634.  
  18635. Data Packet Format 
  18636.  
  18637. typedef struct _DataPacket
  18638. {
  18639.   PVOID pDqmsInfo;
  18640. } DataPacket;
  18641.  
  18642. pDqmsInfo - a 16:16 pointer to the XGA DQMS information 
  18643.  
  18644. This function returns a pointer to the XGA DQMS video information block. 
  18645.  
  18646. Comments 
  18647.  
  18648. The pointer returned is a protect-mode address.  Protect-mode applications and 
  18649. device drivers do not need to convert this address before using it.  The XGA 
  18650. DMQS information is available only for IBM XGA/2 adapters and compatibles. 
  18651.  
  18652. Information on XGA Display Mode Query and Set (DMQS) can be found in the IBM 
  18653. Personal System/2 Hardware Interface Technical Reference - Video Subsystem. 
  18654.  
  18655. The following program, which was supplied by IBM, demonstrates how you would 
  18656. call the OEMHLP device driver to obtain the necessary configuration 
  18657. information. 
  18658.  
  18659. /* OEMHLP category */
  18660.  
  18661. #define  OEMHLP_CATEGORY                       0x80
  18662.  
  18663. /* OEMHLP functions */
  18664.  
  18665. #define  OEMHLP_QUERYOEMADAPTATIONINFO         0x00
  18666. #define  OEMHLP_QUERYMACHINEINFORMATION        0x01
  18667. #define  OEMHLP_QUERYDISPLAYCOMBINIATION       0x02
  18668. #define  OEMHLP_GETVIDEOFONTS                  0x03
  18669. #define  OEMHLP_QUERYEISACONFIG                0x04
  18670. #define  OEMHLP_QUERYBIOSINFO                  0x05
  18671. #define  OEMHLP_QUERYMISCVIDEOINFO             0x06
  18672. #define  OEMHLP_QUERYVIDEOADAPTER              0x07
  18673. #define  OEMHLP_QUERYSVGAINFO                  0x08
  18674. #define  OEMHLP_QUERYMEMORYINFO                0x09
  18675. #define  OEMHLP_QUERYDMQSINFO                  0x0A
  18676.  
  18677. typedef struct _OEMADAPTATIONINFO{
  18678.   CHAR        oai_OEMName[20!;
  18679.   CHAR        oai_InternalRevision[10!;
  18680. } OEMADAPTATIONINFO;
  18681.  
  18682. typedef OEMADAPTATIONINFO far * POEMADAPTATIONINFO;
  18683.  
  18684. typedef struct _MACHINEINFO{
  18685.   CHAR        mi_Manufacturer[20!;
  18686.   CHAR        mi_ModelNumber[10!;
  18687.   CHAR        mi_ROMRevision[10!;
  18688. } MACHINEINFO;
  18689.  
  18690. typedef MACHINEINFO far * PMACHINEINFO;
  18691.  
  18692. typedef BYTE DISPLAYCOMBINATIONCODE;
  18693.  
  18694. typedef struct _VIDEOFONTS{
  18695.   ULONG       vf_8X14Font;
  18696.   ULONG       vf_8X8Font;
  18697.   ULONG       vf_8X8TFont;
  18698.   ULONG       vf_9X14Font;
  18699.   ULONG       vf_8X16Font;
  18700.   ULONG       vf_9X16Font;
  18701. } VIDEOFONTS;
  18702.  
  18703. typedef VIDEOFONTS far * PVIDEOFONTS;
  18704.  
  18705. /* OEM EISA Subfunctions */
  18706.  
  18707. #define OEM_GET_SLOT_INFO      0
  18708. #define OEM_GET_FUNCTION_INFO  1
  18709.  
  18710. /* Adapter Slot */
  18711.  
  18712. #define CFG_MAX_EISA_SLOTS 16
  18713.  
  18714. /* OEM HELP typedefs */
  18715.  
  18716. typedef struct _EISASLOTINFO {
  18717.   UCHAR    esi_Error;
  18718.   UCHAR    esi_Flags;
  18719.   UCHAR    esi_MajorVer;
  18720.   UCHAR    esi_MinorVer;
  18721.   USHORT   esi_CheckSum;
  18722.   UCHAR    esi_DevFunc;
  18723.   UCHAR    esi_FuncInfo;
  18724.   ULONG    esi_CardID;
  18725. } EISASLOTINFO;
  18726.  
  18727. typedef EISASLOTINFO far * PEISASLOTINFO;
  18728.  
  18729. typedef struct _EISAFUNCTIONINFO {
  18730.   UCHAR  efi_SubFunc;
  18731.   UCHAR  efi_Slot;
  18732.   UCHAR  efi_Func;
  18733. } EISAFUNCTIONINFO;
  18734.  
  18735. typedef EISAFUNCTIONINFO far * PEISAFUNCTIONINFO;
  18736.  
  18737. typedef struct _BIOSINFO {
  18738.   USHORT bi_Model;
  18739.   USHORT bi_SubModel;
  18740.   USHORT bi_RevisionLevel;
  18741.   USHORT bi_ABIOS_Present;
  18742. } BIOSINFO;
  18743.  
  18744. typedef BIOSINFO far *PBIOSINFO;
  18745.  
  18746. typedef BYTE MISCVIDEOINFO;
  18747.  
  18748. typedef BYTE VIDEOADAPTER;
  18749.  
  18750. typedef struct _SVGAINFO {
  18751.   USHORT   si_AdapterType;
  18752.   USHORT   si_ChipType;
  18753.   ULONG  si_VideoMemory;
  18754. } SVGAINFO;
  18755.  
  18756. typedef SVGAINFO far *PSVGAINFO;
  18757.  
  18758. typedef struct _OLDMEMORYINFO {
  18759.   USHORT   omi_LowMemory;
  18760.   USHORT   omi_HighMemory;
  18761. } OLDMEMORYINFO;
  18762.  
  18763. typedef OLDMEMORYINFO far *POLDMEMORYINFO;
  18764.  
  18765. typedef struct _NEWMEMORYINFO {
  18766.   USHORT   nmi_LowMemory;
  18767.   ULONG    nmi_HighMemory;
  18768. } NEWMEMORYINFO;
  18769.  
  18770. typedef NEWMEMORYINFO far *PNEWMEMORYINFO;
  18771.  
  18772. typedef PVOID DMQSINFO;
  18773.  
  18774. /* mainline oemhelp.c */
  18775.  
  18776. #define INCL_DOSDEVICES
  18777. #define INCL_DOSDEVIOCTL
  18778. #define INCL_DOSERRORS
  18779. #define INCL_DOS
  18780. #define INCL_TYPES
  18781.  
  18782. #include  <os2.h>
  18783. #include  <stdio.h>
  18784. #include  <stdlib.h>
  18785. #include  "OEMHELP.H"
  18786.  
  18787. const PSZ OEMHLPDD = "OEMHLP$";
  18788.  
  18789. /*****************************************************************/
  18790. /*                       Data/Parameter Packets                  */
  18791. /*****************************************************************/
  18792.  
  18793. OEMADAPTATIONINFO      OEMAdaptationInfo       = {0};
  18794. MACHINEINFO            MachineInfo             = {0};
  18795. DISPLAYCOMBINATIONCODE DisplayCombiniationCode = 0;
  18796. VIDEOFONTS             VideoFonts              = {0};
  18797. EISASLOTINFO           EISASlotInfo            = {0};
  18798. EISAFUNCTIONINFO       EISAFunctionInfo        = {0};
  18799. BIOSINFO               BIOSInfo                = {0};
  18800. MISCVIDEOINFO          MiscVideoInfo           = 0;
  18801. VIDEOADAPTER           VideoAdapter            = 0;
  18802. SVGAINFO               SVGAInfo                = {0};
  18803. OLDMEMORYINFO          OldMemoryInfo           = {0};
  18804. NEWMEMORYINFO          NewMemoryInfo           = {0};
  18805. DMQSINFO               DMQSInfo                = 0;
  18806.  
  18807. /*****************************************************************/
  18808. /*                       Procedure Prototypes                    */
  18809. /*****************************************************************/
  18810.  
  18811. USHORT main(USHORT argc,char *argv[!);
  18812.  
  18813. /*****************************************************************/
  18814. /*                         MAIN Procedure                        */
  18815. /*****************************************************************/
  18816.  
  18817. USHORT main(USHORT argc, char * argv[!)
  18818.  
  18819. {
  18820.   USHORT usAction,index;
  18821.   USHORT rc = 0;
  18822.   HFILE  filehandle;
  18823.   long templow,temphigh,tempall;
  18824.  
  18825.   if (0 ]= (rc = DosOpen(OEMHLPDD,
  18826.                          &filehandle,
  18827.                          &usAction,
  18828.                          0L,
  18829.                          0,
  18830.                          1,
  18831.                          0xC2,
  18832.                          0L)))
  18833.   {
  18834.     printf("\n Error opening OEMHLP device driver.\n");
  18835.     return(rc);
  18836.   }
  18837.  
  18838.   /***************************************************************/
  18839.   /*               OEMHLP_QUERYOEMADAPTATIONINFO         0x00    */
  18840.   /***************************************************************/
  18841.  
  18842.    if (rc = DosDevIOCtl((PVOID)&OEMAdaptationInfo,
  18843.                         (PVOID)NULL,
  18844.                         (USHORT)OEMHLP_QUERYOEMADAPTATIONINFO,
  18845.                         (USHORT)OEMHLP_CATEGORY,
  18846.                         (HFILE)filehandle))
  18847.    {
  18848.      printf("\n Error from function OEMHLP_QUERYOEMADAPTATIONINFO,
  18849.             RC=%xH.\n",rc);
  18850.    }
  18851.    else
  18852.    {
  18853.    printf("\n OEMName          = %s",OEMAdaptationInfo.oai_OEMName);
  18854.    printf("\n InternalRevision = %s",
  18855.           OEMAdaptationInfo.oai_InternalRevision);
  18856.    printf("\n");
  18857.    }
  18858.  
  18859.    /**************************************************************/
  18860.    /*               OEMHLP_QUERYMACHINEINFORMATION        0x01   */
  18861.    /**************************************************************/
  18862.  
  18863.    if (rc = DosDevIOCtl((PVOID)&MachineInfo,
  18864.                         (PVOID)NULL,
  18865.                         (USHORT)OEMHLP_QUERYMACHINEINFORMATION,
  18866.                         (USHORT)OEMHLP_CATEGORY,
  18867.                         (HFILE)filehandle))
  18868.    {
  18869.      printf("\n Error from function OEMHLP_QUERYMACHINEINFORMATION,
  18870.             RC=%xH.\n",rc);
  18871.    }
  18872.    else
  18873.    {
  18874.      printf("\n Manufacturer     = %s",MachineInfo.mi_Manufacturer);
  18875.      printf("\n Model            = %s",MachineInfo.mi_ModelNumber);
  18876.      printf("\n ROM Revision     = %s",MachineInfo.mi_ROMRevision);
  18877.      printf("\n");
  18878.    }
  18879.  
  18880.    /**************************************************************/
  18881.    /*               OEMHLP_QUERYDISPLAYCOMBINIATION       0x02   */
  18882.    /**************************************************************/
  18883.  
  18884.    if (rc = DosDevIOCtl((PVOID)&DisplayCombiniationCode,
  18885.                         (PVOID)NULL,
  18886.                         (USHORT)OEMHLP_QUERYDISPLAYCOMBINIATION,
  18887.                         (USHORT)OEMHLP_CATEGORY,
  18888.                         (HFILE)filehandle))
  18889.    {
  18890.      printf("\n Error from function OEMHLP_QUERYDISPLAYCOMBINIATION,
  18891.              RC=%xH.\n",rc);
  18892.    }
  18893.    else
  18894.    {
  18895.      printf("\n Display Combination code = %xH",DisplayCombiniationCode);
  18896.      printf("\n");
  18897.    }
  18898.  
  18899.    /**************************************************************/
  18900.    /*               OEMHLP_GETVIDEOFONTS                  0x03   */
  18901.    /**************************************************************/
  18902.  
  18903.    if (rc = DosDevIOCtl((PVOID)&VideoFonts,
  18904.                         (PVOID)NULL,
  18905.                         (USHORT)OEMHLP_GETVIDEOFONTS,
  18906.                         (USHORT)OEMHLP_CATEGORY,
  18907.                         (HFILE)filehandle))
  18908.    {
  18909.      printf("\n Error from function OEMHLP_GETVIDEOFONTS, RC=%xH.\n",rc);
  18910.    }
  18911.    else
  18912.    {
  18913.      printf("\n 8X14Font = %p",VideoFonts.vf_8X14Font);
  18914.      printf("\n 8X8Font  = %p",VideoFonts.vf_8X8Font);
  18915.      printf("\n 8X8TFont = %p",VideoFonts.vf_8X8TFont);
  18916.      printf("\n 9X14Font = %p",VideoFonts.vf_9X14Font);
  18917.      printf("\n 8X16Font = %p",VideoFonts.vf_8X16Font);
  18918.      printf("\n 9X16Font = %p",VideoFonts.vf_9X16Font);
  18919.      printf("\n");
  18920.    }
  18921.  
  18922.    /**************************************************************/
  18923.    /*               OEMHLP_QUERYEISACONFIG                0x04   */
  18924.    /**************************************************************/
  18925.  
  18926.    /* initialize EISA parameters */
  18927.  
  18928.    EISAFunctionInfo.efi_SubFunc = OEM_GET_SLOT_INFO;/* EISA Get Slot  */
  18929.    EISAFunctionInfo.efi_Slot    = 0;                /* Slot 0         */
  18930.  
  18931.    if (rc = DosDevIOCtl((PVOID)&EISASlotInfo,
  18932.                         (PVOID)&EISAFunctionInfo,
  18933.                         (USHORT)OEMHLP_QUERYEISACONFIG,
  18934.                         (USHORT)OEMHLP_CATEGORY,
  18935.                         (HFILE)filehandle))
  18936.    {
  18937.      printf("\n Error issuing QueryEISAConfig assuming non-EISA,
  18938.             RC=%u.\n",rc);
  18939.    }
  18940.    else
  18941.    {
  18942.      printf("\n Slot 0 (planar) ID = %lxH ",EISASlotInfo.esi_CardID);
  18943.      printf("\n           Error    = %xH  ",(SHORT)EISASlotInfo.esi_Error);
  18944.      printf("\n           Flags    = %xH  ",(SHORT)EISASlotInfo.esi_Flags);
  18945.      printf("\n           MajorVer = %xH  ",
  18946.             (SHORT)EISASlotInfo.esi_MajorVer);
  18947.      printf("\n           MinorVer = %xH  ",
  18948.             (SHORT)EISASlotInfo.esi_MinorVer);
  18949.      printf("\n           CheckSum = %xH  ",
  18950.             (SHORT)EISASlotInfo.esi_CheckSum);
  18951.      printf("\n           DevFunc  = %xH  ",
  18952.             (SHORT)EISASlotInfo.esi_DevFunc);
  18953.      printf("\n           FuncInfo = %xH  ",
  18954.             (SHORT)EISASlotInfo.esi_FuncInfo);
  18955.      for(index=1;index<CFG_MAX_EISA_SLOTS;index++) /* For each slot */
  18956.      {
  18957.        EISAFunctionInfo.efi_Slot    = (UCHAR) index; /* Slot Number */
  18958.        EISASlotInfo.esi_CardID  = 0;                 /* Reset Adapter ID */
  18959.        rc = DosDevIOCtl((PVOID)&EISASlotInfo,        /* Data Packet */
  18960.                         (PVOID)&EISAFunctionInfo,    /* Parm Packet */
  18961.                         (USHORT)OEMHLP_QUERYEISACONFIG,
  18962.                         (USHORT)OEMHLP_CATEGORY,
  18963.                         (HFILE)filehandle);
  18964.  
  18965.        /* If IOCTL successful and EISA has adapter, then store away
  18966.          the adapter ID, otherwise mark as empty with a zero.
  18967.        */
  18968.  
  18969.        if((rc==0)&&(EISASlotInfo.esi_Error==0))
  18970.        {
  18971.          printf("\n Slot %d ID = %lxH ",index,EISASlotInfo.esi_CardID);
  18972.          printf("\n   Error    = %xH  ",(SHORT)EISASlotInfo.esi_Error);
  18973.          printf("\n   Flags    = %xH  ",(SHORT)EISASlotInfo.esi_Flags);
  18974.          printf("\n   MajorVer = %xH  ",(SHORT)EISASlotInfo.esi_MajorVer);
  18975.          printf("\n   MinorVer = %xH  ",(SHORT)EISASlotInfo.esi_MinorVer);
  18976.          printf("\n   CheckSum = %xH  ",(SHORT)EISASlotInfo.esi_CheckSum);
  18977.          printf("\n   DevFunc  = %xH  ",(SHORT)EISASlotInfo.esi_DevFunc);
  18978.          printf("\n   FuncInfo = %xH  ",(SHORT)EISASlotInfo.esi_FuncInfo);
  18979.        }
  18980.        else
  18981.        {
  18982.          printf("\n Error reading Slot %d ID, RC=%u, EISA Error=%u ",
  18983.                index,rc,(SHORT)EISASlotInfo.esi_Error);
  18984.        }
  18985.      }/* for */
  18986.    printf("\n");
  18987.    }
  18988.  
  18989.    /**************************************************************/
  18990.    /*               OEMHLP_QUERYBIOSINFO                  0x05   */
  18991.    /**************************************************************/
  18992.  
  18993.    if (rc = DosDevIOCtl((PVOID)&BIOSInfo,
  18994.                         (PVOID)NULL,
  18995.                         (USHORT)OEMHLP_QUERYBIOSINFO,
  18996.                         (USHORT)OEMHLP_CATEGORY,
  18997.                         (HFILE)filehandle))
  18998.    {
  18999.      printf("\n Error from function OEMHLP_QUERYBIOSINFO, RC=%xH.\n",rc);
  19000.    }
  19001.    else
  19002.    {
  19003.      printf("\n Model byte     = %xH ",BIOSInfo.bi_Model);
  19004.      printf("\n Submodel byte  = %xH ",BIOSInfo.bi_SubModel);
  19005.      printf("\n Revision level = %xH ",BIOSInfo.bi_RevisionLevel);
  19006.      printf("\n ABIOS Present  = %xH ",BIOSInfo.bi_ABIOS_Present);
  19007.      printf("\n");
  19008.    }
  19009.  
  19010.    /**************************************************************/
  19011.    /*               OEMHLP_QUERYMISCVIDEOINFO             0x06   */
  19012.    /**************************************************************/
  19013.  
  19014.    if (rc = DosDevIOCtl((PVOID)&MiscVideoInfo,
  19015.                         (PVOID)NULL,
  19016.                         (USHORT)OEMHLP_QUERYMISCVIDEOINFO,
  19017.                         (USHORT)OEMHLP_CATEGORY,
  19018.                         (HFILE)filehandle))
  19019.    {
  19020.      printf("\n Error from function OEMHLP_QUERYMISCVIDEOINFO,
  19021.             RC=%xH.\n",rc);
  19022.    }
  19023.    else
  19024.    {
  19025.      printf("\n Misc Video Info   = %xH ",MiscVideoInfo);
  19026.      printf("\n");
  19027.    }
  19028.  
  19029.    /**************************************************************/
  19030.    /*               OEMHLP_QUERYVIDEOADAPTER              0x07   */
  19031.    /**************************************************************/
  19032.  
  19033.    if (rc = DosDevIOCtl((PVOID)&VideoAdapter,
  19034.                         (PVOID)NULL,
  19035.                         (USHORT)OEMHLP_QUERYVIDEOADAPTER,
  19036.                         (USHORT)OEMHLP_CATEGORY,
  19037.                         (HFILE)filehandle))
  19038.    {
  19039.      printf("\n Error from function OEMHLP_QUERYVIDEOADAPTER,
  19040.             RC=%xH.\n",rc);
  19041.    }
  19042.    else
  19043.    {
  19044.      printf("\n Video Adapter     = %xH ",VideoAdapter);
  19045.      printf("\n");
  19046.    }
  19047.  
  19048.    /**************************************************************/
  19049.    /*               OEMHLP_QUERYSVGAINFO                  0x08   */
  19050.    /**************************************************************/
  19051.  
  19052.    if (rc = DosDevIOCtl((PVOID)&SVGAInfo,
  19053.                         (PVOID)NULL,
  19054.                         (USHORT)OEMHLP_QUERYSVGAINFO,
  19055.                         (USHORT)OEMHLP_CATEGORY,
  19056.                         (HFILE)filehandle))
  19057.    {
  19058.      printf("\n Error from function OEMHLP_QUERYSVGAINFO, RC=%xH.\n",rc);
  19059.    }
  19060.    else
  19061.    {
  19062.      printf("\n Adapter Type    = %xH " ,SVGAInfo.si_AdapterType);
  19063.      printf("\n Chip    Type    = %xH " ,SVGAInfo.si_ChipType);
  19064.      printf("\n Video memory    = %lxH ",SVGAInfo.si_VideoMemory);
  19065.      printf("\n");
  19066.    }
  19067.  
  19068.    /***************************************************************/
  19069.    /*               OEMHLP_QUERYMEMORYINFO                0x09    */
  19070.    /***************************************************************/
  19071.  
  19072.    if (strncmp(OEMAdaptationInfo.oai_InternalRevision,"20.",3))
  19073.    {
  19074.  
  19075.      /* String is different, use old memoryinfo */
  19076.  
  19077.      if (rc = DosDevIOCtl((PVOID)&OldMemoryInfo,
  19078.                           (PVOID)NULL,
  19079.                           (USHORT)OEMHLP_QUERYMEMORYINFO,
  19080.                           (USHORT)OEMHLP_CATEGORY,
  19081.                           (HFILE)filehandle))
  19082.      {
  19083.        printf("\n Error from function OEMHLP_QUERYMEMORYINFO,
  19084.               RC=%xH.\n",rc);
  19085.      }
  19086.      else
  19087.      {
  19088.       templow=OldMemoryInfo.omi_LowMemory;
  19089.       temphigh=OldMemoryInfo.omi_HighMemory;
  19090.       tempall=templow+temphigh;
  19091.       printf("\n Low Memory    = %d " ,OldMemoryInfo.omi_LowMemory);
  19092.       printf("\n High Memory   = %d " ,OldMemoryInfo.omi_HighMemory);
  19093.       printf("\n Total Memory  = %ld ",tempall);
  19094.       printf("\n");
  19095.      }
  19096.    }
  19097.    else
  19098.    {
  19099.  
  19100.      /* String is same use new memoryinfo */
  19101.  
  19102.      if (rc = DosDevIOCtl((PVOID)&NewMemoryInfo,
  19103.                           (PVOID)NULL,
  19104.                           (USHORT)OEMHLP_QUERYMEMORYINFO,
  19105.                           (USHORT)OEMHLP_CATEGORY,
  19106.                           (HFILE)filehandle))
  19107.      {
  19108.        printf("\n Error from function OEMHLP_QUERYMEMORYINFO,
  19109.               RC=%xH.\n",rc);
  19110.      }
  19111.      else
  19112.      {
  19113.        templow=NewMemoryInfo.nmi_LowMemory;
  19114.        temphigh=NewMemoryInfo.nmi_HighMemory;
  19115.        tempall=templow+temphigh;
  19116.        printf("\n Low Memory    = %d " ,NewMemoryInfo.nmi_LowMemory);
  19117.        printf("\n High Memory   = %ld " ,NewMemoryInfo.nmi_HighMemory);
  19118.        printf("\n Total Memory  = %ld ",tempall);
  19119.        printf("\n");
  19120.      }
  19121.    }
  19122.  
  19123.    /***************************************************************/
  19124.    /*               OEMHLP_QUERYDMQSINFO                  0x0A    */
  19125.    /***************************************************************/
  19126.  
  19127.    if (rc = DosDevIOCtl((PVOID)&DMQSInfo,
  19128.                         (PVOID)NULL,
  19129.                         (USHORT)OEMHLP_QUERYDMQSINFO,
  19130.                         (USHORT)OEMHLP_CATEGORY,
  19131.                         (HFILE)filehandle))
  19132.    {
  19133.      printf("\n Error from function OEMHLP_QUERYDMQSINFO, RC=%xH.\n",rc);
  19134.    }
  19135.    else
  19136.    {
  19137.      printf("\n DMQS Pointer = %p",DMQSInfo);
  19138.      printf("\n");
  19139.    }
  19140.  
  19141.    if (rc=DosClose(filehandle))
  19142.    {
  19143.      printf("\n Error closing OEMHLP device driver, RC=%xH.\n",rc);
  19144.    }
  19145.  
  19146.    return(rc);
  19147. }
  19148.  
  19149. TESTCFG 
  19150.  
  19151. The TESTCFG device driver offers some additonal functionality to aid in 
  19152. determining the machine bus type and hardware configuration. It consists of six 
  19153. IOCtls in category 0x80. The IOCtls are described in Table D-3. TESTCFG is 
  19154. opened with the name TESTCFG$. 
  19155.  
  19156. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  19157. ΓöéFunctionΓöéDescription                             Γöé
  19158. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  19159. Γöé0x40    ΓöéGet copy of non-system memory           Γöé
  19160. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  19161. Γöé0x41    Γöé"IN" instruction                        Γöé
  19162. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  19163. Γöé0x42    Γöé"OUT" instruction                       Γöé
  19164. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  19165. Γöé0x60    ΓöéGet bus type                            Γöé
  19166. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  19167. Γöé0x61    ΓöéGet POS registers                       Γöé
  19168. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  19169. Γöé0x62    ΓöéGet EISA IDs                            Γöé
  19170. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  19171. Table D-3. TESTCFG IOCtls, Category 0x80 
  19172.  
  19173. FUNCTION 40h - Get Copy Of Non-system Memory 
  19174.  
  19175. Parameter Packet Format 
  19176.  
  19177. typedef struct _ParmPacket
  19178. {
  19179.   ULONG  command;       // must be set to 0
  19180.   ULONG  physaddr;      // physical address 0xc0000 to 0xfffff
  19181.   USHORT numbytes       // number of bytes to get
  19182. } DataPacket;
  19183.  
  19184. Data Packet Format 
  19185.  
  19186. typedef struct _DataPacket
  19187. {
  19188.   BYTE   bytes[numbytes!;
  19189. } DataPacket;
  19190.  
  19191. Comments 
  19192.  
  19193. This IOCtl returns copies the contents of physical memory below the 1MB region 
  19194. to a local buffer. 
  19195.  
  19196. FUNCTION 41h - Perform an "IN" Instruction 
  19197.  
  19198. Parameter Packet Format 
  19199.  
  19200. typedef struct _ParmPacket
  19201. {
  19202.   USHORT portaddress;   // I/O port
  19203.   USHORT width;         // # bytes, 1=byte, 2=word, 3=dword
  19204. } DataPacket;
  19205.  
  19206. Data Packet Format 
  19207.  
  19208. typedef struct _DataPacket
  19209. {
  19210.   ULONG data;           // data read
  19211. } DataPacket;
  19212.  
  19213. Comments 
  19214.  
  19215. Ports below 0x100 are not accessible. 
  19216.  
  19217. FUNCTION 42h - Issue An "OUT" Instruction 
  19218.  
  19219. Parameter Packet Format 
  19220.  
  19221. typedef struct _ParmPacket
  19222. {
  19223.   USHORT portaddress;   // I/O port
  19224.   USHORT width;         // # bytes, 1=byte, 2=word, 4=dword
  19225. } DataPacket;
  19226.  
  19227. Data Packet Format 
  19228.  
  19229. None.
  19230.  
  19231. Comments 
  19232.  
  19233. Ports below 0x100 are not accessible. 
  19234.  
  19235. FUNCTION 60h - Query Bus Architecture 
  19236.  
  19237. Parameter Packet Format 
  19238.  
  19239. typedef struct _ParmPacket
  19240. {
  19241.   ULONG command;        // must be set to 0
  19242. } DataPacket;
  19243.  
  19244. Data Packet Format 
  19245.  
  19246. typedef struct _DataPacket
  19247. {
  19248.   ULONG BusType;        // 0 = ISA, 1= Micro Channel, 2=EISA
  19249. } DataPacket;
  19250.  
  19251. Comments 
  19252.  
  19253. This IOCtl returns the current bus type. 
  19254.  
  19255. FUNCTION 61h - Get All Micro Channel Adapter IDs 
  19256.  
  19257. Parameter Packet Format 
  19258.  
  19259. typedef struct _ParmPacket
  19260. {
  19261.   ULONG command;        // must be set to 0
  19262. } DataPacket;
  19263.  
  19264. Data Packet Format 
  19265.  
  19266. typedef struct _DataPacket
  19267. {
  19268.   USHORT AdapterID[16!;  // receives IDs
  19269. } DataPacket;
  19270.  
  19271. Comments 
  19272.  
  19273. This function returns AdapterID[n] = 0 for ISA or EISA adapters. 
  19274.  
  19275. FUNCTION 62h - Get EISA Adapter IDs 
  19276.  
  19277. Parameter Packet Format 
  19278.  
  19279. typedef struct _ParmPacket
  19280. {
  19281.   ULONG command;         // must be set to 0
  19282. } DataPacket;
  19283.  
  19284. Data Packet Format 
  19285.  
  19286. typedef struct _DataPacket
  19287. {
  19288.   UCHAR EISAtype[16![4!; // EISA adapter IDs returned
  19289. } DataPacket;
  19290.  
  19291. Comments 
  19292.  
  19293. This function returns EISAType[n][n] = 0 for ISA or Micro Channel adapters. 
  19294.  
  19295. LIBRARY ORDER FORM 
  19296.  
  19297. A C callable DevHlp library is available for $79.00 without the library source, 
  19298. or for $149.00 with complete source of the 1.3 and 2.1 libraries, supplied on 
  19299. 3.5" 1.4 MB floppy disk.  Company P.O.s accepted by mail or Fax.  Checks should 
  19300. be made payable to Personal Systems Software, Inc.  International orders must 
  19301. include check payable in US dollars drawn on an international bank or wired to 
  19302. our account.  Sorry, we do not take credit cards.  Use the order blank below to 
  19303. order the DevHlp library.  Please allow 1 week for delivery. 
  19304.  
  19305. Qty ___  C Callable 2.1 DevHlp Library without source @ $79.00
  19306. Qty ___  C Callable 2.1 DevHlp Library with source @ $149.00
  19307.  
  19308. Mail total plus $5.00 shipping to:
  19309.  
  19310.                       Personal Systems Software, Inc.
  19311.                       15 Great Oak Lane
  19312.                       Unionville, CT 06085
  19313.                       Fax  (203) 693-9042
  19314.  
  19315.              Ship to:
  19316.                       ______________________________
  19317.  
  19318.                       ______________________________
  19319.  
  19320.                       ______________________________
  19321.  
  19322.                       ______________________________
  19323.  
  19324.