[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: external device drivers



Hello Brad,

> I am trying to write an external device driver for the
> Mac port of MiNT, but I am unclear on the use of wake
> and sleep (among other things).  I would like to have
> a device that other Mac applications can send data
> to and have the device pass that data on to a mint
> program when it is read.  My first question is: does
> this device have to be a TTY device?  I thought the
> answer was yes, because the kernel had built in support
> for putting a process to sleep if it tried to read a TTY
> device with no data available, but now I'm not sure.  When

If you only intend to use the driver in RAW mode (a printer for
instance), it's not necessary to declare it as a TTY device. On the
other hand, if you need terminal handling services (line discipline,
XON/XOFF, signals), you'll have to define it as a TTY device; a typical
example is a serial line driver. The services above (CBREAK mode) are
provided by the kernel, so in theory you don't have to care about them.
(In fact, you have to; see below.)

> I thought the kernel would automatically put a process to
> sleep I though that the only sleep/wake call I would need
> was a call to wakeselect in the routine that is called when
> data arrives from another Mac application.  Now I am thinking
> that I might need to call sleep in the read routine, but I don't
> know which queue or condition to sleep on.  I also don't know
> if I need to change the wake call in the data ready routine
> depending on whether I am sleeping because of a select call
> or a read call.

The simplest (and for now, unique) way to handle this situation is to
wait for incoming characters in a small loop in your read() routine. If
you don't want this loop to eat too much CPU time, insert a
nap() or yield() instruction inside.

Of course, it would be much more elegant to bring the process to
sleep(). But who will wake it again? You obviously need another thread
of execution to wait for incoming characters (and for other tasks of
supervision) and wake it up; ideally, this thread should execute in
kernel mode so that one can invoke wake() (which is a kernel call). 
If Kai Roemer's proposition of adding addroottimeout() to MiNT 1.11 is
adopted, this would be possible; for now, it isn't.

> If anybody has any ideas on this, or some source code, or some
> pointers to documentation, I would like to hear about it.  I
> have read parts of the modem driver and the raw disk driver
> on atari.archive but this stuff still doesn't quite make sense
> to me.

Examine the 'clockdev' device included in early MiNT distributions. The
raw disk device driver is simple, too: in both cases, the read() and
write() operations will never block.

The modem driver is certainly not the simplest one, unfortunately. 
There is a big problem with the way MiNT considers device drivers; they
are invoked only when the user wants to issue a read/write operation.
Suppose you are remotely logged, and you spawn a program like this one:

  main()  { while(1); }

You'll never be able to kill this process, no matter how hard you press
^C or ^\. Since the program does no I/O, the device driver functions
(read/write) will never be called. If they were called, the kernel would
notice the incoming ^C character and kill the process; unfortunately,
they aren't.

This "synchronous" interface to the driver complicates things
tremendously, because you have to create a new thread of execution
where, among other things, you handle ^C/^S/^Q just like the kernel
would (if it could see them!!)

Thierry.