2.11BSD/sys/sys/sys_net.c
/*
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* @(#)sys_net.c 1.5 (2.11BSD GTE) 1997/2/16
*
* Print the csr of attached ethernet cards. sms - 1997/2/16
*
* Initialize the supervisor mode 'hz' variable via a call from the kernel
* rather compiling in a constant. sms - 1997/2/14
*
* Change uiomove calling convention. The r/w type is now encapsulated
* in the uio structure now. sms - 11/26/94
*
* 2.11BSD - map the I/O region with sufficient UMRs. this precludes
* drivers such as the DEUNA from allocating a UMR per packet.
* sms - 9/8/90
*/
#include "param.h"
#include "../machine/cons.h"
#include "../machine/psl.h"
#include "user.h"
#include "uio.h"
#include "map.h"
#include "uba.h"
#include "mbuf.h"
#include "acct.h"
#include "ioctl.h"
#include "tty.h"
#include "../pdpuba/ubavar.h"
#include "acc.h"
#if NACC > 0
extern struct uba_driver accdriver;
#endif
#include "css.h"
#if NCSS > 0
extern struct uba_driver cssdriver;
#endif
#include "de.h"
#if NDE > 0
extern struct uba_driver dedriver;
#endif
#include "ec.h"
#if NEC > 0
extern struct uba_driver ecdriver;
#endif
#include "il.h"
#if NIL > 0
extern struct uba_driver ildriver;
#endif
#include "qe.h"
#if NQE > 0
extern struct uba_driver qedriver;
#endif
#include "qt.h"
#if NQT > 0
extern struct uba_driver qtdriver;
#endif
#include "sri.h"
#if NSRI > 0
extern struct uba_driver sridriver;
#endif
#include "vv.h"
#if NVV > 0
extern struct uba_driver vvdriver;
#endif
static struct uba_device ubdinit[] = {
#if NDE > 0
{ &dedriver, 0,0, (caddr_t)0174510 },
#endif
#if NIL > 0
{ &ildriver, 0,0, (caddr_t)0164000 },
#endif
#if NQE > 0
{ &qedriver, 0,0, (caddr_t)0174440, 0, 0 },
#endif
#if NQE > 1
{ &qedriver, 1,0, (caddr_t)0174460, 0, 0 },
#endif
#if NQT > 0
{ &qtdriver, 0,0, (caddr_t)0174440, 0, 0 },
#endif
#if NQT > 1
{ &qtdriver, 1,0, (caddr_t)0174460, 0, 0 },
#endif
#if NSRI > 0
{ &sridriver, 0,0, (caddr_t)0167770 },
#endif
#if NVV > 0
{ &vvdriver, 0,0, (caddr_t)0161000 },
#endif
#if NEC > 0
{ &ecdriver, 0,0, (caddr_t)0164330 },
#endif
#if NACC > 0
{ &accdriver, 0,0, (caddr_t)0000000 },
#endif
#if NCSS > 0
{ &cssdriver, 0,0, (caddr_t)0000000 },
#endif
NULL,
};
int hz; /* kernel calls netsethz() to initialize */
long startnet; /* start of network data space */
void
netsethz(ticks)
int ticks;
{
hz = ticks;
}
netstart()
{
extern memaddr miobase, miostart, netdata;
extern ubadr_t mioumr;
extern u_short miosize;
register struct uba_driver *udp;
register struct uba_device *ui = ubdinit;
register int s;
char *attaching = "attaching ";
int first;
struct ubmap *ubp;
ubadr_t paddr;
/*
* The networking uses a mapped region as the DMA area for
* network interface drivers. Allocate this latter region.
*/
if ((miobase = MALLOC(coremap, btoc(miosize))) == 0)
panic("miobase");
/*
* Allocate sufficient UMRs to map the DMA region. Save the
* starting click and UNIBUS addresses for use in ubmalloc later.
* This is early in the systems life, so there had better be
* sufficient UMRs available!
*/
if (mfkd(&ubmap)) {
miostart = miobase;
s = (int)btoub(miosize);
first = MALLOC(ub_map, s);
#ifdef DIAGNOSTIC
if (!first)
panic("ub_map");
#endif
mioumr = (ubadr_t)first << 13;
ubp = &UBMAP[first];
paddr = ctob((ubadr_t)miostart);
while (s--) {
ubp->ub_lo = loint(paddr);
ubp->ub_hi = hiint(paddr);
ubp++;
paddr += (ubadr_t)UBPAGE;
}
}
startnet = ctob((long)mfkd(&netdata));
mbinit();
for (ui = ubdinit; udp = ui->ui_driver; ++ui) {
if (badaddr(ui->ui_addr, 2))
continue;
ui->ui_alive = 1;
udp->ud_dinfo[ui->ui_unit] = ui;
printf("%s%s%d csr %o\n", attaching,udp->ud_dname,ui->ui_unit,
ui->ui_addr);
(*udp->ud_attach)(ui);
}
#include "sl.h"
#if NSL > 0
printf("%ssl\n", attaching);
slattach();
#endif
#include "loop.h"
#if NLOOP > 0
printf("%slo0\n", attaching);
loattach();
#endif
s = splimp();
ifinit();
domaininit(); /* must follow interfaces */
splx(s);
}
/*
* Panic is called on fatal errors. It prints "net panic: mesg" and
* then calls the kernel entry netcrash() to bring down the net.
*/
panic(s)
register char *s;
{
printf("net panic: %s\n", s);
NETCRASH();
/* NOTREACHED */
}
netcopyout(m, to, len)
struct mbuf *m;
char *to;
int *len;
{
if (*len > m->m_len)
*len = m->m_len;
return(copyout(mtod(m, caddr_t), to, *len));
}
/*
* These routines are copies of various kernel routines that are required in
* the supervisor space by the networking. DO NOT MODIFY THESE ROUTINES!
* Modify the kernel version and bring a copy here. The "#ifdef notdef"
* modifications simplify by eliminating portions of routines not required
* by the networking.
*/
/* copied from kern_descrip.c */
ufavail()
{
register int i, avail = 0;
for (i = 0; i < NOFILE; i++)
if (u.u_ofile[i] == NULL)
avail++;
return (avail);
}
/* copied from kern_descrip.c */
ufalloc(i)
register int i;
{
for (; i < NOFILE; i++)
if (u.u_ofile[i] == NULL) {
u.u_r.r_val1 = i;
u.u_pofile[i] = 0;
if (i > u.u_lastfile)
u.u_lastfile = i;
return (i);
}
u.u_error = EMFILE;
return (-1);
}
/* copied from ufs_fio.c */
suser()
{
if (u.u_uid == 0) {
u.u_acflag |= ASU;
return (1);
}
u.u_error = EPERM;
return (0);
}
/* copied from kern_sysctl.c */
sysctl_int(oldp, oldlenp, newp, newlen, valp)
void *oldp;
size_t *oldlenp;
void *newp;
size_t newlen;
int *valp;
{
int error = 0;
if (oldp && *oldlenp < sizeof(int))
return (ENOMEM);
if (newp && newlen != sizeof(int))
return (EINVAL);
*oldlenp = sizeof(int);
if (oldp)
error = copyout(valp, oldp, sizeof(int));
if (error == 0 && newp)
error = copyin(newp, valp, sizeof(int));
return (error);
}
/*
* An old version of uiomove, as uiofmove() and vcopy{in,out}() don't
* exist in supervisor space. Note, we assume that all transfers will
* be to/from user D space. Probably safe, until someone decides to
* put NFS into the kernel.
*
* The 4.3BSD uio/iovec paradigm adopted, ureadc() and uwritec() inlined
* at that time to speed things up. 3/90 sms
*/
uiomove(cp, n, uio)
caddr_t cp;
u_int n;
register struct uio *uio;
{
register struct iovec *iov;
int error, count, ch;
register u_int cnt;
#ifdef DIAGNOSTIC
if (uio->uio_segflg != UIO_USERSPACE)
panic("net uiomove");
#endif
while (n && uio->uio_resid) {
iov = uio->uio_iov;
cnt = iov->iov_len;
if (cnt == 0) {
uio->uio_iov++;
uio->uio_iovcnt--;
continue;
}
if (cnt > n)
cnt = n;
count = cnt;
if ((cnt | (int)cp | (int)iov->iov_base) & 1) {
if (uio->uio_rw == UIO_READ) {
while (cnt--)
if (subyte(iov->iov_base++, *cp++) < 0)
return (EFAULT);
}
else {
while (cnt--) {
if ((ch = fubyte(iov->iov_base++)) < 0)
return (EFAULT);
*cp++ = ch;
}
}
cnt = count; /* use register */
}
else {
if (uio->uio_rw == UIO_READ)
error = copyout(cp, iov->iov_base, cnt);
else
error = copyin(iov->iov_base, cp, cnt);
if (error)
return (error);
iov->iov_base += cnt;
cp += cnt;
}
iov->iov_len -= cnt;
uio->uio_resid -= cnt;
uio->uio_offset += cnt;
n -= cnt;
}
return (0);
}
#define TOCONS 0x1
#define TOTTY 0x2
#define TOLOG 0x4
/* copied from subr_prf.c */
/*VARARGS1*/
printf(fmt, x1)
char *fmt;
unsigned x1;
{
prf(fmt, &x1, TOCONS | TOLOG);
}
/* copied from subr_prf.c */
prf(fmt, adx, flags)
register char *fmt;
register u_int *adx;
int flags;
{
register int c;
u_int b;
char *s;
int i, any;
loop:
while ((c = *fmt++) != '%') {
if (c == '\0')
return;
_pchar(c, flags);
}
c = *fmt++;
switch (c) {
case 'l':
c = *fmt++;
switch(c) {
case 'x':
b = 16;
goto lnumber;
case 'd':
b = 10;
goto lnumber;
case 'o':
b = 8;
goto lnumber;
default:
_pchar('%', flags);
_pchar('l', flags);
_pchar(c, flags);
}
break;
case 'X':
b = 16;
goto lnumber;
case 'D':
b = 10;
goto lnumber;
case 'O':
b = 8;
lnumber: printn(*(long *)adx, b, flags);
adx += (sizeof(long) / sizeof(int)) - 1;
break;
case 'x':
b = 16;
goto number;
case 'd':
case 'u': /* what a joke */
b = 10;
goto number;
case 'o':
b = 8;
number: printn((long)*adx, b, flags);
break;
case 'c':
_pchar(*adx, flags);
break;
case 'b':
b = *adx++;
s = (char *)*adx;
printn((long)b, *s++, flags);
any = 0;
if (b) {
while (i = *s++) {
if (b & (1 << (i - 1))) {
_pchar(any? ',' : '<', flags);
any = 1;
for (; (c = *s) > 32; s++)
_pchar(c, flags);
} else
for (; *s > 32; s++)
;
}
if (any)
_pchar('>', flags);
}
break;
case 's':
s = (char *)*adx;
while (c = *s++)
_pchar(c, flags);
break;
case '%':
_pchar(c, flags);
break;
default:
_pchar('%', flags);
_pchar(c, flags);
break;
}
adx++;
goto loop;
}
/* copied from subr_prf.c */
printn(n, b, flags)
long n;
u_int b;
{
char prbuf[12];
register char *cp = prbuf;
register int offset = 0;
if (n<0)
switch(b) {
case 8: /* unchecked, but should be like hex case */
case 16:
offset = b-1;
n++;
break;
case 10:
_pchar('-', flags);
n = -n;
break;
}
do {
*cp++ = "0123456789ABCDEF"[offset + n%b];
} while (n = n/b); /* Avoid n /= b, since that requires alrem */
do
_pchar(*--cp, flags);
while (cp > prbuf);
}
extern int putchar();
_pchar(c, flg)
int c, flg;
{
return(SKcall(putchar, sizeof(int)+sizeof(int)+sizeof(struct tty *),
c, flg, (struct tty *)0));
}