1.4 Some details
1.4.1 PDD header
The PDD header defines the characteristics of a driver.
field description |
length in bytes |
---|---|
a) far pointer to next device header |
4 |
b) device attribute |
2 |
c) 16 bit offset to strategy routine |
2 |
d) 16 bit offset to inter-device-driver-communication (IDC) routine |
2 |
e) driver name (character DD) / number of units (block DD) |
8 |
f) reserved |
8 |
g) capabilities bit strip |
8 |
a) far pointer to
next device header
This pointer should be set to 1
(ffffffff) in the driver's code. While loading the drivers, OS/2
builds a linked list for all drivers by using this field. If the
driver supports multiple devices, there is one header for each
device. Only the last header should be set to 1 the other ones
need to be linked together!
b) device
attribute
Describes the characteristics of the physical device
driver to the system.
CHR (bit 15)
Set,
if the physical device driver operates in character mode. Bit 15 is
the device type bit. Use bit 15 to tell the system if the device
driver is a block or character device. For block device drivers, bit
15 is 0. For character device drivers, bit 15 is 1.
IDC (bit 14)
Set,
if the physical device driver participates in inter-device-driver
communication (IDC). Bit 14 is the IDC bit and indicates that the
offset to the IDC entry point in the physical device driver header
is set.
IBM (R) (bit
13)
Set, if non-IBM block format (block device drivers only). For
block device drivers, bit 13 indicates the method which the physical
device driver uses to determine the media type. If a block device
driver uses information in the BIOS Parameter Block (BPB) to
determine the media type, bit 13 should be set to 1. If the physical
device driver uses the media descriptor byte to determine the media
type, bit 13 must be 0.
SHR (bit 12)
Set,
if the device driver supports shared-device access-checking
(character devices). Bit 12 is the shared bit. It is set if the
device name is not to be protected by the sharer. Bit 12 has no
meaning for block device drivers and must be 0. If clear (default),
file system sharing rules do not apply to the device, and the
physical device driver provides contention control. If set, file
system sharing rules apply to the device, just as these rules apply
to any other file system name. In addition, any given physical
device can have only one logical name. (Devices cannot have
aliases.)
OPN (bit 11)
Set,
if the device driver supports removable media (block devices) or
device open/close (character devices). For block device drivers, bit
11 is the removable media bit. If set, this bit indicates that the
physical device driver handles removable media. For character device
drivers, bit 11 is the open/close bit. If set, this bit indicates
that the physical device driver must receive OPEN and CLOSE request
packets.
bit 10
Reserved=0.
bits 9-7
bits
9-7 indicate the physical device driver function level, where:
bit 9 |
bit 8 |
bit 7 |
description |
---|---|---|---|
0 |
0 |
1 |
OS/2 driver (default) [Level 1 driver] |
0 |
1 |
0 |
Supports DosDevIOCtl2 and shutdown requests [Level 2 driver] |
0 |
1 |
1 |
Uses a capabilities strip bit in the header [Level 3 driver] |
bit
6-4
Reserved=0.
CLK (bit 3)
Set,
if CLOCK device. Bit 3 is the clock device bit. It is used by a
character device driver to indicate the system clock device.
NUL (bit 2)
Set,
if NULL device. Bit 2 is the NULL attribute bit. It is used by
character devices only. Bit 2 is used to tell the OS/2 operating
system if the character device driver is a NULL device. Although
there is a NULL device attribute bit, the NULL device cannot be
reassigned.
SCR (bit 1)
Set,
if standard output device (STDOUT). For character devices, bits 1
and 0 are the standard input or standard output bits. These bits are
used to tell the OS/2 operating system if the character device
driver is the new standard input or standard output device.
KBD (bit 0)
Set,
if standard input device (STDIN). See above.
c) 16 bit offset to
strategy routine
This is the
entry point to the code running in kernel mode. The kernel is using
this address to call the strategy routine.
d)
16 bit offset to inter-device-driver-communication (IDC) routine
This
address could be called by other device drivers to provide IDC.
e)
driver name (character DD) / number of units (block DD)
For
character DD's, the name needs to be in uppercase, left oriented and
filled up with blanks until the length is 8 bytes. The device name
takes precedence over file names! To avoid conflicts, sometimes a
driver's name uses special symbols, like a $ sign. Block DD's fill in
the number of supported units.
f)
reserved
reserved area for future use ?????
g)
capabilities bit strip
Level 3 device drivers have an
additional 8 byte field appended to the device header. Each bit of
this new field is a flag indicating whether or not a particular
feature is supported.
bit
0
Set to 1, if DosDevIOCtl2 request packets are supported, and if
shutdown support is provided.
bit
1
For block device drivers, this bit is reserved and must be set
to 0. Block device drivers indicate their ability to support higher
than 16 MB. For character device drivers, this bit is set to 1 (if
memory addressing above 16 MB is supported).
bit
2
Set to 1, if the physical device driver supports parallel
ports.
bit
3
Indicates that the physical device driver is participating in
the adapter device driver (ADD) strategy, which selects an alternate
INIT request packet format from the kernel.
bit
4
If set to 1, the Initialization Complete Command (1Fh) is
supported.
bits
5-31
Reserved. Must be set to 0.
Strategy routine:
a) If an application wants to communicate with the PDD, it calls one of the above kernel functions (e.g. DosOpen(), DosWrite(), ...).
b) The kernel does some parameter checking and builds a data structure called request packet.
c) The kernel calls the strategy entry point in the device driver and passes a pointer to the request packet. Pointers in the request packet (only for read/write requests) are already translated into a 32 bit physical address (already locked and verified), which is done automatically by the kernel. The strategy routine may build a request queue for further requests. Addresses received by IOCTL calls, are virtual addresses, not locked and not verified!
d) If the request can be answered in a short time, the strategy routine sets the return status in the request packet and ends. If the request can't be answered quickly (maybe the hardware isn't ready until yet), the driver should call a function to block the application thread. If the interrupt routine recognizes that the device is ready, the thread can be resumed. This mechanism is necessary to guarantee the multitasking mechanism. Code in the DD never preempts by the scheduler! You need to block the applications thread every time, if you can't directly deliver the result to the application. If the request can be answered directly, but it takes a lot of other calculation time in the strategy routine, yield the CPU every 3 milliseconds with a special function call!
e) NO "standard" OS/2 API function call can be made in this mode! Only special device-helper-functions can be used!
Interrupt routine:
a) The interrupt routine can be preempted by higher priority interrupts.
b) If time critical device checking is performed, it's a good idea to disable interrupts (for a very short time), to avoid preemption.
c) If the application thread has been blocked in the strategy routine, it can be resumed from the interrupt routine (if the data is available).
d) NO "standard" OS/2 API function call can be done in this mode! Only special device-helper-functions can be used!
INIT routine:
a) After the device driver is loaded (via a DEVICE= or BASEDEV= statement in CONFIG.SYS), this routine is called via the strategy routine. The request packet is marked as an INIT command!
b) Command line parameters can be read.
c) Because the context of this routine is a kernel thread, running at ring 3 with I/O privilege, some device initialization can be done here.
d) Some "standard" API functions can be used in this mode:
DosBeep (Generate sound from the speaker)
DosCaseMap (Perform case mapping)
DosChgFilePtr (Change (move) file read/write pointer)
DosClose (Close file handle)
DosDelete (Delete file)
DosDevConfig (Get device configuration)
DosDevIOCtl (I/O control for devices)
DosFindClose (Close find handle)
DosFindFirst (Find first matching file)
DosFindNext (Find next matching file)
DosGetEnv (Get address of process environment string)
DosGetInfoSeg (Get address of system variables segment)
DosGetMessage (Get system message with variable text)
DosOpen (Open file)
DosPutMessage (Output message text to indicated handle)
DosQCurDir (Query current directory)
DosQCurDisk (Query current disk)
DosQFileInfo (Query file information)
DosQFileMode (Query file mode)
DosRead (Read from file)
DosSMRegisterDD (Register session switch notification)
DosWrite (Synchronous write to file)
Only these functions can be called for kernel services in the kernel and interrupt mode. Some of them could be called at INIT mode. The interface is called DevHlp interface, which provides these functions.
One very important parameter is received with the first request packet while the driver gets initialized. This is a far pointer to the DevHlp entry point which needs to be saved by the driver to call the DevHlp functions, whenever needed!
You need to look at the PDD reference guide to find out, which function can be called with which context. Not all functions are available at kernel (task time), interrupt and INIT context!
There are about 90 DevHlp functions documented so far. The functions can be grouped together into the following categories:
Advanced BIOS Calls (ABIOS)
Character Queue Management
PDD-VDD Communication Services
Context Hook Services
Interrupt Management
Memory Management
Monitor Management
Process Management
Request Queue Management
Semaphore Management
System Clock Management
System Services
Timer Services
The Request Packet which is received by the drivers strategy routine, is divided into two different parts. The "Request Packet Header" and the "Command Specific Data". The following request packet commands have been documented so far:
Code |
Function |
Block DD |
Character DD |
---|---|---|---|
0 |
INIT |
x |
x |
1 |
MEDIA CHECK |
x |
|
2 |
BUILD BPB |
x |
|
4 |
READ |
x |
x |
5 |
NONDESTRUCTIVE READ NO WAIT |
|
x |
6 |
INPUT STATUS |
|
x |
7 |
INPUT FLUSH |
|
x |
8 |
WRITE |
x |
x |
9 |
WRITE WITH VERIFY |
x |
x |
A |
OUTPUT STATUS |
|
x |
B |
OUTPUT FLUSH |
|
x |
D |
OPEN DEVICE |
x |
x |
E |
CLOSE DEVICE |
x |
x |
F |
REMOVABLE MEDIA |
x |
|
10 |
GENERIC IOCtl |
x |
x |
11 |
RESET MEDIA |
x |
|
12 |
GET LOGICAL DRIVE MAP |
x |
|
13 |
SET LOGICAL DRIVE MAP |
x |
|
14 |
DEINSTALL |
|
x |
16 |
PARTITIONABLE HARD DISKS |
x |
|
17 |
GET HARD DISK/LOGICAL UNIT MAP |
x |
|
1C |
SHUTDOWN |
x |
x |
1D |
GET DRIVER CAPABILITIES |
x |
|
1F |
INITIALIZATION COMPLETE |
|
x |
Warpstock Europe 1999 |