[comp.sys.ibm.pc] ioctl on msdos device drivers

martyl@rocksvax.UUCP (04/04/87)

I just wrote a COM port device driver which buffers both input and output.

I typically use my PC through the RS-232 interface and have a window on
my 6085 to communicate with the PC.  What I want to know is:

How do IOCTL really work?  I've looked in the DOS technical reference
and a number of books, and the general consensus on ioctl seems to be 
"you can send magic bytes to/from device drivers".

Is there any spec on what magic byte operations are supported?

I'm aware of an ioctl function in MSDOS (function 44H).  But how to I
figure out which features are interpreted by msdos and which are 
interpreted by the driver?

What are want to do is be able to turn raw mode on and off (so it can either
understand XON/XOFF or not).  There is a binary bit, but it is defined as
checking for cntl-Z.

I've been able to use this driver to figure out what MS-DOS does (by 
blasting information out to the monitor ram).  However, I'd rather have
a spec I can make sense out of than have to impirically figure out what the
OS does.

Thanks --

marty leisner
xerox corp.
leisner.henr@xerox.com
martyl@rocksvax.uucp

scott@hpcvck.UUCP (04/10/87)

I would also be interested in what people have to say about
setting ioctl for devices like printers.  I have been trying
to write a graphics dump routine for my MSDOS computer (not IBM
compatible), and was having trouble.  I was opening the printer
as a binary device, but MSDOS was *not* treating like a binary
device/file.  If I wrote the info to a file first, then did
COPY <fname> PRN: /B, it printed the info fine.

I am mainly interested in setting devices to raw/cooked mode from
C.  Any help would be appreciated.

Scott Linn
hplabs!hp-pcd!scott

connery@bnrmtv.UUCP (04/12/87)

> I would also be interested in what people have to say about
> setting ioctl for devices like printers.  I have been trying
> to write a graphics dump routine for my MSDOS computer (not IBM
> compatible), and was having trouble.  I was opening the printer
> as a binary device, but MSDOS was *not* treating like a binary
> device/file.  If I wrote the info to a file first, then did
> COPY <fname> PRN: /B, it printed the info fine.
> 

	void SetRaw(fd)
	int fd;
	{
	   union REGS r;

	   r.h.ah = 0x44;
	   r.x.bx = fd;
	   r.h.al = 0;
	   intdos(&r, &r);

	   if (r.x.dx & 0x80) {
		r.h.ah = 0x44;
		r.x.bx = fd;
		r.h.al = 1;
		r.x.dx |= 0x20;
		r.x.dx &= 0xFF;
		intdos(&r, &r);
	   }
	}

Basically, this just sets raw if the handle passed is a device, and sets
raw mode if it is.  Works fine on network devices too.
-- 

Glenn Connery, Bell Northern Research, Mountain View, CA
{hplabs,amdahl,3comvax}!bnrmtv!connery

dan@srs.UUCP (04/13/87)

> I would also be interested in what people have to say about
> setting ioctl for devices like printers.  I have been trying
> to write a graphics dump routine for my MSDOS computer (not IBM
> compatible), and was having trouble.  I was opening the printer
> as a binary device, but MSDOS was *not* treating like a binary
> device/file.  If I wrote the info to a file first, then did
> COPY <fname> PRN: /B, it printed the info fine.
> I am mainly interested in setting devices to raw/cooked mode from
> C.  Any help would be appreciated.
> 
> Scott Linn
> hplabs!hp-pcd!scott

Exactly my experience.

(The /b option on copy is also useful for blasting text files to the screen
 because, in RAW mode, DOS sends the entire write request to the device
 rather than breaking it up into single bytes as it does in cooked mode.)

Here follows Microsoft C code for setting handles to raw mode.
It was posted in February, but merits reposting.

- Dan Kegel

/*--- rawmode.c -------------------------------------------------
  Routines to set and reset raw mode for Microsoft C.
  Stolen from the sources to the mighty game Hack.
  Thanks to Mark Zbikowski (markz@microsoft.UUCP).

  Applications should set stdout to raw mode when they start up, and set 
  it back to the old mode when terminating.  
  Programs which rely on cooked mode will appear to hang in raw mode because, 
  in raw mode, keyboard reads don't terminate when the user hits ENTER; they 
  continue until the line buffer is full.
------------------------------------------------------------------*/
#include <dos.h>
#include <stdio.h>

#define DEVICE		0x80
#define RAW		0x20
#define IOCTL		0x44
#define STDIN		fileno(stdin)
#define STDOUT		fileno(stdout)
#define GETBITS		0
#define SETBITS		1

static unsigned	old_stdin, old_stdout, ioctl();

#define BREAKCHECK	0x33

static unsigned old_breakchk, breakctl();

/*---- SetHandleRaw -----------------------------------------------------
Given any file handle, sets it into raw mode.  Useful when opening handles
to printers, COM ports, etc., as it lets you output ^Z chars without fear.
-------------------------------------------------------------------------*/
void
SetHandleRaw(handle)
short handle; 
{ 
    int temp;
    temp = ioctl(handle, GETBITS, 0);
    if (temp & DEVICE)
	ioctl(handle, SETBITS, temp | RAW);
}

