/*
 * pseudocode for Unix char device driver
 *
 * This might be a console device or a multiplexed rs-232 device.
 */

#define CONSADDR	((struct consdev *) 0160100)

struct consdev {
	int csr;	/* control status register */
	unsigned char transmit; /* output register */
	unsigned char recieve;  /* input register */
};

/* tty structures managed by this device driver
*/
struct tty conttys[SOMENUMBER];	/* as many as minor devices */

/*
 * open the device. May sleep if something like
 * carrier needs to change state; i.e., hang
 * in device open call (could happen in read too).
 *
 * May be called multiple times.
 */
conopen(dev, flag)
DEVICE dev;
int flag;
{
	.check minor dev value to make sure it makes sense
	.map minor device to local tty structure
	.do any local tty structure init
		.e.g, set "output" start procedure
	.if state indicates NOT open
		.set more tty defaults; e.g., state is not ISOPEN
		.may block and wait for carrier 
		.state is ISOPEN
		.set up device hardware (baud rate...)
		.init tty default characters (e.g., control-s)
	.else might be error if not root or exclusive use device
		u.u_error = EBUSY;
	call line discipline ttyopen(dev, &tty pointer)
		line discipline will finish tty struct init
}

/*
 * called on last close of device.
 */
conclose(dev, flag)
DEVICE dev;
int flag;
{
	.map device to tty structure
	.do any local cleanup if any
		(typically none).
	.call line discipline tty_close to clean up 
		tty structure and queue's. queue flushing is of
		concern.
}

/*
 * called from read-side. Doesn't do much
 */
conread(dev)
{
	map device to tty
	call line discipline read (ttread(&tty pointer))
}

conwrite(dev)
{
	map device to tty
	call line discipline write (ttwrite(&tty pointer))
}

/*
 * ioctl calls. System ioctl will jump to this
 * routine. this routine calls common tty code first.
 */
conioctl(dev, cmd, addr, flag)
DEVICE	dev;
int cmd;
ADDRESS addr;
{
	call ttioctl() tty line discipline common ioctl routine
		to handle common ioctl calls.
		if call indicates hardware changes
			(e.g., was TIOCCSETP or TIOCSETN (Berkeley))
			make local hardware changes (change baud rate).
	else if call failed
		error
			u.u_error = ENOTTY... 
]

/*
 * receiver interrupt routine
 * Characters are coming in.
 */
conrintr(dev)
int flag;
{
	.may need to map device to physical address
		of registers
	.map device to tty structure
	.may need to wakeup someone sleeping on a open
	.get char c from receiver register
	.may do some minimal processing (e.g., parity)
	.put intput char in input queue via line discipline call
		ttyinput(c, tp);
}

/*
 * transmit interrupt routine.
 * Characters are going out.
 */
contintr(dev)
{
	.may need to map device to physical address
		of registers
	.map minor device to tty structure

	/* we may need protection against various interrupt
	 * related troubles such as trying to output chars
	 * when we are logically stopped...
	 */
	if device is tied up somehow (BUSY | STOPPED)
		return

	if write is sleeping on output overflow, wake him up
		tty state is not asleep
		wakeup

	if no chars to output
		return

	if any chars to output
		use putc to get from queue
		write them out to hardware
}

/*
 * may need start routine so that tty driver can
 * start output if for example output queue has drained.
 * Or just to get i/o going in general. 
 */
constart()
{
}

/*
 * may have local internal routine for changing hardware
 * parameters like baud rate.
 */
conparam()
{
}

/*
 * may have stop routine so that tty driver can
 * issue stop to driver on receiving logical stop char.
 */
constop()
{
}

/*
 * console will have local polled putchar() 
 * used by internal printf for printing kernel
 * messages; e.g., panics. Famous "not for chitchat"
 * derives from this. 
 */
putchar(c)
{
	.setup hardware for output of one char
	.write c to transmit register
	.wait for status register to signal done (busy loop)
}
