SRI-NOSC/new/dist.ufmt
<File 1>
h/filsys.h
1221
/*
* Definition of the unix super block.
* The root super block is allocated and
* read in iinit/alloc.c. Subsequently
* a super block is allocated and read
* with each mount (smount/sys3.c) and
* released with unmount (sumount/sys3.c).
* A disk block is ripped off for storage.
* See alloc.c for general alloc/free
* routines for free list and I list.
*/
struct filsys
{
int s_isize; /* size in blocks of I list */
char *s_fsize; /* size in blocks of entire volume */
int s_nfree; /* number of in core free blocks (0-100) */
int s_free[100]; /* in core free blocks */
int s_ninode; /* number of in core I nodes (0-100) */
int s_inode[100]; /* in core free I nodes */
char s_flock; /* lock during free list manipulation */
char s_ilock; /* lock during I list manipulation */
char s_fmod; /* super block modified flag */
char s_ronly; /* mounted read-only flag */
int s_time[2]; /* current date of last update */
int pad[50];
/*PWB int pad[40];
/*PWB char *s_tfree; /* total free blocks available */
/*PWB char *s_tinode; /* total free inodes available */
/*PWB char s_fname[6]; /* name of the file system */
/*PWB char s_fpack[6]; /* name of the pack (pack ID) */
};
<File 1>
h/systm.h
2328
/*
* Random set of variables
* used by more than one
* routine.
*/
#ifdef CMAPSIZ
int coremap[CMAPSIZ]; /* space for core allocation */
#endif CMAPSIZ
#ifdef SMAPSIZ
int swapmap[SMAPSIZ]; /* space for swap allocation */
#endif SMAPSIZ
int *rootdir; /* pointer to inode of root directory */
int cputype; /* type of cpu =40, 45, or 70 */
int execnt; /* number of processes in exec */
int lbolt; /* time of day in 60th not in time */
int time[2]; /* time in sec from 1970 */
/*
* The callout structure is for
* a routine arranging
* to be called by the clock interrupt
* (clock.c) with a specified argument,
* in a specified amount of time.
* Used, for example, to time tab
* delays on teletypes.
*/
struct callo
{
int c_time; /* incremental time */
int c_arg; /* argument to routine */
int (*c_func)(); /* routine */
};
#ifdef NCALL
struct callo callout[NCALL];
#endif NCALL
/*
* Mount structure.
* One allocated on every mount.
* Used to find the super block.
*/
struct mount
{
int m_dev; /* device mounted */
int *m_bufp; /* pointer to superblock */
int *m_inodp; /* pointer to mounted on inode */
#ifdef UCBUFMOD
int m_isize; /* incore copy of s_isize */
char *m_fsize; /* incore copy of s_fsize */
int m_nfree; /* incore copy of s_nfree */
int m_ninode; /* incore copy of s_ninode */
char m_flock; /* lock during free list manipulation */
char m_ilock; /* lock during I list manipulation */
char m_fmod; /* super block modified flag */
char m_ronly; /* mounted read-only flag */
/*PWB char *m_tfree; /* total free blocks available */
/*PWB char *m_tinode; /* total free inodes avaliable */
#endif UCBUFMOD
};
#ifdef NMOUNT
struct mount mount[NMOUNT];
#endif NMOUNT
char runin; /* scheduling flag */
char runout; /* scheduling flag */
char runrun; /* scheduling flag */
char curpri; /* more scheduling */
int maxmem; /* actual max memory per process */
int *lks; /* pointer to clock device */
int rootdev; /* dev of root see conf.c */
int swapdev; /* dev of swap see conf.c */
int swplo; /* block number of swap space */
int nswap; /* size of swap space */
int updlock; /* lock for sync */
int rablock; /* block to be read ahead */
char regloc[]; /* locs. of saved user registers (trap.c) */
<File 1>
ncpk/drivers/vdh.c
9718
#include "param.h"
#include "buf.h"
#include "net_net.h"
#include "net_netbuf.h"
#include "net_ncp.h"
#include "net_vdhstat.h"
#include "net_vdh_imp.h"
#include "net_vdh.h"
char vdhlock -1;
v_pan (msg)
char *msg;
{
register t;
struct vdhregs sv_regs;
register int *p, *q;
t = PS->integ;
spl7();
p = &sv_regs.wco; q = &VDH->wco;
do { /* save registers at time of panic */
*p-- = *q--;
} while q >= &VDH->csri;
VDH->csri =& ~ V_INTENB;
VDH->csro =& ~ (V_INTENB|V_TIMRUN);
panic (msg);
}
imp_init ()
{
register t, *ptr;
register int oldps;
oldps = PS->integ;
spl_imp ();
vdhichn = 0;
prvictl = 0;
vstatebits = VDHILAST;
impldrd ();
hellonext = 2*VDH_T*VDH_R;
vdhosnd = -1;
vdhofill = 0;
vdhoack = V_HTOI;
for(t = 0; t < NCHNS; t++)
vdhouse[t] = -1;
ptr = &VDH->csro;
if ((*ptr & V_INTENB) == 0)
{
*ptr++ = V_TIMSEL;
*ptr = 12500/(HZ/10); /* 125000 too big for one word */
*--ptr = V_TIMRUN | V_INTENB;
}
oimp.o_type = ih_nop;
for ( t = 3; --t>=0; )
sndnetbytes (&oimp,4,0,0,1);
PS->integ = oldps;
}
#ifndef UCBUFMOD
imp_output()
{
#endif UCBUFMOD
#ifdef UCBUFMOD
imp_output(msg)
struct netbuf *msg;
{
register sps;
sps = PS->integ;
spl_imp();
msg_q(&impoq, 0, 0, msg);
#endif UCBUFMOD
if (((vstatebits ^ UP) & (OUTBUSY|UP)) == 0)
{
vdhostart ();
}
#ifdef UCBUFMOD
PS->integ = sps;
#endif UCBUFMOD
}
vdhiint ()
{
register int t;
register int *p;
register int *state;
int *q;
int xorrot;
if (++vdhlock)
v_pan ("VDH-i");
#ifdef PARANOID
v_bufck ();
#endif PARANOID
state = &vstatebits;
p = &VDH->csri;
#ifndef VDHE
while ( (*p ^ V_GO) & (V_EOT|V_GO) ) {
#endif not VDHE
#ifdef VDHE
while (*p & V_EOT) {
#endif VDHE
if (!(*state & TRYING)) {
VDH->csri =& ~ V_INTENB;
goto finis;
}
if (*p<0) {
vs.harderr++;
vdherr = *p;
goto eot_done;
}
p = (*state&VDHIAB) ? &vdhibuf[1][0]:&vdhibuf[0][0];
if ((t = (VDH->cwai - p) - 1) < 0) { /* null transfer */
wcerr:
/* log some error? */
goto eot_done;
}
if (*p & V_HTOI) {
vs.looped++;
goto eot_done;
}
if (*p & V_SPBIT) {
if (t != 0) goto wcerr;
if (*p>0) {
*state =| (SAWHELLO|OUT2GO);
} else {
hellounacked = 0;
helloinarow++;
}
goto eot_done;
}
if (t != (p->hibyte&077)) goto wcerr;
if (!(*state & UP)) {
vs.wpaks++;
goto eot_done;
}
xorrot = (prvictl ^ *p) << (14-NCHNS);
t = NCHNS-1;
do {
if (xorrot<0) {
vdhouse[t] = -1;
*state =| OUT2GO;
}
xorrot =<< 1;
} while (--t>=0);
prvictl = *p;
if ((*p & V_WCBITS)==0) {
vs.inulls++;
goto eot_done;
}
*state =| (ACK2SND|OUT2GO);
if ((t = *p & V_CHBITS) != vdhichn) {
vs.chwrong++;
goto eot_done;
}
if ((*p ^ ((vdhoack>>t)*(V_EVNODD/V_C0ACK)))
& V_EVNODD) {
vs.idups++;
goto eot_done;
}
if (*state & VDHILAST) {
wakeup ( &imp );
vs.ifull++;
goto eot_done;
}
if (net_b.b_cntfree < (VDHDSIZE + NET_B_SIZE - 1)/NET_B_SIZE) {
vs.nobuf++;
*state =| VDHINEED;
wakeup (&imp);
goto eot_done;
}
t = (p++->hibyte & 077);
swabuf (p,t);
t =<< 1;
if (impi_msg==0) {
q = impleader ? &imp.type : &imp.pad1;
t =- 4;
*q++ = *p++;
*q = *p++;
}
if (t && vectomsg (p,t,&impi_msg,1))
v_pan ("vdh: vectomsg failed");
impleader = 0;
vdhoack =^ V_C0ACK<<vdhichn;
if (prvictl & V_LAST) {
#ifdef PARANOID
v_bufck();
#endif PARANOID
*state =| VDHILAST;
wakeup (&imp);
}
vdhichn++;
vdhichn =& NCHNS-1;
vs.igood++;
eot_done:
p = &VDH->csri;
VDH->cwai = (*state&VDHIAB)?&vdhibuf[1][0]:&vdhibuf[0][0];
#ifndef VDHE
VDH->wci = VDHSIZE;
do {
*p =| V_GO;
} while !(*p&V_GO);
#endif not VDHE
#ifdef VDHE
VDH->wci = -(VDHSIZE*2);
*p =| V_GO;
#endif VDHE
*state =^ VDHIAB;
*p = (*state&VDHIAB) ? (V_ABSEL | V_INTENB) : V_INTENB;
}
if (((*state ^ OUT2GO) & (OUT2GO|OUTBUSY)) == 0) {
vdhostart();
}
*state =& ~OUT2GO;
finis:
#ifdef PARANOID
v_bufck ();
#endif PARANOID
--vdhlock;
}
vdhoint ()
{
register *p;
register xorrot;
register *state;
if (++vdhlock)
v_pan ("VDH-o");
state = &vstatebits;
if (VDH->csro&V_TIMINT)
{
VDH->csro =& ~ V_TIMINT;
#ifdef NOCLOCK
*state =| CLOCKINT;
#endif NOCLOCK
if (ncpopnstate == 0)
{
*state =& ~(UP | TRYING);
goto clock_done;
}
for(xorrot = 0; xorrot < NCHNS; xorrot++)
if(vdhouse[xorrot] > 0)
vdhouse[xorrot]--;
if (--hellonext > 0)
goto clock_done;
hellonext =+ VDH_R;
switch (*state & (UP | TRYING))
{
case UP|TRYING:
if (hellounacked > VDH_T)
{
*state =& ~(TRYING | UP);
hellonext = 077777;
needinit++;
wakeup ( &imp );
goto clock_done;
}
break;
case TRYING:
if (hellounacked)
{
helloinarow = 0;
}
else
if (helloinarow >= VDH_K)
{
*state =| UP;
wakeup ( &imp );
}
break;
default:
*state =| TRYING;
*state =& ~(SAWHELLO | SENDHELLO | UP);
#ifndef VDHE
VDH->csri = 0;
VDH->cwai = &vdhibuf[0][0];
VDH->wci = VDHSIZE;
VDH->csri = V_GO | V_ABSEL;
VDH->cwai = &vdhibuf[1][0];
VDH->wci = VDHSIZE;
VDH->csri = V_INTENB | V_GO;
#endif not VDHE
#ifdef VDHE
VDH->csri = 0;
VDH->cwai = &vdhibuf[0][0];
VDH->wci = -(VDHSIZE*2);
VDH->csri = V_GO;
VDH->csri =| V_ABSEL;
VDH->cwai = &vdhibuf[1][0];
VDH->wci = -(VDHSIZE*2);
VDH->csri = V_INTENB | V_GO | V_ABSEL;
VDH->csri =& ~ V_ABSEL;
#endif VDHE
}
*state =| SENDHELLO;
}
clock_done:
if (VDH->csro&V_EOTINT)
{
*state =& ~OUTBUSY;
}
if ((*state & OUTBUSY) == 0) {
vdhostart();
#ifdef PARANOID
v_bufck ();
#endif PARANOID
}
--vdhlock;
#ifdef NOCLOCK
if (*state & CLOCKINT)
{
*state =& ~CLOCKINT;
vdh_clock(); /* no return */
}
#endif NOCLOCK
}
vdhostart ()
{
register int *p;
register int i;
register int *state;
state = &vstatebits;
if ((*state & TRYING) == 0)
return;
#ifdef PARANOID
v_bufck();
#endif PARANOID
if (*state & SAWHELLO)
{
I_HEARD_YOU;
*state =& ~ SAWHELLO;
return;
}
if (*state & SENDHELLO)
{
HELLO;
hellounacked++;
*state =& ~SENDHELLO;
return;
}
if ((*state & UP) == 0)
return;
/* Proceed below if we are UP&TRYING -- I just didn't want */
/* to indent that much.... */
fillochans();
for (i = 0; i < NCHNS; i++)
{
vdhosnd++;
vdhosnd =& NCHNS-1;
if (vdhouse[vdhosnd] == 0) {
p = vdhobuf [vdhosnd];
p [0] = (p [0] & ~V_ACKBITS) | vdhoack;
vdhsnd (p);
vdhouse[vdhosnd] = HZ*100/1000; /* hold off 100 ms */
*state =& ~ACK2SND;
return;
}
}
/* No data to be sent */
if (*state & ACK2SND) { /* And an ack to send? */
OACK;
*state =& ~ACK2SND;
}
}
#ifndef UCBUFMOD
struct buf vdbuf;
#endif UCBUFMOD
#ifdef UCBUFMOD
struct netbuf *vdhmsg;
#endif UCBUFMOD
fillochans ()
{
register int *p;
register char *bp;
register int len;
while (vdhouse[vdhofill] < 0) {
#ifndef UCBUFMOD
if (vdbuf.b_dev==0)
{
bp = impotab.d_actf;
if (bp==0)
return;
impotab.d_actf = bp->b_forw;
bytesout (&bp->b_dev, &vdbuf, BUFSIZE, 1);
vdbuf.b_wcount = msglen (vdbuf.b_dev);
len = 4;
}
else
len = min (VDHDSIZE, vdbuf.b_wcount);
bytesout (&vdbuf.b_dev, p = &vdhobuf[vdhofill][1], len, 1);
vdbuf.b_wcount =- len;
if (vdbuf.b_wcount<0)
v_pan ("Bad wcount");
#endif UCBUFMOD
#ifdef UCBUFMOD
if(vdhmsg==0) { /* must pick up new message? */
if((bp = impoq) == 0) /* if nothing to output */
return; /* just go away */
bp->b_resv =| b_eom; /* so I'm paranoid */
do { /* remove first message from q */
bp = bp->b_qlink;
} while( (bp->b_resv&b_eom) == 0 );
/* now pointing at last buffer of msg */
if(bp == impoq) { /* only message in q? */
impoq = 0; /* clear q pointer */
} else {
len = impoq->b_qlink; /* use len as temp */
impoq->b_qlink = bp->b_qlink;
bp->b_qlink = len;
}
vdhmsg = bp; len = 4; /* only header in first packet */
} else
len = VDHDSIZE;
len =- bytesout(&vdhmsg, p = &vdhobuf[vdhofill][1], len, 1);
#endif UCBUFMOD
*--p = vdhofill;
len =>> 1;
p->hibyte = len;
#ifndef UCBUFMOD
if (vdbuf.b_wcount==0)
#endif UCBUFMOD
#ifdef UCBUFMOD
if (vdhmsg==0)
#endif UCBUFMOD
*p =| V_LAST;
if ( (prvictl>>vdhofill) & V_C0ACK )
*p =| V_EVNODD;
swabuf (&p[1], len);
vdhouse[vdhofill] = 0;
vdhofill++;
vdhofill =& NCHNS-1;
vs.opaks++;
}
}
#ifndef UCBUFMOD
msglen(abp) char *abp;
{
register char *bp;
register int cnt;
bp = abp;
if(bp==0) return 0;
for( cnt = bp->b_len; (bp=bp->b_qlink)!=abp; )
cnt =+ bp->b_len&0377;
return cnt;
}
#endif UCBUFMOD
impldrd ()
{
spl_imp ();
if (!(vstatebits & VDHILAST))
log_to_ncp ("Bad impldrd");
else
{
impleader = 1;
impi_msg = 0; /* can a buffer get lost here ? */
vstatebits =& ~VDHILAST;
}
}
vdh1snd (oneliner) int oneliner;
{
static vdh1buf; /* static because we dma out of here */
vdh1buf = oneliner;
vdhsnd (&vdh1buf);
}
vdhsnd (buffer) int *buffer;
{
vstatebits =| OUTBUSY;
if ((buffer[0]&V_HTOI) == 0) v_pan ("vdhsnd");
VDH->cwao = buffer;
#ifndef VDHE
VDH->wco = (buffer->hibyte & 077)+1;
#endif not VDHE
#ifdef VDHE
VDH->wco = -(((buffer->hibyte & 077)+1)<<1);
#endif VDHE
VDH->csro =& ~ V_EOTINT;
VDH->csro =| V_GO;
}
<File 1>
ken/acct.c
2235
#
#include "param.h"
#include "inode.h"
#include "user.h"
#include "acct.h"
#include "proc.h"
#ifdef ACCTSYS
int acc_lock; /* lock for exclusive use */
char accsvuid;
char accbuf [512];
char *accbufp accbuf;
char acc_vec [ACCVLEN]; /* for system users to build in */
accinput (vecaddr) /* internal form */
char *vecaddr;
{
register int n;
register char *vptr, *bptr;
acc_lock++;
while (acc_lock > 1)
sleep( &acc_lock, -1 );
bptr = accbufp;
vptr = vecaddr;
for (n=ACCVLEN; n--; *bptr++ = *vptr++);
accbufp = bptr;
accwrite ();
if (--acc_lock) signal ( &acc_lock );
}
accput () /* called via sys accput;addr;passwd */
{
register int n, t;
register char *cp;
acc_lock++;
while (acc_lock > 1)
sleep( &acc_lock, -1 );
u.u_error = 0;
if (u.u_arg[1] != ACCPSWD) {
u.u_error = EACCT;
if (--acc_lock) signal ( &acc_lock );
return;
}
cp = accbufp;
u.u_base = u.u_arg[0];
u.u_count = n = ACCVLEN;
u.u_segflg = 0; /* data from user space */
do {
if (( t = cpass () ) < 0) {
printf ("ACC cpass error \n");
}
*cp++ = t;
} while --n;
accbufp = cp;
accwrite ();
if (--acc_lock) signal ( &acc_lock );
}
accwrite ()
{
register int *ip;
extern schar ();
if (accbufp < &accbuf[sizeof accbuf - ACCVLEN])
return;
/*
* set su priv, open file, check access, and write, then reset
* su priv
*/
accsvuid = u.u_uid; /* save uid, and set su priv */
u.u_uid = 0;
u.u_error = 0; /* open file */
u.u_dirp = "/usr/lpd/logs/logfile";
ip = namei (&schar, 0); /* file must already be on disk */
if (ip == NULL)
goto out; /* else fix pointer and return */
if (( !access (ip, IWRITE)) /* su allowed to write ? */
&& (ip->i_mode & IFMT) == 0) { /* is it a data file on disk */
u.u_offset[0] = ip->i_size0; /* seek eof */
u.u_offset[1] =
ip->i_size1 & 0177000; /* force to a block boundary */
u.u_base = accbuf; /* set up for write */
u.u_count = 512;
u.u_segflg = 1; /* we are writing from sys space */
writei (ip); /* do the io */
}
iput (ip); /* close the file */
out:
u.u_uid = accsvuid; /* relinquish su priv */
u.u_error = 0;
accbufp = accbuf;
}
#endif ACCTSYS
<File 1>
ncpp/ftp-s/srvrdaemon.c
2242
# /* Server FTP daemon */
#include "net_open.h"
#define SIGINR 15
#include "spawn.c"
/*name:
srvrdaemon
installation:
if $1x = newerx goto newer
if $1e = finale goto finale
cc -L/usr/include:..:/usr/sys/ncpp srvrdaemon.c
exit
: newer
if ! { newer srvrdaemon.c /usr/net/etc/ftpsvr } exit
echo ncpp/ftp-s/srvrdaemon.c:
: finale
cc -L/usr/include:..:/usr/sys/ncpp -O -s srvrdaemon.c
if ! -r a.out exit
if ! -r /usr/sys/ncpp/ftp-s/srvrdaemon.c goto same
if { cmp -s srvrdaemon.c /usr/sys/ncpp/ftp-s/srvrdaemon.c } goto same
su cp srvrdaemon.c /usr/sys/ncpp/ftp-s/srvrdaemon.c
su chmod 444 /usr/sys/ncpp/ftp-s/srvrdaemon.c
rm -f srvrdaemon.c
: same
su rm -f /usr/net/etc/ftpsvr
su cp a.out /usr/net/etc/ftpsvr
rm -f a.out
su chmod 544 /usr/net/etc/ftpsvr
su chown root /usr/net/etc/ftpsvr
su chgrp system /usr/net/etc/ftpsvr
function:
to handle server ftp connections to socket 3 and start
up a program to handle the traffic. It was done as two
pieces to keep down the size of process waiting for connections
to open( that is a smaller program to swap in and out ).
algorithm:
forever
set up params for a server connection to socket 3
wait for a connection to complete
spawn a child process
make file desc 0 and 1 the telnet file
exec the server process
close the network file
parameters:
none
returns:
nothing
globals:
openparams=
calls:
open (sys)
fork (sys)
exec (sys)
dup (sys)
close(sys)
called by:
/etc/rc file as /etc/srvrdaemon
history:
initial coding 4/18/76 by S. F. Holmgren
*/
struct openparams openparams;
main( argc, argv )
int argc;
char **argv;
{
register netfid;
signal(SIGINR,1); /* ignore INS interrupts */
while( 1 )
{
netfid = -1;
while( netfid < 0 )
{
openparam.o_lskt = 3;
openparam.o_type = 2;
openparam.o_fskt[0] = 0;
openparam.o_fskt[1] = 0;
netfid = open( "/dev/net/anyhost",&openparam );
}
if( spawn() == 0 )
{
close( 0 );
dup( netfid );
close( 1 );
dup( netfid );
close( netfid );
execl( "/usr/net/etc/srvrftp", argv[0], "server process", 0);
exit( 1 );
}
close( netfid );
}
}
<File 1>
dmr/hp.c
4716
#
/*
*/
/*
* RP04 disk driver
*
* This driver has been tested on a working RP04 for a few hours.
* It does not attempt ECC error correction and is probably
* deficient in general in the case of errors and when packs
* are dismounted.
*/
#include "param.h"
#include "buf.h"
#include "conf.h"
#include "user.h"
struct {
int hpcs1; /* Control and Status register 1 */
int hpwc; /* Word count register */
int hpba; /* UNIBUS address register */
int hpda; /* Desired address register */
int hpcs2; /* Control and Status register 2*/
int hpds; /* Drive Status */
int hper1; /* Error register 1 */
int hpas; /* Attention Summary */
int hpla; /* Look ahead */
int hpdb; /* Data buffer */
int hpmr; /* Maintenance register */
int hpdt; /* Drive type */
int hpsn; /* Serial number */
int hpof; /* Offset register */
int hpca; /* Desired Cylinder address register*/
int hpcc; /* Current Cylinder */
int hper2; /* Error register 2 */
int hper3; /* Error register 3 */
int hppos; /* Burst error bit position */
int hppat; /* Burst error bit pattern */
int hpbae; /* 11/70 bus extension */
};
#define HPADDR 0176700
#define NHP 8
struct {
char *nblocks;
int cyloff;
} hp_sizes[] {
9614, 0, /* cyl 0 thru 23 */
/* cyl 24 thru 43 available */
-1, 44, /* cyl 44 thru 200 */
-1, 201, /* cyl 201 thru 357 */
20900, 358, /* cyl 358 thru 407 */
/* cyl 408 thru 410 blank */
40600, 0,
40600, 100,
40600, 200,
40600, 300,
};
struct devtab hptab;
struct buf hpbuf;
char hp_openf;
/* Drive Commands */
#define GO 01
#define PRESET 020
#define RECAL 06
#define RCLR 010
#define OFFSET 014
#define READY 0200 /* hpds - drive ready */
#define PIP 020000 /* hpds - Positioning Operation in Progress */
#define ERR 040000 /* hpcs1 - composite error */
#define DU 040000 /* hper1 - Drive Unsafe */
#define DTE 010000 /* hper1 - Drive Timing Error */
#define OPI 020000 /* hper1 - Operation Incomplete */
/* Error Correction Code errors */
#define DCK 0100000 /* hper1 - Data Check error */
#define ECH 0100 /* hper1 - ECC hard error */
#define CLR 040 /* hpcs2 - Controller Clear */
#define FMT22 010000 /* hpof - 16 bit /word format */
/*
* Use av_back to save track+sector,
* b_resid for cylinder.
*/
#define trksec av_back
#define cylin b_resid
hpopen(dev)
{
if(!hp_openf)
HPADDR->hpcs2 = CLR;
if(! ( (hp_openf>>(dev.d_minor>>3))&1) ) {
hp_openf =| 1<<(dev.d_minor>>3);
HPADDR->hpcs2 = dev.d_minor>>3;
HPADDR->hpcs1 = RCLR|GO;
HPADDR->hpcs1 = PRESET|GO;
HPADDR->hpof = FMT22;
}
}
hpstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register char *p1, *p2;
bp = abp;
p1 = &hp_sizes[bp->b_dev.d_minor&07];
if (bp->b_dev.d_minor >= (NHP<<3) ||
bp->b_blkno >= p1->nblocks) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
bp->av_forw = 0;
bp->cylin = p1->cyloff;
p1 = bp->b_blkno;
p2 = lrem(p1, 22);
p1 = ldiv(p1, 22);
bp->trksec = (p1%19)<<8 | p2;
bp->cylin =+ p1/19;
spl5();
if ((p1 = hptab.d_actf)==0)
hptab.d_actf = bp;
else {
for (; p2 = p1->av_forw; p1 = p2) {
if (p1->cylin <= bp->cylin
&& bp->cylin < p2->cylin
|| p1->cylin >= bp->cylin
&& bp->cylin > p2->cylin)
break;
}
bp->av_forw = p2;
p1->av_forw = bp;
}
if (hptab.d_active==0)
hpstart();
spl0();
}
hpstart()
{
register struct buf *bp;
if ((bp = hptab.d_actf) == 0)
return;
hptab.d_active++;
HPADDR->hpcs2 = bp->b_dev.d_minor >> 3;
HPADDR->hpca = bp->cylin;
rhstart(bp, &HPADDR->hpda, bp->trksec, &HPADDR->hpbae);
}
hpintr()
{
register struct buf *bp;
register int ctr;
if (hptab.d_active == 0)
return;
bp = hptab.d_actf;
hptab.d_active = 0;
if (HPADDR->hpcs1 & ERR) { /* error bit */
deverror(bp, HPADDR->hpcs2, HPADDR->hper1);
deverror(bp,HPADDR->hper2);
if(HPADDR->hper1 & (DU|DTE|OPI)) {
HPADDR->hpcs2 =| CLR;
HPADDR->hpcs1 = RECAL|GO;
ctr = 0;
while ((HPADDR->hpds&PIP) && --ctr);
}
HPADDR->hpcs1 = RCLR|GO;
if (++hptab.d_errcnt <= 10) {
hpstart();
return;
}
bp->b_flags =| B_ERROR;
}
hptab.d_errcnt = 0;
hptab.d_actf = bp->av_forw;
bp->b_resid = HPADDR->hpwc;
iodone(bp);
hpstart();
}
hpread(dev)
{
if(hpphys(dev))
physio(hpstrategy, &hpbuf, dev, B_READ);
}
hpwrite(dev)
{
if(hpphys(dev))
physio(hpstrategy, &hpbuf, dev, B_WRITE);
}
hpphys(dev)
{
register c;
c = lshift(u.u_offset, -9);
c =+ ldiv(u.u_count+511, 512);
if(c > hp_sizes[dev.d_minor & 07].nblocks) {
u.u_error = ENXIO;
return(0);
}
return(1);
}
<File 1>
dmr/rx.c
4650
#
/*
* RX floppy disk driver
* Ron Broersma -- Naval Ocean Systems Center, San Diego, California
*/
#include "param.h"
#include "buf.h"
#include "conf.h"
#include "user.h"
#include "seg.h"
#ifndef RXADDR
#define RXADDR 0177170
#endif not RXADDR
#define NRX 2
#define NRXBLK 500
#define GO 1
#define FILL 0
#define EMPTY 2
#define WRITE 4
#define READ 6
#define RDSTAT 012
#define RDERR 016
#define IENABLE 0100
#define TR 0200
#define DRVRDY 0200
#define DONE 040
#define INIT 040000
#define INITDONE 4
#define WAIT while(!(RXADDR->rxcs&(TR | DONE)))
struct {
int rxcs;
int rxdb;
};
struct devtab rxtab;
struct buf rrxbuf;
struct rxadr {
char sector;
char track;
};
rxstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
bp = abp;
if (bp->b_blkno >= NRXBLK) {
if (bp->b_blkno==NRXBLK)
bp->b_wcount = max(bp->b_wcount, -128);
/* so we don't get errors when */
/* trying to read the last 2 sectors */
else {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
}
bp->b_resid = -bp->b_wcount; /* used to tell how far to go */
bp->b_wcount = 0; /* used to tell how far we are (in bytes!) */
bp->av_forw = 0;
spl5();
if (!(rxtab.d_actf))
rxtab.d_actf = bp;
else
rxtab.d_actl->av_forw = bp;
rxtab.d_actl = bp;
if (!(rxtab.d_active)) rxstart();
spl0();
}
rxaddr(abp)
struct buf *abp;
{
register int sect, track;
register struct buf *bp;
int t1, t2, dtyp;
bp = abp;
dtyp = (bp->b_dev.d_minor&6) >> 1;
sect = (bp->b_blkno<<2) + (bp->b_wcount>>7);
if (!dtyp)
sect = sect==36?NRXBLK*4:sect==NRXBLK*4?36:sect;
t1 = sect/26;
if ((!dtyp) || dtyp == 2) {
t2 = sect%26;
track = t1 + (dtyp?1:0);
sect = 6*t1 + t2*2 + (t2>=13?1:0);
}
else track = t1;
return((track << 8) + sect%26 + 1);
}
rxto(word)
{
WAIT;
RXADDR->rxdb.lobyte = word.lobyte;
WAIT;
RXADDR->rxdb.lobyte = word.hibyte;
}
rxfrom()
{
int word;
WAIT;
word.lobyte = RXADDR->rxdb.lobyte;
WAIT;
word.hibyte = RXADDR->rxdb.lobyte;
return(word);
}
char sbuf[128];
rxdata(bp, command, wcount)
struct buf *bp;
{
register char *cp;
register int nbytes;
register int bn;
int tn[2];
#ifndef UCBUFMOD
int sa, sps;
#endif not UCBUFMOD
cp = bp; /* for speed and size */
tn[0] = cp->b_xmem; tn[1] = cp->b_addr;
dpadd(tn, cp->b_wcount);
bn = lshift(tn, -6);
tn[1] =& 077;
RXADDR->rxcs = command | GO;
nbytes = wcount<<1;
if (command == FILL) {
#ifndef UCBUFMOD
cp = ka6-6; sa = cp->integ;
sps = PS->integ; PS->integ = 030340;
cp->integ = bn;
copyin(tn[1], sbuf, nbytes);
cp->integ = sa; PS->integ = sps;
#endif not UCBUFMOD
#ifdef UCBUFMOD
btk(bn, tn[1], sbuf, wcount);
#endif UCBUFMOD
cp = sbuf;
do {
WAIT;
RXADDR->rxdb.lobyte = *cp++;
} while --nbytes;
while(!(RXADDR->rxcs&DONE)) rxto(0);
}
else {
cp = sbuf;
do {
WAIT;
*cp++ = RXADDR->rxdb.lobyte;
} while --nbytes;
#ifndef UCBUFMOD
cp = ka6-6; sa = cp->integ;
sps = PS->integ; PS->integ = 030340;
cp->integ = bn;
copyout(sbuf, tn[1], wcount<<1);
cp->integ = sa; PS->integ = sps;
#endif not UCBUFMOD
#ifdef UCBUFMOD
ktb(bn, tn[1], sbuf, wcount);
#endif UCBUFMOD
while(!(RXADDR->rxcs&DONE)) rxfrom();
}
}
rxstart()
{
register struct buf *bp;
register cmd;
if (!(bp = rxtab.d_actf))
return;
cmd = WRITE | GO | IENABLE | ((bp->b_dev.d_minor&1)<<4);
if (bp->b_flags&B_READ)
cmd =| READ;
else rxdata(bp, FILL, min(bp->b_resid, 64));
rxtab.d_active++;
RXADDR->rxcs = cmd;
rxto(rxaddr(bp));
}
rxintr()
{
register struct buf *bp;
int ersave;
if (!(rxtab.d_active))
return;
rxtab.d_active = 0;
bp = rxtab.d_actf;
if (RXADDR->rxcs < 0) {
RXADDR->rxcs = RDSTAT | GO | ((bp->b_dev.d_minor&1)<<4);
while (!(RXADDR->rxcs&DONE));
if ((ersave = RXADDR->rxdb) & DRVRDY) {
RXADDR->rxcs = RDERR;
while(!(RXADDR->rxcs&DONE));
deverror(bp, ersave, RXADDR->rxdb);
RXADDR->rxcs = INIT;
while (!(RXADDR->rxdb&INITDONE));
if (++rxtab.d_errcnt <= 10) {
rxstart();
return;
}
}
bp->b_flags =| B_ERROR;
}
if (bp->b_flags&B_READ)
rxdata (bp, EMPTY, min(bp->b_resid, 64));
bp->b_resid =- min(bp->b_resid, 64);
bp->b_wcount =+ 128;
if (bp->b_resid && !(bp->b_flags&B_ERROR)) {
rxstart();
return;
}
rxtab.d_errcnt = 0;
rxtab.d_actf = bp->av_forw;
iodone(bp);
rxstart();
}
rxread(dev)
{
physio(rxstrategy, &rrxbuf, dev, B_READ);
}
rxwrite(dev)
{
physio(rxstrategy, &rrxbuf, dev, B_WRITE);
}
<File 1>
ncpp/mail/mailer.c
15964
#/*
Module Name:
mailer.c -- ARPAnet mailer daemon
Installation:
if $1x = newerx goto newer
if $1e = finale goto finale
cc -c mailer.c
if ! -r mailer.o exit
cc mailer.o /usr/net/hnconv.c
rm -f mailer.o hnconv.o
exit
: newer
if ! { newer mailer.c /usr/net/etc/mailer } exit
echo ncpp/mail/mailer.c:
: finale
cc -O -c mailer.c
if ! -r mailer.o exit
cc -O -s mailer.o /usr/net/hnconv.c -lj
if ! -r a.out exit
if ! -r /usr/sys/ncpp/mail/mailer.c goto same
if { cmp -s mailer.c /usr/sys/ncpp/mail/mailer.c } goto same
su cp mailer.c /usr/sys/ncpp/mail/mailer.c
su chmod 444 /usr/sys/ncpp/mail/mailer.c
rm -f mailer.c
: same
if -r /usr/net/etc/mailer su rm -f /usr/net/etc/mailer
su cp a.out /usr/net/etc/mailer
rm -f a.out mailer.o hnconv.o
su chmod 555 /usr/net/etc/mailer
su chown bin /usr/net/etc/mailer
su chgrp bin /usr/net/etc/mailer
Synopsis:
mailer [ delay-time [ bypass-count [ log-word [ debug-dir ] ] ] ]
Function:
Deliver ARPAnet mail.
Module History:
modified for Illinois NCP
return undeliverable mail as a message
fixed write length in returned.mail
6Mar79 Greg Noel. Introduced paranoia about slugish hosts.
30Apr79 Greg Noel. Transient remote errors are now retried later.
15May79 Greg Noel. 450 User Unknown is hard error, not transient.
*/
#include "net_open.h"
struct openparam openparam;
#define true 1
#define false 0
#define SLPTIME 600 /* default sleep time */
#define NTBYPASS 3 /* default bypass count */
#define MSGSEP "\001\001\001\001\n"
#define MSGSEPL 5
char hostname[100];
char mailcomd[256] { "mail <list of user names> "};
char returnto[256];
char linebuf[256];
char badhost[256];
char mailbuf[512];
char netbuf[512];
int dirfd;
int nflag, nflag1, tvec[2];
int slptime;
int ntbypass;
/* don't separate these two declarations */
int entry;
char filename[16];
/* don't separate the preceding two declarations */
int statbuf[32];
int timoutflg;
int mailproc;
int timeout();
struct fcb {
int f_fd;
char *f_ptr;
char *f_buf;
int f_count;
}
netfcb,mailfcb;
/* name:
maildaemon
function:
To see if there is any mail waiting delivery to some other
site on the network, and deliver it.
algorithm:
If there is any mail, send it.
Wait a while and look for mail again.
parameters:
If argv[1] is present, it is the number of seconds to sleep
between passes through the mail directory. If it is absent
or 0, a default value is used (SLPTIME).
If argv[2] is present, it is the number of passes through
which to bypass mail for hosts which are not responding.
If argv[3] is present, messages will be written out indicating
the progress of the mailer.
If argv[4] is present, use this as the mail directory and make
one pass through it. Used for debugging.
returns:
globals:
dirfd fd of /usr/netmail
calls:
open sys
seek sys
printf library
get_next_file
ship_it_off
called by:
history:
Design and initial coding by Mark Kampe, 12/27/75
*/
main(argc, argv)
int argc;
char **argv;
{
int i;
extern int fout;
signal(1,1);
signal(2,1);
signal(3,1);
mailproc = getpid();
if (argc < 2 || (slptime=atoi(argv[1])) <= 0) slptime = SLPTIME;
if (argc < 3 || (ntbypass=atoi(argv[2])) <= 0) ntbypass = NTBYPASS;
if (argc > 3) nflag++;
if (chdir(argc > 4 ? argv[4] : "/usr/netmail") < 0 ||
(dirfd = open(".",0)) < 0) {
printf("Unable to open /usr/netmail\n");
exit(-1);
}
fout = dup(1); /* buffer all further output */
log("Sleep time = %d, Bypass = %d\n", slptime, ntbypass);
nflag1 = 0;
openparam.o_host = 0;
netfcb.f_fd = -1;
loop:
/*
* The mailer should lock this directory so that conflicts
* with other incarnations of the mailer will not occur.
* The lock should be established here and removed below.
* The routine get_next_file must be modified to skip
* over the lock. Another alternative is to fork for each
* new destination host encountered and lock only on the
* basis of destination; this will maximize parallelism
* of transmission.
*/
seek(dirfd,0,0);
while(get_next_file())
ship_it_off();
closenet(); /* close last connection */
for (i=0; i<256; i++)
if (badhost[i]) --badhost[i];
if(nflag1) {
log("Ending cycle\n");
nflag1 = 0;
}
/* Remove lock here.... */
if(argc>4) exit(0); /* used for testing */
sleep(slptime);
goto loop;
}
/* name:
log
function:
to log something if logging is enabled.
algorithm:
if logging is enabled
print leading banner
print message to be logged
parameters:
identical to printf
returns:
nothing
globals:
nflag set if logging is enabled
tvec time at which current cycle began
calls:
printf (sys)
time (sys)
ctime (sys)
called by:
many places
history:
24 Aug 77 coded by Greg Noel
24 Jul 78 modified by Greg Noel to condense logging printout
*/
log(t, a, b, c, d)
{
if (nflag)
{ time(tvec);
printf("%-16.16sMailer: ", ctime(tvec)+4);
printf(t, a, b, c, d);
flush();
nflag1++;
}
}
/* name:
get_next_file
function:
To find get the next file in /usr/netmail and set up all
of the parameters for the mailing.
algorithm:
Read next non-empty record
if end of file, return error
set up hostname
mail command line
file name (for future deletion)
root of sender for possible return.
return true
parameters:
returns:
boolean true means a file was found and set up
false means no more files in directory
globals:
hostname
mailcomd
mailfcb
filename
dirfd
returnto
calls:
read (sys)
open (sys)
getline
unlink (sys)
called by:
main
history:
Initial coding by Mark Kampe 11/27/75
*/
get_next_file()
{ register char *p;
register char *s;
register int i;
loop: i = read(dirfd,&entry,16);
if (i != 16) return(false);
if (entry == 0) goto loop;
if (filename[0] == '.') goto loop;
if (filename[13]) filename[14] = '\000';
mailfcb.f_fd = open(filename,0);
if (mailfcb.f_fd < 0)
goto badfile;
mailfcb.f_count = 0;
mailfcb.f_buf = mailbuf;
p = getline(&mailfcb);
if (p == 0) goto badfile;
s = hostname;
while(*p != ':') if ((*s++ = *p++) == '\000') goto badfile;
*s++ = '\000';
p++;
s = &mailcomd[5];
while(*p != ':') if ((*s++ = *p++) == '\000') goto badfile;
*s++ = '\000';
p++;
s = returnto;
if (*p == ':')
*s = '\0';
else { while(*p != ':') if ((*s++ = *p++) == '\000') goto badfile;
for(p = "/.mail"; *s++ = *p++;);
}
return(true);
badfile:
log("File %s in illegal format -- deleted\n", filename);
unlink(filename);
goto loop;
}
/* name:
ship_it_off
function:
To carry out the protocol to mail off a file over the network
algorithm:
Connect to the forign host
Await a ready command
send the mail command
Await the send your mail response.
send the mail
Await the confirmation.
Delete the file if the transmission was successful.
If there was a permanent failure, put the file in the sender's
root with an explanatory message.
parameters:
returns:
globals:
hostname contains name of foreign host
mailcomd contains a mail command with all appt names
netfcb file descriptor of network file
filename name of the current file
returnto sender's mailbox (if return is necessary);
badhost
calls:
getline
writef
reply
open sys
close sys
getline
called by:
main
history:
Initial coding by Mark Kampe 12/27/75
Modified by Greg Noel 7/24/78 to maintain connection if destination
host does not change
*/
ship_it_off()
{
extern char *hnconv();
int hnum;
register char *p;
register int i;
register int rtnfd;
int timeproc;
netfcb.f_count = 0;
openparam.o_fskt[1] = 3;
openparam.o_timo = 60;
if ((hnum=atoi(hnconv(hostname))) <= 0) /***/
{ log("Mail in %s for %s at %s\n",
filename, &mailcomd[5], hostname); /***/
p = "Destination host is unknown.";
goto fail;
}
if (badhost[hnum])
goto nogood;
log("Mail in %s for %s at %s\n", filename, &mailcomd[5], hostname);
if ((openparam.o_host&0377) != hnum) {
closenet();
openparam.o_host = hnum;
set_alarm(120);
netfcb.f_fd = open("/dev/net/anyhost",&openparam);
alarm(0);
if (netfcb.f_fd <= 0)
{ log("Unable to open connection\n");
badhost[hnum] = ntbypass; /* number of times to bypass */
goto nogood;
}
netfcb.f_count = 0;
netfcb.f_buf = netbuf;
do { p = getline(&netfcb);
if (p == 0) goto tempfail;
i = reply(p);
if (i >= 400) goto tempfail;
} while(i != 300);
}
i = writef(netfcb.f_fd,mailcomd);
if (i < 0) goto tempfail;
i = writef(netfcb.f_fd,"\r\n");
if (i < 0) goto tempfail;
i = 0;
while(i != 350)
{ p = getline(&netfcb);
if (p == 0) goto tempfail;
i = reply(p);
if (i == 951) continue; /* Mail will be forwarded... */
if (i == 504)
switch (loginfirst())
{ case -1: goto fail;
case 0: goto tempfail;
case 1: continue;
};
if (i >= 500) goto fail;
if (i == 450) goto fail; /* User unknown */
if (i > 400) goto tempfail;
if (i == 400) goto fail; /* Service not implemented */
if (i == 331) goto fail; /* Need account parameter */
}
while(p = getline(&mailfcb)) {
i = writef(netfcb.f_fd,p);
if (i < 0) goto tempfail;
i = writef(netfcb.f_fd,"\r\n");
if (i < 0) goto tempfail;
}
i = writef(netfcb.f_fd, ".\r\n");
if (i < 0) goto tempfail;
i = 0;
while(i != 256)
{ p = getline(&netfcb);
if (p == 0) goto tempfail;
i = reply(p);
if (i >= 500) goto fail;
if (i > 400) goto tempfail;
if (i > 300) goto fail;
}
close(mailfcb.f_fd);
unlink(filename);
return(true);
fail:
log("Unrecoverable error; mail returned to sender\n");
/* now return the message to the sender */
if (returnto &&
( ((rtnfd=open(returnto,1)) >= 0) ||
((rtnfd=creat(returnto,0666)) >= 0) ) )
{ seek(rtnfd,0,2);
writef(rtnfd,"From: mailer\n");
writef(rtnfd,"Subject: Undeliverable mail\n\n");
writef(rtnfd, "Mail for "); writef(rtnfd, &mailcomd[5]);
writef(rtnfd, " at "); writef(rtnfd, hostname);
writef(rtnfd, " undeliverable because:\n\t");
writef(rtnfd,p);
writef(rtnfd,"\n------- Unsent message is below -------\n\n");
seek(mailfcb.f_fd,0,0);
mailbuf[0] = 0;
while(mailbuf[0] != '\n') read(mailfcb.f_fd,mailbuf,1);
while((i = read(mailfcb.f_fd,mailbuf,512)) > 0)
write(rtnfd,mailbuf,i);
close(rtnfd);
}
unlink(filename);
tempfail:
closenet();
nogood:
close(mailfcb.f_fd);
return(false);
}
closenet()
{
openparam.o_host = 0;
if(netfcb.f_fd < 0) return; /* not currently open */
writef(netfcb.f_fd,"BYE\r\n");
getline(&netfcb); /* keep NCP happy until 'flush user' fixed */
close(netfcb.f_fd);
netfcb.f_fd = -1;
}
timeout()
{ timoutflg++;
wait(); /* get rid of zombie */
reset(); /* return to ship_it_off */
}
/* name:
getline
function:
To retrieve one "line" from the file on the specified descriptor.
algorithm:
Ignore carriage returns.
While the next character is not a new line, stash it in linebuf;
null terminate the string in linebuf;
return a pointer to linebuf;
If we should reach end of file and have a line started, terminate
it and return. If no line is started, return a zero.
parameters:
*fcb file control block for the file in question.
returns:
*char pointer to a null terminated string.
or a zero indicating end of file.
globals:
linebuf destination of read
calls:
read (sys)
called by:
get_next_file
ship_it_off
history:
Initial coding by Mark Kampe 12/27/75
*/
getline(afcb)
struct fcb *afcb;
{ register int count;
register char *nextin;
register char *nextout;
char lastchar;
count = afcb->f_count;
nextin = afcb->f_ptr;
nextout = linebuf;
lastchar = '\000';
while(lastchar != '\n') {
if (count <= 0) {
set_alarm(60);
count = read(afcb->f_fd,afcb->f_buf,512);
alarm(0);
if (count <= 0)
{ count = -1;
nextin = "\n";
}
else nextin = afcb->f_buf;
}
count--;
lastchar = *nextin++;
if(nextout < &linebuf[sizeof linebuf])
*nextout++ = lastchar;
if (lastchar == '\r') nextout--;
}
afcb->f_count = count;
afcb->f_ptr = nextin;
*--nextout = '\000';
if (nextout == linebuf)
if (count < 0) return(0);
if (nextout == &linebuf[1] && linebuf[0] == '.') {
*nextout++ = ' ';
*nextout = '\0';
}
return(linebuf);
}
/* name:
writef
function:
To write a null terminated string out to the specified file descriptor.
algorithm:
Find the length of the string.
Write it out .
parameters:
int file descriptor
*char address of string to be written.
returns:
int value returned by write.
globals:
calls:
write (sys)
called by:
ship_it_off
history:
Initial coding by Mark Kampe 12/27/75
*/
writef(afd,as)
int afd;
char *as;
{ register char *s;
register int i;
register int j;
i = 0;
for(s = as; *s++; i++);
if(i == 0) return 0;
set_alarm(60);
j = write(afd, as, i);
alarm(0);
if (j != i) /* did error occur? */
{ log("write(%d,0%o,%d) returned %d.\n",afd,as,i,j);
log("line was '%s'.\n", as);
}
return(j);
}
/* name:
reply
function:
To find the reply number from a network message.
algorithm:
Convert the first three characters into an integer.
If any are non numeric, return a zero.
parameters:
*char pointer to the string in question (null terminated)
returns:
int
globals:
calls:
called by:
ship_it_off
history:
Initial coding by Mark Kampe 12/27/75
*/
reply(ap)
char *ap;
{ register char c;
int i;
register int j;
register char *s;
s = ap;
log("%s\n",s);
while((*s<'0') || (*s>'9')) if (*s++ == '\000') return(0); /* fuckers at multics */
j = 0;
for(i = 3; i; i--)
{ c = *s++;
if ((c < '0') || (c > '9')) return(0);
j =* 10;
j =+ c;
j =- '0';
}
return(j);
}
/* name:
loginfirst
function:
to login to a bastard host who insists on it
algorithm:
send a "user NETML\npassNETML\n";
wait for the 330 230
resend the mail command
if a transmission failure return 0
if a bad reply return -1
else return 1
parameters:
returns:
-1 permanent failure
0 temperary failure
1 success
globals:
netfcb
mailcomd
calls:
getline
reply
writef
called by:
ship_it_off
history:
Designed and coded by a disgruntled Mark Kampe 1/5/76
*/
loginfirst()
{ register int i;
register char *p;
i = writef(netfcb.f_fd,"USER NETML\r\n");
if (i<=0) return(0);
i = 0;
while(i != 330)
{ p = getline(&netfcb);
if (p == 0) return(0);
i = reply(p);
if (i == 230) goto gotin;
if (i >= 400) return(-1);
};
i = writef(netfcb.f_fd, "PASS NETML\r\n");
if (i <= 0) return(0);
i = 0;
while(i != 230)
{ p = getline(&netfcb);
if (p == 0) return(0);
i = reply(p);
if (i >= 400) return(-1);
}
gotin:
i = writef(netfcb.f_fd, mailcomd);
if (i<=0) return(0);
i = writef(netfcb.f_fd, "\r\n");
if (i <= 0) return(0);
return(1);
}
/*
name:
set_alarm, ring
function:
to terminate an operation if the remote host is too slugish.
algorithm:
set an alarm for the specified period.
when the alarm occurs, just return -- the interrupted system call
will return -1.
parameters:
the number of seconds to wait
returns:
yes
globals:
none.
calls:
alarm (sys)
signal (sys)
log
called by:
several people.
history:
coded 6Mar79 by Greg Noel
*/
set_alarm(v)
int v;
{
int ring();
signal(14, &ring);
alarm(v);
}
ring()
{
log("Timeout\n");
}
<File 1>
dmr/rl.c
4123
#
/*
* RL01 disk driver
*
* Tom Ferrin - 19 July 78
* UCSF Computer Graphics Laboratory
*
* This driver has now been running for several weeks on a dual drive 11/60.
* It doesn't minimize seek scheduling & totally ignores DEC's bad block table.
*/
#include "param.h"
#include "buf.h"
#include "conf.h"
#include "user.h"
#ifndef NRL
#define NRL 4
#endif not NRL
#ifndef RLADDR
#define RLADDR 0174400
#endif not RLADDR
#define NRLBLK 10220 /* block = 2 sectors = 512 bytes, last track reserved */
#define HNF 010000
#define OPI 02000
#define CRDY 0200
#define IENABLE 0100
#define RCOM 014
#define WCOM 012
#define RHCOM 010
#define SCOM 06
#define GSCOM 04
#define DRST 010
#define DSDIR 04
#define DSTAT 02
#define DMARK 01
#define VC 01000
#define rlexec(a,b) dp->rlcs=((a)<<8)|(b); while((dp->rlcs&CRDY)==0)
struct {
int rlcs;
int rlba;
int rlda;
int rlmp;
};
struct {
char openf; /* open flag */
int cyltrk; /* current cylinder & head select */
} rl01[NRL];
struct devtab rltab;
struct buf rrlbuf;
rlopen(dev, flag)
{
register int unit, *dp, i;
if (rl01[unit=dev.d_minor].openf == 0) {
dp = RLADDR;
spl5();
dp->rlda = DRST|DSTAT|DMARK;
rlexec(unit, GSCOM);
rlexec(unit, RHCOM);
i = dp->rlcs;
spl0();
if (i < 0) {
u.u_error = EIO;
return;
}
rl01[unit].cyltrk = dp->rlmp & ~077;
rl01[unit].openf++;
}
}
rlstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register int i;
bp = abp;
if (bp->b_flags&B_PHYS)
mapalloc(bp);
if (bp->b_dev.d_minor >= NRL || (i=bp->b_blkno) >= NRLBLK) {
u.u_error = ENXIO;
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
bp->av_back = (i/20)<<6 | (i%20)<<1; /* desired address */
bp->av_forw = 0;
spl5();
if (rltab.d_actf==0)
rltab.d_actf = bp;
else
rltab.d_actl->av_forw = bp;
rltab.d_actl = bp;
if (rltab.d_active==0)
rltran();
spl0();
}
rltran()
{
register struct buf *bp;
register int i;
if ((bp=rltab.d_actf) == 0)
return;
i = bp->av_back;
i = (40-(i&077))*128; /* words left on track */
if (i >= -bp->b_wcount)
bp->b_resid = 0;
else {
bp->b_resid = bp->b_wcount+i; /* words left for next transfer */
bp->b_wcount = -i;
}
rlstart();
}
rlstart()
{
register struct buf *bp;
register int da, *dp;
int unit, ca, rda;
rltab.d_active++;
bp = rltab.d_actf;
unit = bp->b_dev.d_minor;
da = bp->av_back;
dp = &rl01[unit].cyltrk;
if ((da&~077) != *dp) {
ca = *dp & ~100;
*dp = da & ~077;
dp = RLADDR;
rda = da & ~0177;
da = (da&0100)>>2;
if ((ca =- rda) < 0)
ca = -ca|DSDIR;
dp->rlda = da|ca|DMARK;
rlexec(unit, SCOM);
}
dp = &RLADDR->rlmp;
*dp = bp->b_wcount;
*--dp = bp->av_back;
*--dp = bp->b_addr;
da = (bp->b_xmem&03)<<4 | unit<<8 | IENABLE;
if (bp->b_flags&B_READ)
da =| RCOM;
else
da =| WCOM;
*--dp = da;
}
rlintr()
{
register struct buf *bp;
register int *dp, i;
int n[2];
if (rltab.d_active == 0)
return;
bp = rltab.d_actf;
rltab.d_active = 0;
if ((dp=RLADDR)->rlcs < 0) { /* error bit */
n[0] = dp->rlcs;
i = bp->b_dev.d_minor;
dp->rlda = DSTAT|DMARK;
rlexec(i, GSCOM);
n[1] = dp->rlmp;
deverror(bp, n[0], n[1]);
dp->rlda = DRST|DSTAT|DMARK;
rlexec(i, GSCOM);
if ((n[0]&(HNF|OPI))==(HNF|OPI) || (n[1]&VC)) {
rlexec(i, RHCOM);
if (dp->rlcs < 0)
goto abort;
rl01[i].cyltrk = dp->rlmp & ~077;
}
if (++rltab.d_errcnt <= 10) {
rlstart();
return;
}
abort:
bp->b_flags =| B_ERROR;
bp->b_resid = 0;
}
rltab.d_errcnt = 0;
if (bp->b_resid) {
n[0] = bp->b_xmem; /* more of previous transfer */
n[1] = bp->b_addr;
dpadd(n, -bp->b_wcount<<1);
bp->b_xmem = n[0];
bp->b_addr = n[1];
bp->b_wcount = bp->b_resid;
i = bp->av_back;
bp->av_back = (i&~077) + 0100;
} else {
rltab.d_actf = bp->av_forw;
iodone(bp);
}
rltran();
}
rlread(dev)
{
physio(rlstrategy, &rrlbuf, dev, B_READ);
}
rlwrite(dev)
{
physio(rlstrategy, &rrlbuf, dev, B_WRITE);
}
<File 1>
dmr/tm.c
6249
#
/*
*/
/*
* TM tape driver
*/
#include "param.h"
#include "buf.h"
#include "conf.h"
#include "user.h"
struct {
int tmer;
int tmcs;
int tmbc;
int tmba;
int tmdb;
int tmrd;
};
struct devtab tmtab;
struct buf rtmbuf;
#ifdef NOSC /* extra flag in rtmbuf.b_flags to handle odd-length writes */
#define B_ODDLEN 0100000
#endif NOSC
#define B_SCOM 0040000
char t_openf[8];
#define TMopen 0001
#define TMeof 0002 /* last read an EOF */
#define TMflush 0004 /* purge all I/O to this device */
char *t_blkno[8];
char *t_nxrec[8];
#define TMADDR 0172520
#define NOREW 020
#define GO 01
#define NOCMD 000
#define RCOM 002
#define WCOM 004
#define WEOF 006
#define SFORW 010
#define SREV 012
#define WIRG 014
#define REW 016
#define DENS 060000 /* 9-channel */
#define IENABLE 0100
#define CRDY 0200
#define GAPSD 010000
#define TUR 1
#define HARD 0102200 /* ILC, EOT, NXM */
#define EOF 0040000
#define SSEEK 1
#define SIO 2
#define SCOM 3
tmopen(dev, flag)
{
register dminor;
dminor = dev.d_minor&07;
if (t_openf[dminor])
u.u_error = ENXIO;
else {
t_openf[dminor] = TMopen;
t_blkno[dminor] = 0;
t_nxrec[dminor] = 65535;
}
}
tmclose(adev, flag)
{
register int dminor, dev;
dev = adev;
dminor = dev.d_minor&07;
if (flag) {
tcommand(dev, WEOF);
tcommand(dev, WEOF);
tcommand(dev, dev&NOREW ? SREV : REW);
} else {
if((dev&NOREW)==0)
tcommand(dev, REW);
else if((t_openf[dminor] & TMeof) == 0)
tcommand(dev, SFORW);
}
t_openf[dminor] = 0;
}
tcommand(dev, com)
{
register struct buf *bp;
bp = &rtmbuf;
spl6();
while(bp->b_flags & B_BUSY) {
bp->b_flags =| B_WANTED;
sleep(bp, PRIBIO);
}
spl0();
bp->b_dev = dev;
bp->b_resid = com;
bp->b_blkno = 0;
bp->b_flags = B_SCOM | B_BUSY | B_READ;
tmqup(bp);
iowait(bp);
if(bp->b_flags & B_WANTED)
wakeup(bp);
bp->b_flags = 0;
return(bp->b_resid);
}
tmstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register char **p;
bp = abp;
if(bp->b_flags&B_PHYS)
mapalloc(bp);
p = &t_nxrec[bp->b_dev.d_minor&07];
if (*p <= bp->b_blkno) {
if (*p < bp->b_blkno) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
if (bp->b_flags&B_READ) {
clrbuf(bp);
iodone(bp);
return;
}
}
if ((bp->b_flags&B_READ)==0)
*p = bp->b_blkno + 1;
tmqup(bp);
}
tmqup(abp)
struct buf *abp;
{
register struct buf *bp;
bp = abp;
bp->av_forw = 0;
spl5();
if (tmtab.d_actf==0)
tmtab.d_actf = bp;
else
tmtab.d_actl->av_forw = bp;
tmtab.d_actl = bp;
if (tmtab.d_active==0)
tmstart();
spl0();
}
tmstart()
{
register struct buf *bp;
register int com;
int unit;
register char *blkno;
loop:
if ((bp = tmtab.d_actf) == 0)
return;
com = ((bp->b_dev.d_minor&~NOREW)<<8) | ((bp->b_xmem & 03) << 4);
if(bp->b_flags&B_SCOM) {
if(bp->b_resid == NOCMD) {
/* don't want IENABLE bit or else */
/* interrupt will occur immediately */
TMADDR->tmcs = com;
bp->b_resid = TMADDR->tmer;
tmdone();
goto loop;
}
tmtab.d_active = SCOM;
TMADDR->tmbc = 1; /* i.e. infinity, or until eof */
TMADDR->tmcs = bp->b_resid | com | IENABLE | GO;
return;
}
unit = bp->b_dev.d_minor&07;
if ((t_openf[unit] & TMflush) || (TMADDR->tmcs & CRDY)==0) {
bp->b_flags =| B_ERROR;
tmdone();
goto loop;
}
t_openf[unit] =& ~TMeof;
blkno = t_blkno[unit];
if (blkno != bp->b_blkno) {
tmtab.d_active = SSEEK;
if (blkno < bp->b_blkno) {
com =| SFORW|IENABLE|GO;
TMADDR->tmbc = blkno - bp->b_blkno;
} else {
com =| SREV|IENABLE|GO;
TMADDR->tmbc = bp->b_blkno - blkno;
}
TMADDR->tmcs = com;
return;
}
tmtab.d_active = SIO;
TMADDR->tmbc = bp->b_wcount << 1;
#ifdef NOSC
if(bp->b_flags & B_ODDLEN) TMADDR->tmbc++;
#endif NOSC
TMADDR->tmba = bp->b_addr; /* core address */
TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|IENABLE|GO:
((tmtab.d_errcnt)? WIRG|IENABLE|GO: WCOM|IENABLE|GO));
}
tmdone()
{
register struct buf *bp;
bp = tmtab.d_actf;
tmtab.d_errcnt = 0;
tmtab.d_actf = bp->av_forw;
tmtab.d_active = 0;
iodone(bp);
}
tmintr()
{
register struct buf *bp;
register int unit;
if ((bp = tmtab.d_actf)==0)
return;
unit = bp->b_dev.d_minor&07;
/* ignore errors on SCOM */
if (tmtab.d_active == SCOM) {
bp->b_resid = TMADDR->tmbc -1; /* return skip count */
tmdone();
tmstart();
return;
}
if (TMADDR->tmcs < 0) { /* error bit */
while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */
if ((TMADDR->tmer&(HARD|EOF))==0 && tmtab.d_active==SIO) {
if (++tmtab.d_errcnt < 10) {
t_blkno[unit]++;
tmtab.d_active = 0;
tmstart();
return;
}
/*
deverror(bp, TMADDR->tmer, 0);
*/
} else if (TMADDR->tmer&EOF) {
t_openf[unit] =| TMeof;
if (bp != &rtmbuf) /* flush future I/O on */
t_openf[unit] =| TMflush; /* cooked device */
bp->b_resid = bp->b_wcount << 1;
tmdone();
tmstart();
return;
}
/*
else deverror(bp, TMADDR->tmer, 0);
*/
bp->b_flags =| B_ERROR;
tmtab.d_active = SIO;
}
if (tmtab.d_active == SIO) {
t_blkno[unit]++;
bp->b_resid = TMADDR->tmbc;
tmdone();
} else
t_blkno[unit] = bp->b_blkno;
tmstart();
}
#ifndef NOSC
tmread(dev)
{
tmphys(dev);
physio(tmstrategy, &rtmbuf, dev, B_READ);
u.u_count = -rtmbuf.b_resid;
}
tmwrite(dev)
{
tmphys(dev);
physio(tmstrategy, &rtmbuf, dev, B_WRITE);
u.u_count = 0;
}
tmphys(dev)
{
register unit, a;
unit = dev.d_minor&07;
a = lshift(u.u_offset, -9);
t_blkno[unit] = a;
t_nxrec[unit] = ++a;
}
#endif NOSC
#ifdef NOSC
/* Special NOSC code to permit odd-length reads and writes */
tmread(dev)
{
physio(tmstrategy, &rtmbuf, dev, tmphys(dev)|B_READ);
u.u_count = -rtmbuf.b_resid;
}
tmwrite(dev)
{
physio(tmstrategy, &rtmbuf, dev, tmphys(dev)|B_WRITE);
u.u_count = 0;
}
tmphys(dev)
{
register unit, a;
unit = dev.d_minor&07;
a = lshift(u.u_offset, -9);
t_blkno[unit] = a;
t_nxrec[unit] = ++a;
if(u.u_count & 01) {
u.u_count++;
return (B_ODDLEN);
}
return 0;
}
#endif NOSC
<File 1>
dmr/dz.c
15304
#
/*
module name:
dz.c
function:
Device driver for the DEC dz11 8 line asynchronous multiplexor
globals containied:
dz11 array of tty structures for the dz11 lines
dzaddrs array of addresses of the various dz11 controllers
dzmodem array specifying which dz ports have modem control
dzcycling whether or not modem control is cycling
routines contained:
dzopen open system call routine
dzclose close system call routine
dzread read system call routine
dzwrite write system call routine
dzrint receive interrupt routine
dzxint transmit interrupt routine
dzstart I/O startup routine
dzsgtty sgtty system call routine
dzparam hardare parameter setting routine
dzstatus modem control cycling routine
routines referenced:
ttread, ttwrite, ttyinput, ttystty, ttrstrt
sleep, wakeup
timeout
issig, psig
modules referenced:
user.h needed because of the error code definitions
param.h contains constants required by user.h
conf.h contains the device structure definition
tty.h contains definition of tty structure
options.h to get system compile time parameters
compile time parameters:
UCLATTY define this if you are using the ucla tty.c
leave this undefined if you are using the standard one
history:
Designed and coded by Mark Kampe, 9/27/77.
*/
#include "param.h"
#include "conf.h"
#include "user.h"
#include "tty.h"
#define true 0177777
#define false 0000000
#define then /* */
#ifndef NDZ11
#define NDZ11 8 /* default number of DZ lines */
#endif not NDZ11
#ifndef DZADDRS
#define DZADDRS 0760100 /* default address of dz registers */
#endif not DZADDRS
#ifndef DZMODEM
#define DZMODEM 1, 1, 1, 1, 1, 1, 1, 1 /* default modem control enable */
#endif not DZMODEM
#define DZRATE 5*HZ /* sample modem status every 5 seconds */
struct tty dz11[ NDZ11 ];
struct dzregs /* the readable DZ11 registers */
{ int dzcsr; /* control status register */
int dzrcv; /* receive buffer register */
int dztcr; /* transmit control register */
int dzmsr; /* modem status register */
};
struct /* the writeable DZ11 registers */
{ int dzcsr; /* control status register */
int dzlpr; /* line parameter register */
int dztcr; /* transmit control register */
int dztdr; /* transmit data register */
};
struct dzregs *dzaddrs[] { DZADDRS }; /* addresses of DZ registers */
/* specification of which lines have modem control enabled */
char dzmodem[ NDZ11 ] /* Setting the i'th entry to a 1 */
{ DZMODEM }; /* enables modem control on that */
/* line. Although this array is */
/* statically initialized, it can */
/* be changed dynamically. */
int dzcycling; /* whether or not the dz has a modem test
pending on any modem controlled lines */
extern ttrstrt();
int dzstart();
char speedmap[ 16 ] /* map a Unix speed into a DZ11 equivalent */
{ 000, /* 0 baud */
000, /* 50 baud */
001, /* 75 baud */
002, /* 110 baud */
003, /* 134.5 baud */
004, /* 150 baud */
000, /* dz doesn't support 200 baud */
005, /* 300 baud */
006, /* 600 baud */
007, /* 1200 baud */
010, /* 1800 baud */
012, /* 2400 baud */
014, /* 4800 baud */
016, /* 9600 baud */
000, /* external 1 not supported */
000 /* external 2 not supported */
};
/* definitions for bits in the DZ11 registers */
#define MUXCLR 0000020 /* clear multiplexer in csr */
#define SCENABL 0000040 /* scan enable in csr */
#define IENABLE 0040100 /* xmt & rcv interrupts in csr */
#define RINT 0000200 /* receive done bit in csr */
#define XINT 0100000 /* transmit done bit in csr */
#define LINENUM 0003400 /* line # mask in rcv & csr */
#define PERROR 0010000 /* parity error in rcv */
#define FRERROR 0020000 /* framing error in rcv */
#define OVERRUN 0040000 /* data over run in rcv */
#define BITS_6 0000010 /* six bit characters in lpr */
#define BITS_7 0000020 /* seven bit characters in lpr */
#define BITS_8 0000030 /* eight bit characters in lpr */
#define ONE_SB 0000000 /* one stop bit in lpr */
#define TWO_SB 0000040 /* two stop bits in lpr */
#define PENABLE 0000100 /* parity enabled in lpr */
#define OPAR 0000200 /* odd parity selected in lpr */
#define SSPEED 0000007 /* unix notation for 300 baud */
#define RCV_ON 0010000 /* receiver enable in lpr */
#define DEFAULT 0012470 /* initial parameters for lpr */
/* name:
dzopen and dzclose
function:
open system call routine for the dz11
close system call routine for the dz11
algorithm:
open:
validate the device unit number
get the controller address
if the line isn't already open
initialize the hardware
if modem control is enabled on that line
wait for the line to come up
initialize the software parameters
call ttyopen on it
close:
flush any pending output
mark the line closed
disable further input from that line
parameters:
device designation (major and minor numbers)
flag (whether or not write access is desired)
returns:
a setting of u.u_error if it fails
globals:
dz11 tty tables for the dz11 lines
dzaddrs pointer to the registers
dzmodem
dzcycling
calls:
ttyopen to complete the opening operation
wflushtty to flush the queues
dzparam to set the initial parameters
dzstatus to start modem status cycling
called by:
openi through cdevsw
*/
dzopen( dev , flag )
int dev, flag;
{ register struct dzregs *dzp;
register struct tty *tp;
register int unit;
unit = dev.d_minor;
if (unit >= NDZ11)
then return( u.u_error = ENXIO );
dzp = dzaddrs[ (unit >> 3) ];
tp = &dz11[ unit ];
unit =& 7;
if ((tp->t_state & ISOPEN) == 0) then
{ dzp->dztcr =| (0400 << unit);
dzp->dzcsr =| (SCENABL|IENABLE);
if ( dzmodem[dev.d_minor] ) then
{ spl5();
dzp->dzlpr = unit|DEFAULT;
tp->t_state = WOPEN;
if (~dzcycling)
then dzstatus();
while((tp->t_state & CARR_ON) == 0)
{ sleep( tp, TTIPRI );
if (issig()) then
{ spl0();
psig();
return;
}
}
spl0();
}
tp->t_state =| SSTART|CARR_ON;
tp->t_flags = XTABS|ECHO|CRMOD|EVENP|ODDP;
tp->t_erase = CERASE;
tp->t_kill = CKILL;
tp->t_speeds = SSPEED | (SSPEED << 8);
tp->t_addr = dzstart;
dzparam( dev.d_minor );
}
ttyopen( dev, tp );
}
dzclose( dev, flag )
int dev, flag;
{ register struct tty *tp;
register int unit;
register struct dzregs *dzp;
unit = dev.d_minor;
tp = &dz11[ unit ];
dzp = dzaddrs[ unit >> 3 ];
wflushtty( tp );
tp->t_state = 0;
unit =& 7;
dzp->dzlpr = unit;
dzp->dztcr =& ~(0400 << unit);
}
/* name:
dzread and dzwrite
function:
read system call routine for the dz11
write system call routine for the dz11
algorithm:
convert the minor device designation into a pointer to a tty struct
call the appropriate device independent routine
parameters:
major and minor device designations
globals:
dz11
calls:
ttread
ttwrite
called by:
readi and writei through the cdevsw
*/
dzread( dev )
int dev;
{ register int unit;
register struct tty *tp;
unit = dev.d_minor;
tp = &dz11[ unit ];
ttread( tp );
}
dzwrite( dev )
int dev;
{ register int unit;
register struct tty *tp;
unit = dev.d_minor;
tp = &dz11[ unit ];
ttwrite( tp );
}
/* name:
dzrint
function:
receive interrupt handling routine for the dz11
algorithm:
get a pointer to the registers for the interrupting dz11
while there is data in the silo
get the next character
if from an illegal line,
continue
if a framing error
say the character was a null
call ttyinput with the character
parameters:
dz11 controller number of the interrupting unit
globals:
dz11 tty structures for the dz11 lines
dzaddrs address of dz11 controllers
calls:
ttyinput to process the received characters
called by:
trap
*/
dzrint( unit )
int unit;
{ register struct dzregs *dzp;
register struct tty *tp;
register int c;
int lineno;
dzp = dzaddrs[ unit ];
unit =<< 3;
while((c = dzp->dzrcv) < 0)
{ lineno = ((c & LINENUM) >> 8) + unit;
if (lineno >= NDZ11)
then continue;
tp = &dz11[ lineno ];
if (c & PERROR)
then continue;
if (c & FRERROR)
then c = 0;
else c =& 0377;
if (tp->t_state & ISOPEN)
then ttyinput( c , tp );
else wakeup( tp );
}
}
/* name:
dzxint
function:
dz11 transmit interrupt routine
algorithm:
get a pointer to the controller that interrupted
while the dj thinks that I am done with some line
get the line number
get the associated tty structure
if it is timed out, or done disable this line
get the next character
if it is a delay indication, schedule the restart
and disable this line
else set the character up for output
if there is a sleeping writer and the queue has drained some
wake him up
parameters:
the controller number for the dz11 that interrupted
globals:
dz11 pointers to the teletype structures for the dz11 lines
dzaddrs pointers to the dz11 controllers
calls:
wakeup
timeout
called by:
trap
*/
dzxint( unit )
int unit;
{ register struct dzregs *dzp;
register struct tty *tp;
register int lineno;
int c;
dzp = dzaddrs[ unit ];
unit =<< 3;
while( dzp->dzcsr&XINT )
{ lineno = (dzp->dzcsr&LINENUM) >> 8;
tp = &dz11[ lineno + unit ];
if ((tp->t_state&TIMEOUT) || ((tp->t_state&ISOPEN) == 0))
then goto disable;
if ((c = getc( &tp->t_outq )) < 0 )
then goto disable;
#ifdef UCLATTY
if (c == CESCAPE)
then c = getc( &tp->t_outq );
else
#endif
if (c & 0200) then
{ tp->t_state =| TIMEOUT;
if (c =& 0177)
then timeout( ttrstrt, tp, c&0177 );
#ifdef UCLATTY
else tp->t_state =| STOPOUT;
#endif
goto disable;
}
dzp->dztdr = c;
if ((tp->t_state&ASLEEP) && (tp->t_outq.c_cc <= TTLOWAT)) then
{ tp->t_state =& ~ASLEEP;
wakeup( &tp->t_outq );
}
continue;
disable:
dzp->dztcr =& ~(1 << lineno);
}
dzp->dzcsr =| IENABLE;
}
/* name:
dzstart
function:
to start an output operation on a dz line
algorithm:
if the line is timed out, do nothing
else enable it for transmission
parameters:
pointer to the tty structure for that line
globals:
dzaddrs pointers to addresses of dz11 controllers
dz11 table of tty structures for dz lines
calls:
wakeup to notify a sleeping writer
timeout to schedule resuming output
called by:
dzxint to continue an output operation
ttstart to initiate an output operation
*/
dzstart( atp )
struct tty *atp;
{ register struct dzregs *dzp;
register struct tty *tp;
register int lineno;
tp = atp;
if (tp->t_state&TIMEOUT)
then return;
lineno = tp - dz11;
dzp = dzaddrs[ lineno >> 3 ];
lineno =& 7;
dzp->dztcr =| (1 << lineno);
}
/* name:
dzsgtty
function:
dz11 sgtty system call routine
algorithm:
get a pointer to the corresponding tty structure
call ttystty
if anything changed, call dzparam
parameters:
major and minor device designation
argument vector pointer
globals:
dzaddrs addresses of dz11 controllers
calls:
ttystty device independent special function routine
called by:
sgtty (throught cdevsw)
*/
#ifdef UCLATTY
dzsgtty( dev )
int dev;
#endif
#ifndef UCLATTY
dzsgtty( dev , v )
int dev, *v;
#endif
{ register struct tty *tp;
register int unit;
unit = dev.d_minor;
tp = &dz11[ unit ];
#ifdef UCLATTY
if (ttystty( tp ))
#endif
#ifndef UCLATTY
if (ttystty( tp, v ))
#endif
then return;
else dzparam( unit );
}
/* name:
dzparam
function:
DZ11 parameter setting routine
algorithm:
ascertain what controller the specified unit is on
get a pointer to its tty structure
if the speed is set to 0, just turn the line off
else, compute the parametersd
and install them for that line
parameters:
DZ unit number
globals:
dzaddrs to get the controller addresses
dz11 tty structure for the dz lines
called by:
dzopen to initialize the line for the first time
dzsgtty to change parameters
*/
dzparam( unit )
int unit;
{ register struct dzregs *dzp;
register struct tty *tp;
register int parms;
int speed;
dzp = dzaddrs[ unit >> 3 ];
tp = &dz11[ unit ];
unit =& 7;
if (tp->t_speeds == 0) then
{ dzp->dzlpr = unit; /* just turn the line off */
return;
}
else
{ speed = tp->t_speeds&017;
speed = speedmap[ speed ];
}
parms = unit|RCV_ON;
parms =| (speed << 8);
if (tp->t_flags & EVENP) then
if (tp->t_flags & ODDP)
then parms =| BITS_8;
else parms =| (BITS_7|PENABLE);
else parms =| (BITS_7|OPAR|PENABLE);
if (tp->t_speeds.lobyte == 3)
then parms =| TWO_SB;
dzp->dzlpr = parms;
}
/* name:
dzstatus
function:
to see if the lines with modem control enabled still have the
appropriate signals up
algorithm:
For all open lines with modem control enabled,
if the carrier has dropped, send a hangup to the group
if any open lines still have modem control
schedule the next call to dzstatus
else turn off dzcycling
parameters:
none
globals:
dz11
dzmodem
dzcycling
calls:
timeout
called by:
timeout
*/
dzstatus()
{ register int line;
register struct tty *tp;
register struct dzregs *dzp;
int numlines;
numlines = 0;
for( line = 0; line < NDZ11; line++ )
{ dzp = dzaddrs[ line >> 3 ];
tp = &dz11[ line ];
if ((dzmodem[ line ] == 0) || ((tp->t_state&(ISOPEN+WOPEN)) == 0) )
then continue;
numlines++;
if (dzp->dzmsr & (0400 << (line&7))) then
{ tp->t_state =| CARR_ON;
if (tp->t_state&WOPEN)
then wakeup( tp );
}
else
{ tp->t_state =& ~CARR_ON;
if (tp->t_state & ISOPEN)
then signal( tp->t_pgrp, SIGHUP );
}
}
if (numlines) then
{ timeout( &dzstatus, 0, DZRATE );
dzcycling = true;
}
else dzcycling = false;
}