/*---- rawgetchar ---------------------------------------------------
Read a character from keyboard with neither echo nor ^C-checking.
Used by editors, etc., which can't afford to let themselves be killed by the
user, or who want to use ^C for a function key.
----------------------------------------------------------------------*/
int
rawgetchar()
{
    return (0xff & bdos(7, 0, 0));
}

/*--- set_raw ---------------------------------------------------------
  Call this to set raw mode; call restore_raw() later to restore
  console to old rawness state.  (Don't strand user in RAW mode!)
  Not only sets raw mode, but also turns off ^C trapping on random DOS calls.
  All character input from stdin should be done with rawgetchar() to
  avoid ^C trapping on input.
-----------------------------------------------------------------------*/
set_raw()
{
	old_stdin = ioctl(STDIN, GETBITS, 0);
	old_stdout = ioctl(STDOUT, GETBITS, 0);
	old_breakchk = breakctl(GETBITS, 0);
	if (old_stdin & DEVICE)
		ioctl(STDIN, SETBITS, old_stdin | RAW);
	if (old_stdout & DEVICE)
		ioctl(STDOUT, SETBITS, old_stdout | RAW);
	(void) breakctl(SETBITS, 0);
}

restore_raw()
{
	if (old_stdin)
		(void) ioctl(STDIN, SETBITS, old_stdin);
	if (old_stdout)
		(void) ioctl(STDOUT, SETBITS, old_stdout);
	if (old_breakchk)
		(void) breakctl(SETBITS, old_breakchk);
}

static unsigned
ioctl(handle, mode, setvalue)
unsigned setvalue;
{
	union REGS regs;

	regs.h.ah = IOCTL;
	regs.h.al = mode;
	regs.x.bx = handle;
	regs.h.dl = setvalue;
	regs.h.dh = 0;			/* Zero out dh */
	intdos(&regs, &regs);
	return (regs.x.dx);
}

/* Controls ^C - checking during everything except keyboard reads */
static unsigned
breakctl(mode, setvalue)
unsigned setvalue;
{
	union REGS regs;

	regs.h.ah = BREAKCHECK;
	regs.h.al = mode;
	regs.h.dl = setvalue;
	intdos(&regs, &regs);
	return (regs.x.dx & 0xff);
}

/*------ end of rawmode.c ----------------------------------------------*/

psfales@ihlpl.UUCP (04/14/87)

In article <4490002@hpcvck.HP>, scott@hpcvck.HP (Scott Linn) writes:
> I would also be interested in what people have to say about
> setting ioctl for devices like printers.  I have been trying
> to write a graphics dump routine for my MSDOS computer (not IBM
> compatible), and was having trouble.  I was opening the printer
> as a binary device, but MSDOS was *not* treating like a binary
> device/file.  If I wrote the info to a file first, then did
> COPY <fname> PRN: /B, it printed the info fine.

I don't know about your particular C compiler, but I just discovered
a couple of days ago how to do it en ECO-C88.  It turns out that most
of the stuff you want binary mode for (CR to CR/NL translation, 8th bit
stripping, etc.) is handled by the compiler library read and write
routines.  For files opened by the program, the file may be opened in
binary mode, but for the preopened files like stdin and stdout you
don't have this choice.   There are a set of flags in the file descriptor
that the read and write routines look at to determine what modes are
currently in effect.  In my case, I can change stdout to binary mode
by setting stdout->_flag |= _BFLAG.   

Note that this has works independently of the driver RAW mode.

In your case, I suspect the write routines are buggy and are still
performing some translations even though the file is asked to be open in
raw mode.   Do you have access to another compiler?

-- 
Peter Fales		UUCP:	...ihnp4!ihlpl!psfales
			work:	(312) 979-7784
				AT&T Information Systems, IW 1Z-243
				1100 E. Warrenville Rd., IL 60566

psfales@ihlpl.UUCP (04/14/87)

Sorry about letting my chauvinsim show through - I just noticed
that the original poster never mentioned what language he was using.

So in my response:
 
s/C compiler/compiler/g

-- 
Peter Fales		UUCP:	...ihnp4!ihlpl!psfales
			work:	(312) 979-7784
				AT&T Information Systems, IW 1Z-243
				1100 E. Warrenville Rd., IL 60566

scott@hpcvck.HP (Scott Linn) (04/20/87)

Thanks for all the help regarding devices and raw mode.  The two code
fragments worked fine on my Datalight C compiler.  My original problem
was with the Mix C compiler, but it seems that the raw/cooked problem
lies with the *compiler* rather than the printer mode.  If anyone has
any experience with raw/cooked mode and the Mix C compiler, let me know.

Mix C writes to disk files okay in raw or cooked mode, but it seems to
treat the printer as always being in cooked mode, even after using a
dos call to set raw mode (as in the posted examples).  I have simply
resorted to using the Datalight compiler for this particular
application.

Thanks again!

Scott Linn
hplabs!hp-pcd!hpcvck!scott