/*
 * Memory special file
 *	minor device 0 is physical memory
 *	minor device 1 is kernel memory
 *	minor device 2 is EOF/BITBUCKET
 *	minor device 3 is 3200 series memory error logger
 *	any other minor device number acts like 2 (null).
 */

/*** Rewritten for Interdata 7-8/32
 *** Code is made simpler (and less portable!) by the assumption
 *** that all physical memory is contiguous and directly addressable.
 ***/

#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/conf.h"
#include "../h/seg.h"

int	mmelog	=	0;


mmopen(dev)
dev_t dev;
{
	switch (minor(dev))  {

		case 0:
		case 1:
		case 2:
			break;

		case 3:
			if (mmelog)
				u.u_error = EBUSY;
			else
				mmelog = 1;
			break;

		default:
			u.u_error = ENXIO;
			break;
		}

	return;
}

mmclose(dev)
dev_t dev;
{
	switch (minor(dev))  {
		case 0:
		case 1:
		case 2:
		default:
			break;

		case 3:
			mmelog = 0;
			break;
		}

	return;
}

mmread(dev)
dev_t dev;
{
	register int i;
	register int c;
	caddr_t  addr;

	switch (minor(dev))  {

		case 0:
		case 1:
			do {
				addr = u.u_offset;
				if ((minor(dev) == 1 && lraddr(&addr, kisa))
				    || addr >= memtop)
					break;
			} while(u.u_error==0 && passc(*addr) >= 0);
			break;

		case 2:
		default:
			break;

		case 3:
			if (u.u_count != 1024)  {
				u.u_error = ENXIO;
				break;
				}

			addr = 0;
			for (i=0; i<512; i++)  {
				c = rel(addr);
				if (passc(c>>8) < 0  ||  passc(c & 0xff) < 0)
					break;

				addr += 0x2000;
				}

			break;
		}

	return;
}

mmwrite(dev)
dev_t dev;
{
	caddr_t addr;
	register c;

	switch (minor(dev))  {

		case 0:
		case 1:
			for (;;) {
				addr = u.u_offset;
				if ((c=cpass())<0 || u.u_error!=0)
					break;
				if ((minor(dev) == 1 && lraddr(&addr, kisa))
				    || addr >= memtop)
					break;
				*addr = c;
			}
			break;

		case 2:
		default:
			c = u.u_count;
			u.u_count = 0;
			u.u_base += c;
			u.u_offset += c;
			break;

		case 3:
			break;
		}

	return;
}

mmioctl()
{
	u.u_error = ENXIO;
}
