P8000/WEGA/src/uts/dev/chardev.c

317 lines
7.4 KiB
C

/**********************************************************
*
* Rahmenprogramm fuer Charactergeraet
*
*********************************************************/
#include "sys/param.h"
#include "sys/tty.h"
#include "sys/sysinfo.h"
#include "sys/systm.h"
#include "sys/dir.h"
#include "sys/state.h"
#include "sys/mmu.h"
#include "sys/s.out.h"
#include "sys/user.h"
/**************************************************
* Geraete-abhaengige Definitionen
**************************************************/
/* Fehlermaske */
#define U1ERROR 0x8000
/* Maske, wenn Uebertragung OK */
#define U1OK 0x0000
/* Uebertragungsrichtung */
#define DIRECTION 0x7000
#define OUTPUT 0x4000
#define INPUT 0x2000
/* maximale Anzahl der Zeichen in der Ausgabeschlange,
* bevor der Prozess schlafen geschickt wird */
#define U1HIWATER 100
/*der Anzahl der Zeichen, wenn der Prozess wieder geweckt
* wird */
#define U1LOWATER 10
/* flag, wenn der Prozess schlaeft */
#define U1ASLEEP 1 /* fuer Ausgabe */
#define U1ISLEEP 2 /* fuer Eingabe */
/* Prioritaet fuer wakeup */
#define U1PRI 45
/* U1HOG ist ein Begrenzer, wenn mehr als U1HOG Zeichen in
* der Eingabeschlange enthalten sind (Zeichen empfangen,
* Prozess hat sie aber nicht abgeholt) werden alle Zeichen
* in der Eingabeschlange geloescht */
#define U1HOG 200
/**************************************************
* Deklaration von Symbolen
**************************************************/
/* Header fuer Ein- und Ausgabeschlange */
struct clist u1_inq, u1_outq;
/* Status-Flag */
unsigned int u1flag;
extern int last_int_serv;
/**************************************************
* Interrupt-Routine
**************************************************/
u1int(s)
register struct state *s;
{
register char c;
last_int_serv = USR1INT;
if ((s->s_eventid & U1ERROR) == U1OK) {
/* U1ERROR ist eine Geraete-abhaengige Maske fuer das
* obere Byte von s_eventid (falls der Status im
* oberen Teil des Int-Vektors enthalten ist) */
switch (s->s_eventid & DIRECTION) {
/* Diese Int-Routine behandelt Ein- und
* Ausgabe-Interrupts */
case OUTPUT:
/* Ausgabe Zeichen erfolgt, neues Zeichen
* kann ausgegeben werden */
/**************************
* Geraete-spezifischer Kode
* Reset Int (reti)
**************************/
u1start();
/* Die Ausgabe des naechsten Zeichens laeuft nun,
* falls noch Zeichen auszugeben waren
* Es wird nun ueberprueft, ob der Prozess
* geweckt werden muss */
if ((u1_outq.c_cc <= U1LOWATER)
&&(u1flag & U1ASLEEP)) /*schlaeft er ?*/
{
u1flag &= ~U1ASLEEP;
wakeup(&u1_outq); /*Prozess wecken*/
}
return;
case INPUT:
/***************************************
* Geraete-spezifischer Kode
* ein Zeichen vom Geraet nach c einlesen
***************************************/
/* zu viele Zeichen im Eingabepuffer? */
if (u1_inq.c_cc > U1HOG) {
/* ja, loeschen aller Zeichen */
while(u1_inq.c_cc) {
getc(&u1_inq);
}
return;
}
/* Zeichen in Eingabepuffer eintragen */
putc(c, &u1_inq);
/* Prozess wecken, falls er schlaeft */
if (u1flag & U1ISLEEP) {
u1flag &= ~U1ISLEEP;
wakeup(&u1_inq); /*Prozess wecken*/
}
/**************************
* Geraete-spezifischer Kode
* Reset Int (reti)
**************************/
return;
}
}
else { /* Uebertragungsfehler */
printf("Descriptive message\n");
/************************************
* Geraete-abhaengige Fehlerbehandlung
* und Reset Int (reti)
************************************/
return;
}
}
/**************************************************
* Open-Routine
**************************************************/
/* Dummy-Definition zur Ueberpruefung der Minor-Nummer */
#define INVALID(n) (n<0 || n>2)
u1open(dev)
dev_t dev; /* dev_t ist eine typedef*/
{
register int minordev; /*local Minor-Nummer*/
static int u1first = 0; /*zur einmaligen Ausfuehrung*/
minordev = minor(dev);
if (u1first++ == 0) {
/******************************************
* Geraete-spezifischer Kode, der nur einmal
* ausgefuehrt wird
******************************************/
}
/* Hier kann auch eine Verriegelung des Treibers zur
* Verhinderung einer gleichzeitigen mehrfachen
* Benutzung eingebaut werden */
/* Ueberpruefung der Minor-Nummer */
if (INVALID(minordev)) {
u.u_error = ENXIO; /* Fehler */
return;
}
}
/**************************************************
* Close-Routine
**************************************************/
u1close(dev)
dev_t dev;
{
/**************************
* Geraete-abhaengiger Kode
*************************/
}
/**************************************************
* Read-Routine
**************************************************/
u1read(dev)
dev_t dev;
{
/* Zeichen von der Eingabeschlange einlesen, bis diese
* leer ist oder der Prozess keine Zeichen mehr haben
* will */
/*Disable Ints, weil wir in die Eingabeschlage sehen */
dvi();
/* Zeichen in der Eingabeschlange ? */
while(u1_inq.c_cc == 0) {
/* nein, sleep bis Zeichen da */
sleep(&u1_inq, U1PRI);
}
evi();
/* Zeichen sind da, auslesen */
while (u1_inq.c_cc && passc(getc(&u1_inq)) >= 0)
;
return;
}
/**************************************************
* Write-Routine
**************************************************/
u1write(dev)
dev_t dev;
{
register char c;
while (u.u_count) { /* fuer jedes Zeichen des
* Write-Calls */
dvi();
/* zu viele Zeichen in der Ausgabeschlange ? */
while (u1_outq.c_cc > U1HIWATER) {
/* ja, Ausgabe starten und sleep */
u1start();
u1flag |= U1ASLEEP;
sleep(&u1_outq, U1PRI);
}
evi();
/* naechstes Zeichen vom User-Prozess holen */
if ((c = cpass() ) < 0)
break; /* alles ausgegeben */
/* Zeichen in Ausgabeschlange bringen */
putc(c, &u1_outq);
}
/* Start der Ausgabe */
u1start();
}
/**************************************************
* I/O-Control-Routine
**************************************************/
u1ioctl(dev, cmd, arg_addr, flag)
dev_t dev;
int cmd; /*Kommando*/
caddr_t arg_addr; /*Adresse vom Argument-Block*/
int flag; /*Kopie des Open-Mode-Flags*/
{
struct u1ioct1b {
int device_specific;
}u1ioct1b;
/* Dieses sind Dummy-Definitionen */
#define CMD1 1
#define CMD2 2
switch (cmd) {
case CMD1: /* Geraete-spezifisch */
/* Dies ist ein typisches Fragment zum Setzen
* der Parameter */
if (copyin(arg_addr, (caddr_t)&u1ioct1b,
sizeof (u1ioct1b)))
{
u.u_error = EFAULT; /* Fehler bei copyin */
break;
}
/****************************************
* Geraete-spezifische Interpretation vom
* u1ioct1b Inhalt
***************************************/
break;
case CMD2:
/* typisches Fragment zum Lesen der Parameter*/
if (copyout(arg_addr, (caddr_t)&u1ioct1b,
sizeof(u1ioct1b)))
{
u.u_error = EFAULT;
}
break;
default:
u.u_error = EINVAL;
break;
}
return;
}
/**************************************************
* Start-Routine
**************************************************/
u1start()
{
char c;
/* Zeichen von Ausgabeschlange einlesen */
c = getc(&u1_outq);
/*********************************
* Geraete-spezifischer Ausgabekode
* sende Zeichen in c zum Geraet
*********************************/
}