This section written by Alberto Vignani <firstname.lastname@example.org> , Aug 10, 1997
For port I/O access the type ioport_t has been defined; it should be an unsigned short, but the previous unsigned int is retained for compatibility. Also for compatibility, the order of parameters has been kept as-is; new code should use the port_real_xxx(port,value) function. The new port code is selected at configuration time by the parameter --enable-new-port which will define the macro NEW_PORT_CODE. Files: portss.c is now no more used and has been replaced by n_ports.c; all functions used by 'old' port code have been moved to ports.c. Note that the code in portss.c (retrieved from Scott Buchholz's pre-0.61) was previously disabled (not used), because it had problems with older versions of dosemu.
The rep;in,out instructions will been optimized so to call iopl() only once.
Every process under Linux has a map of ports it is allowed to access. Too bad this map covers only the first 1024 (0x400) ports. For all the ports whose access permission is off, and all ports over 0x400, an exception is generated and trapped by dosemu.
When the I/O permission (ioperm) bit for a port is ON, the time it takes to access the port is much lower than a microsecond (30 cycles on a P5-150); when the port is accessed from dosemu through the exception mechanism, access times are in the range of tenths of us (3000 cycles on the P5-150) instead. It is easy to show that 99% of this time is spent in the kernel trap and syscalls, and the influence of the port selection method (table or switch) is actually minimal.
There is nothing we can do for ports over 0x400, only hope that these slow access times are not critical for the hardware (generally they are not) and use the largest possible word width (i.e. do not break 16- and 32-bit accesses).
The 'old' port code used a switch...case mechanism for accessing ports, while now the table access (previously in the unused file portss.c) has been chosen, as it is much more clear, easy to maintain and not slower than the "giant switch" method (at least on pentium and up).
There are two main tables in ports.c:
It works this way: when an I/O instruction is trapped (in do_vm86.c and dpmi.c) the standard entry points port_in[bwd],port_out[bwd] are called. They log the port access if specified and then perform a double indexed jump into the port table to the function responsible for the actual port access/emulation.
Ports must be registered before they can be used. This is the purpose of the port_register_handler function, which is called from inside the various device initializations in dosemu itself, and of port_allow_io, which is used for user-specified ports instead. Some ports, esp. those of the video adapter, are registered an trapped this way only under X, while in console mode they are permanently enabled (ioperm ON). The ioperm bit is also set to ON for the user-specified ports below 0x400 defined as fast. Of course, when a port has the ioperm bit ON, it is not trapped, and thus cannot be traced from inside dosemu.
There are other things to consider:
To block two programs from accessing a port without knowing what the other program does, this is the strategy dosemu takes:
If the strategy administrator did list ports in /etc/dosemu.conf and allows a user listed in /etc/dosemu.users to use dosemu, (s)he must know what (s)he is doing. Port access is inherently dangerous, as the system can easily be screwed up if something goes wrong: just think of the blank screen you get when dosemu crashes without restoring screen registers...
Next Previous Contents
|The DOSEMU team|