Compare commits

...
Author SHA1 Message Date
cvs2svn c37538200e This commit was manufactured by cvs2svn to create tag
'RELENG_3_2_0_RELEASE'.
1999-05-24 16:47:10 +00:00
70 changed files with 2140 additions and 29501 deletions

No files matched your search

+7
View File
@@ -230,6 +230,10 @@
.if "\\$1"FreeBSD" \{\
. if "\\$2"2" .ds oS FreeBSD 2.0
. ie \\n(.$==1 \c
. el .ie "\\$2"1.0" \c
. el .ie "\\$2"1.1" \c
. el .ie "\\$2"1.1.5" \c
. el .ie "\\$2"1.1.5.1" \c
. el .ie "\\$2"2" \c
. el .ie "\\$2"2.0" \c
. el .ie "\\$2"2.0.5" \c
@@ -238,12 +242,15 @@
. el .ie "\\$2"2.1.6" \c
. el .ie "\\$2"2.1.7" \c
. el .ie "\\$2"2.2" \c
. el .ie "\\$2"2.2.1" \c
. el .ie "\\$2"2.2.2" \c
. el .ie "\\$2"2.2.5" \c
. el .ie "\\$2"2.2.6" \c
. el .ie "\\$2"2.2.7" \c
. el .ie "\\$2"2.2.8" \c
. el .ie "\\$2"3.0" \c
. el .ie "\\$2"3.1" \c
. el .ie "\\$2"3.2" \c
. el .ie "\\$2"4.0" \c
. el .tm Unknown FreeBSD version ``\\$2'' at line \\n(c.
.\}
+1
View File
@@ -171,6 +171,7 @@
.el .ie "\\$1"2.2.8" \c
.el .ie "\\$1"3.0" \c
.el .ie "\\$1"3.1" \c
.el .ie "\\$1"3.2" \c
.el .ie "\\$1"4.0" \c
.el .ie "\\$1"," .rm ab \" Allow ".Fx ,"
.el .ie "\\$1"." .rm ab \" Allow ".Fx ."
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-165
View File
@@ -1,165 +0,0 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Hacked version of print-ether.c Larry Lile <[email protected]>
*/
#ifndef lint
static const char rcsid[] =
"@(#) $Header$";
#endif
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#if __STDC__
struct mbuf;
struct rtentry;
#endif
#include <net/if.h>
#include "token.h"
#include <netinet/in.h>
#include <net/ethernet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <stdio.h>
#include <pcap.h>
#include "interface.h"
#include "addrtoname.h"
#include "ethertype.h"
#include "llc.h"
const u_char *packetp;
const u_char *snapend;
static inline void
token_print(register const u_char *bp, u_int length)
{
register const struct token_header *tp;
register const struct llc *lp;
u_short ether_type;
tp = (const struct token_header *)bp;
lp = (struct llc *)(bp + TOKEN_HDR_LEN);
if (IS_SOURCE_ROUTED)
lp = (struct llc *)(bp + TOKEN_HDR_LEN + RIF_LENGTH);
/*
* Ethertype on ethernet is a short, but ethertype in an llc-snap has
* been defined as 2 u_chars. This is a stupid little hack to fix
* this for now but something better should be done using ntohs()
* XXX
*/
ether_type = ((u_short)lp->ethertype[1] << 16) | lp->ethertype[0];
if (qflag)
(void)printf("%s %s %d: ",
etheraddr_string(ESRC(tp)),
etheraddr_string(EDST(tp)),
length);
else
(void)printf("%s %s %s %d: ",
etheraddr_string(ESRC(tp)),
etheraddr_string(EDST(tp)),
etherproto_string(ether_type),
length);
}
/*
* This is the top level routine of the printer. 'p' is the points
* to the ether header of the packet, 'tvp' is the timestamp,
* 'length' is the length of the packet off the wire, and 'caplen'
* is the number of bytes actually captured.
*/
void
token_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
struct token_header *tp;
u_short ether_type;
extern u_short extracted_ethertype;
u_int route_len = 0;
struct llc *lp;
tp = (struct token_header *)p;
ts_print(&h->ts);
if (caplen < TOKEN_HDR_LEN) {
printf("[|token-ring]");
goto out;
}
if (eflag)
token_print(p, length);
/*
* Some printers want to get back at the ethernet addresses,
* and/or check that they're not walking off the end of the packet.
* Rather than pass them all the way down, we set these globals.
*/
tp = (struct token_header *)p;
/* Adjust for source routing information in the MAC header */
if (IS_SOURCE_ROUTED) {
route_len = RIF_LENGTH;
}
/* Set pointer to llc header, adjusted for routing information */
lp = (struct llc *)(p + TOKEN_HDR_LEN + route_len);
packetp = p;
snapend = p + caplen;
/* Skip over token ring MAC header */
length -= TOKEN_HDR_LEN + route_len;
caplen -= TOKEN_HDR_LEN + route_len;
p += TOKEN_HDR_LEN + route_len;
ether_type = ntohs((int)lp->ethertype);
extracted_ethertype = 0;
/* Try to print the LLC-layer header & higher layers */
if (llc_print(p, length, caplen, ESRC(tp), EDST(tp)) == 0) {
/* ether_type not known, print raw packet */
if (!eflag)
token_print((u_char *)tp, length);
if (extracted_ethertype) {
printf("(LLC %s) ",
etherproto_string(htons(extracted_ethertype)));
}
if (!xflag && !qflag)
default_print(p, caplen);
}
if (xflag)
default_print(p, caplen);
out:
putchar('\n');
}
-43
View File
@@ -1,43 +0,0 @@
/*
* Copyright (c) 1998, Larry Lile
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#define TOKEN_HDR_LEN 14
#define IS_SOURCE_ROUTED (tp->ether_shost[0] & 0x80)
#define RIF_LENGTH ((ntohs(tp->rcf) & 0x1f00) >> 8)
#define TOKEN_RING_MAC_LEN 6
#define ROUTING_SEGMENT_MAX 16
struct token_header {
u_char ac;
u_char fc;
u_char ether_dhost[TOKEN_RING_MAC_LEN];
u_char ether_shost[TOKEN_RING_MAC_LEN];
u_short rcf;
u_short rseg[ROUTING_SEGMENT_MAX];
};
-8
View File
@@ -1,8 +0,0 @@
# $Id$
#
# This file is required by the ISC DHCP client.
# See ``man 5 dhclient.conf'' for details.
#
# In most cases an empty file is suffient for most people as the
# defaults are usually fine.
#
+6 -4
View File
@@ -1,4 +1,4 @@
# $Id: Makefile,v 1.1 1999/05/08 17:53:43 obrien Exp $
# $Id: Makefile,v 1.3 1999/05/21 18:37:33 obrien Exp $
DISTRIBUTION= compat22
@@ -12,16 +12,18 @@ LIBS= libalias.so.2.4 libc.so.3.1 libc_r.so.3.0 libcalendar.so.2.0 \
libtelnet.so.2.0 libtermcap.so.2.1 libutil.so.2.2 libvgl.so.1.0 \
libxpg4.so.2.0 libz.so.2.0
CLEANFILES+= ${LIBS}
CLEANFILES+= ${LIBS} ld.so
all: ${LIBS}
all: ${LIBS} ld.so
.for lib in ${LIBS}
.for lib in ${LIBS} ld.so
${lib}: ${lib}.gz.uu
uudecode -p ${.CURDIR}/${lib}.gz.uu | gunzip > ${lib}
.endfor
beforeinstall:
${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} ld.so \
${DESTDIR}/usr/libexec
${INSTALL} ${COPY} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} ${LIBS} \
${DESTDIR}${LIBCOMPATDIR}/aout
@${ECHO} "libcrypt.so.2.0 -> libscrypt.so.2.0" ; \
+702
View File
@@ -0,0 +1,702 @@
begin 555 ld.so.gz
M'XL("+G*_38"`VQD+G-O`.V]#7Q4Q=4X?/<CR28L[((K!(VZ:E`0A`016`1,
M`AL^RD*(;()?C8%L()@ODGN30-DD>!/-Y;*Z?8#6MK8/[8,M;:E2$8G*1X(T
M`8L:@2IHT$AIO>NF&FV$A:[L>\[,W/T(H#Y]GO?__G^_UX7)W/D^<^;,F3,S
M9V:.<H^W<7T<QUDY;BE'?U8N\G-*?[M/P8\'U[\V!>+)=J/,R8,T[8M#@C$D
M&'2B'@)#7>(AXX-'7H/8CZ2WR8*^6(X7/XW/R5.:((UXR"#9]85'7J/YR7:#
M[#2?RTC(X.-DAU&3=.2U687EY16\M=K%6Y=5N0H?K:PH*>>MHT=5C^%84)7K
MSLJJ"MZU_/(8F&=^7AC*'WZ&4!K$MDMB0%,S0G0;]/Q0^*OA![6&X.?;I^4X
MK^PPRYD&*%ZG@4\)/BLMZ$J7ZY)U-MNEZIN]7G$FQU\GQY-(.:'T/.5>2"YV
M&*"NMDM5'T&>NOHA\B8#E`MQY,P420M^VGHC<25+8I<.0DBX.(T3#![Q!'B0
M2)#0(_;J2$(IT^HW89+%1NHG91EET<AR76R6S$HVU$D2S==RG#*+?%KP,X-\
M)N/G#/*9`I^>75;XFWY,)M%M)*8P1";1;"0&'_>*!C*7ABO_O(64$5IM7,7A
MO]`NA%CIAR:5.N3LE%!&,OQMG)NB"0EFC)B.L6@U<I0W,-I!.8M$R\)H6O'0
M:%*Y%$@F#]?EC).SD^4,@R['P"?F*EL_15K04_O5-`"%XTU*1R*X`B$A3CD*
MA)>GG$DBL:C7RU:,.HE$M4"5D-;2E$T`_RI.>>13AGBCG&.@@4";&0;`\*NI
MF,2TI6U4"&R@P^E&0H<TU^76<,)*O2Q:2$(IVR+6ZSE34PLZUUC6?\SUA4*K
M$E9RD'&^\J]_8`9&S&`$Q9-'O,T<"N6LTB@?0YC7Z_5DFW,(.BW*:?!9%<>2
MMI&D%DQJ49-FLJ0[_L%`L4C91EH'<2K')W1F&["1E*>361,9E!]"U%:@7<[C
MZG_P^P5'7ELPNV!);N8L>\&"19FS[;,+%F7-M\]:<E]!3NZB.0LS'7:.NUJ,
M;,>2="[QSM)1%>-'E5EGS+2.JH2^5#<FZ>M23.021U6P:-@EBRN$\B)N5#4W
M"OY6TKXM]J9$=<7X7JSJ0]=`597WX5NR]T/+-K<)B9Y=;O"5A'Z/6$^"]Y+@
M8#CX9R0XZ!%WDN"?D^!`./@-$AP`8H,&FP9(D06#7&.4A+[F<Z:F9/28+`F]
MZ)N=(M;I.7Z(G*&7<U)D3I<U3F,G(35Z25":SV%^[Y+\%-D=D(6^<]EZC:FI
M$_`ONX.^`QIL7/'"*%/36]@Z%Q[BL^[email protected]_B-K!LM9C]BR*ANN
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
MWY'(9X;-WMKPYTBB9#[email protected]^);R'K=9!^I+R/IH^.0+P8M`.J*5VD1[!,
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
M$`&/^UY1ZP%][-ZJ<%D/3B")O@^)$$U?362D,`"?DR80_&/+WM"[email protected]=Y!\G
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
MLZ!*#JHEH6XNZN6B3B[JX[8R]1E4&7H5##[email protected]/*&:@=M8%!]`E58\%`F
MROEXARG>]HGZIH?!X+MZ>)OGG\'@^])OH"X)F+?`X+0!'Q8ZQE%]U!-@_@+F
M'3#O@L&WO$ZAK@)']5/QY:_38/`Y[P_!]*#>`I@S'-571=69OZ$N"IB/P>!1
M4A^83SBJOXIW.?T#S*=@/J-3$PYOZ/^"H_JL>/0?IAS<.=17`8/'CB^`N<A1
M_5:\A>PK,)?`A+[K_Z3_9S*1!L^RX)D(5)?!LQ!X#@+/0.#Y!SS[@.<>\!P&
MGGO`^1Z>>\`S#WC>`<\ZX#D'/..`>M5XM@'/->"9!CS/\,#7]/__4^5_U_^_
MZ_]7ZO]?N[;R9:S.'/9U+DGSM?,2HB^91?4<<?U"U1?^[Z_KQ)9S]'\IWZ0!
M@F^J]M_/=R7`I&-UM@[XI0WX#4P;QWBC.^S3-^#MTONIG?$4M5M>H_:J`+$;
MF\832+N&+2=VT[L_)K;KC3?0MA9LU2);46KF3D'[5YNO*P,[XV_/I/T*;.^-
MA_:^`_:DV[Y\U#B+:^R9LN:US%G<UI/-^9-J9G&'%ZXH:__]+&[&#Q\YN_2C
M61D;=]?=\/RULW,^._/.V>N^-_L__N*(?ZNO<;::;D1YW.[=K9NRO[QPKT^W
M:*ICX@UI%^;6/O;`]`/5#:<772OLE4[^^(5CSTR_ZS?;_W+KN7FV&;_IG_V5
MZ=F)/__QQK<,KSPX:E;%CJ+1\8>3HO'C+'^TO**V7+UY\QO;XJ&=>%@;Q@HP
MUX'1@OD,F,0I,`?![`3S#!@)3`68I6"RP4P#DPHF&8P1S$5@+B?!'`;S,ICM
M8#:`J0&3#V8N&!N8F\%8P%P"AO09F+^".0CFCV"\8&K`+`5C`Y,"9A"87F!@
M?P&S'\PV,!O!E(.9">9V,`8P`6!T'X'9!^89,"*8$C`.,'>#L8#Y`ACB!V#^
M#.:W8'X$1@)3!Z8(S&(P66#&@TD&<PZ8Z%DPQ\#L![,=S)-@?@!F&9B,WX9I
EL.&[&=%WO^]^W_V^^WWW^^[WW>^[WW>__YM__P\[+-(F`!`!``!F
`
end
-8
View File
@@ -1,8 +0,0 @@
# $Id:$
PROG= mutex
SRCS= mutex.c
NOMAN= 1
LDFLAGS= -pthread
.include <bsd.prog.mk>
File diff suppressed because it is too large. Load diff
+7 -1
View File
@@ -164,12 +164,18 @@ pthread_exit(void *status)
if (pthread_cond_signal(&_gc_cond) != 0)
PANIC("Cannot signal gc cond");
/*
* Mark the thread as dead so it will not return if it
* gets context switched out when the mutex is unlocked.
*/
PTHREAD_SET_STATE(_thread_run, PS_DEAD);
/* Unlock the garbage collector mutex: */
if (pthread_mutex_unlock(&_gc_mutex) != 0)
PANIC("Cannot lock gc mutex");
/* This this thread will never be re-scheduled. */
_thread_kern_sched_state(PS_DEAD, __FILE__, __LINE__);
_thread_kern_sched(NULL);
/* This point should not be reached. */
PANIC("Dead thread has resumed");
+6 -186
View File
@@ -29,7 +29,6 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: uthread_priority_queue.c,v 1.2 1999/06/20 08:28:37 jb Exp $
*/
#include <stdlib.h>
#include <sys/queue.h>
@@ -41,51 +40,9 @@
/* Prototypes: */
static void pq_insert_prio_list(pq_queue_t *pq, int prio);
#if defined(_PTHREADS_INVARIANTS)
static int _pq_active = 0;
#define _PQ_IN_SCHEDQ (PTHREAD_FLAGS_IN_PRIOQ | PTHREAD_FLAGS_IN_WAITQ | PTHREAD_FLAGS_IN_WORKQ)
#define _PQ_SET_ACTIVE() _pq_active = 1
#define _PQ_CLEAR_ACTIVE() _pq_active = 0
#define _PQ_ASSERT_ACTIVE(msg) do { \
if (_pq_active == 0) \
PANIC(msg); \
} while (0)
#define _PQ_ASSERT_INACTIVE(msg) do { \
if (_pq_active != 0) \
PANIC(msg); \
} while (0)
#define _PQ_ASSERT_IN_WAITQ(thrd, msg) do { \
if (((thrd)->flags & PTHREAD_FLAGS_IN_WAITQ) == 0) \
PANIC(msg); \
} while (0)
#define _PQ_ASSERT_IN_PRIOQ(thrd, msg) do { \
if (((thrd)->flags & PTHREAD_FLAGS_IN_PRIOQ) == 0) \
PANIC(msg); \
} while (0)
#define _PQ_ASSERT_NOT_QUEUED(thrd, msg) do { \
if ((thrd)->flags & _PQ_IN_SCHEDQ) \
PANIC(msg); \
} while (0)
#else
#define _PQ_SET_ACTIVE()
#define _PQ_CLEAR_ACTIVE()
#define _PQ_ASSERT_ACTIVE(msg)
#define _PQ_ASSERT_INACTIVE(msg)
#define _PQ_ASSERT_IN_WAITQ(thrd, msg)
#define _PQ_ASSERT_IN_PRIOQ(thrd, msg)
#define _PQ_ASSERT_NOT_QUEUED(thrd, msg)
#define _PQ_CHECK_PRIO()
#endif
int
_pq_alloc(pq_queue_t *pq, int minprio, int maxprio)
_pq_init(pq_queue_t *pq, int minprio, int maxprio)
{
int i, ret = 0;
int prioslots = maxprio - minprio + 1;
@@ -98,27 +55,9 @@ _pq_alloc(pq_queue_t *pq, int minprio, int maxprio)
(pq_list_t *) malloc(sizeof(pq_list_t) * prioslots)) == NULL)
ret = -1;
else {
/* Remember the queue size: */
pq->pq_size = prioslots;
ret = _pq_init(pq);
}
return (ret);
}
int
_pq_init(pq_queue_t *pq)
{
int i, ret = 0;
if ((pq == NULL) || (pq->pq_lists == NULL))
ret = -1;
else {
/* Initialize the queue for each priority slot: */
for (i = 0; i < pq->pq_size; i++) {
for (i = 0; i < prioslots; i++) {
TAILQ_INIT(&pq->pq_lists[i].pl_head);
pq->pq_lists[i].pl_prio = i;
pq->pq_lists[i].pl_queued = 0;
@@ -126,7 +65,9 @@ _pq_init(pq_queue_t *pq)
/* Initialize the priority queue: */
TAILQ_INIT(&pq->pq_queue);
_PQ_CLEAR_ACTIVE();
/* Remember the queue size: */
pq->pq_size = prioslots;
}
return (ret);
}
@@ -136,27 +77,7 @@ _pq_remove(pq_queue_t *pq, pthread_t pthread)
{
int prio = pthread->active_priority;
/*
* Make some assertions when debugging is enabled:
*/
_PQ_ASSERT_INACTIVE("_pq_remove: pq_active");
_PQ_SET_ACTIVE();
_PQ_ASSERT_IN_PRIOQ(pthread, "_pq_remove: Not in priority queue");
/*
* Remove this thread from priority list. Note that if
* the priority list becomes empty, it is not removed
* from the priority queue because another thread may be
* added to the priority list (resulting in a needless
* removal/insertion). Priority lists are only removed
* from the priority queue when _pq_first is called.
*/
TAILQ_REMOVE(&pq->pq_lists[prio].pl_head, pthread, pqe);
/* This thread is now longer in the priority queue. */
pthread->flags &= ~PTHREAD_FLAGS_IN_PRIOQ;
_PQ_CLEAR_ACTIVE();
}
@@ -165,23 +86,10 @@ _pq_insert_head(pq_queue_t *pq, pthread_t pthread)
{
int prio = pthread->active_priority;
/*
* Make some assertions when debugging is enabled:
*/
_PQ_ASSERT_INACTIVE("_pq_insert_head: pq_active");
_PQ_SET_ACTIVE();
_PQ_ASSERT_NOT_QUEUED(pthread,
"_pq_insert_head: Already in priority queue");
TAILQ_INSERT_HEAD(&pq->pq_lists[prio].pl_head, pthread, pqe);
if (pq->pq_lists[prio].pl_queued == 0)
/* Insert the list into the priority queue: */
pq_insert_prio_list(pq, prio);
/* Mark this thread as being in the priority queue. */
pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ;
_PQ_CLEAR_ACTIVE();
}
@@ -190,23 +98,10 @@ _pq_insert_tail(pq_queue_t *pq, pthread_t pthread)
{
int prio = pthread->active_priority;
/*
* Make some assertions when debugging is enabled:
*/
_PQ_ASSERT_INACTIVE("_pq_insert_tail: pq_active");
_PQ_SET_ACTIVE();
_PQ_ASSERT_NOT_QUEUED(pthread,
"_pq_insert_tail: Already in priority queue");
TAILQ_INSERT_TAIL(&pq->pq_lists[prio].pl_head, pthread, pqe);
if (pq->pq_lists[prio].pl_queued == 0)
/* Insert the list into the priority queue: */
pq_insert_prio_list(pq, prio);
/* Mark this thread as being in the priority queue. */
pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ;
_PQ_CLEAR_ACTIVE();
}
@@ -216,12 +111,6 @@ _pq_first(pq_queue_t *pq)
pq_list_t *pql;
pthread_t pthread = NULL;
/*
* Make some assertions when debugging is enabled:
*/
_PQ_ASSERT_INACTIVE("_pq_first: pq_active");
_PQ_SET_ACTIVE();
while (((pql = TAILQ_FIRST(&pq->pq_queue)) != NULL) &&
(pthread == NULL)) {
if ((pthread = TAILQ_FIRST(&pql->pl_head)) == NULL) {
@@ -235,8 +124,6 @@ _pq_first(pq_queue_t *pq)
pql->pl_queued = 0;
}
}
_PQ_CLEAR_ACTIVE();
return (pthread);
}
@@ -246,15 +133,10 @@ pq_insert_prio_list(pq_queue_t *pq, int prio)
{
pq_list_t *pql;
/*
* Make some assertions when debugging is enabled:
*/
_PQ_ASSERT_ACTIVE("pq_insert_prio_list: pq_active");
/*
* The priority queue is in descending priority order. Start at
* the beginning of the queue and find the list before which the
* new list should be inserted.
* new list should to be inserted.
*/
pql = TAILQ_FIRST(&pq->pq_queue);
while ((pql != NULL) && (pql->pl_prio > prio))
@@ -270,66 +152,4 @@ pq_insert_prio_list(pq_queue_t *pq, int prio)
pq->pq_lists[prio].pl_queued = 1;
}
#if defined(_PTHREADS_INVARIANTS)
void
_waitq_insert(pthread_t pthread)
{
pthread_t tid;
/*
* Make some assertions when debugging is enabled:
*/
_PQ_ASSERT_INACTIVE("_waitq_insert: pq_active");
_PQ_SET_ACTIVE();
_PQ_ASSERT_NOT_QUEUED(pthread, "_waitq_insert: Already in queue");
if (pthread->wakeup_time.tv_sec == -1)
TAILQ_INSERT_TAIL(&_waitingq, pthread, pqe);
else {
tid = TAILQ_FIRST(&_waitingq);
while ((tid != NULL) && (tid->wakeup_time.tv_sec != -1) &&
((tid->wakeup_time.tv_sec < pthread->wakeup_time.tv_sec) ||
((tid->wakeup_time.tv_sec == pthread->wakeup_time.tv_sec) &&
(tid->wakeup_time.tv_nsec <= pthread->wakeup_time.tv_nsec))))
tid = TAILQ_NEXT(tid, pqe);
if (tid == NULL)
TAILQ_INSERT_TAIL(&_waitingq, pthread, pqe);
else
TAILQ_INSERT_BEFORE(tid, pthread, pqe);
}
pthread->flags |= PTHREAD_FLAGS_IN_WAITQ;
_PQ_CLEAR_ACTIVE();
}
void
_waitq_remove(pthread_t pthread)
{
/*
* Make some assertions when debugging is enabled:
*/
_PQ_ASSERT_INACTIVE("_waitq_remove: pq_active");
_PQ_SET_ACTIVE();
_PQ_ASSERT_IN_WAITQ(pthread, "_waitq_remove: Not in queue");
TAILQ_REMOVE(&_waitingq, pthread, pqe);
pthread->flags &= ~PTHREAD_FLAGS_IN_WAITQ;
_PQ_CLEAR_ACTIVE();
}
void
_waitq_setactive(void)
{
_PQ_ASSERT_INACTIVE("_waitq_setactive: pq_active");
_PQ_SET_ACTIVE();
}
void
_waitq_clearactive(void)
{
_PQ_ASSERT_ACTIVE("_waitq_clearactive: ! pq_active");
_PQ_CLEAR_ACTIVE();
}
#endif
#endif
+8 -8
View File
@@ -29,7 +29,6 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: uthread_setschedparam.c,v 1.2 1999/06/20 08:28:44 jb Exp $
*/
#include <errno.h>
#include <sys/param.h>
@@ -51,10 +50,10 @@ pthread_setschedparam(pthread_t pthread, int policy, struct sched_param *param)
/* Find the thread in the list of active threads: */
else if ((ret = _find_thread(pthread)) == 0) {
/*
* Defer signals to protect the scheduling queues from
* access by the signal handler:
* Guard against being preempted by a scheduling
* signal:
*/
_thread_kern_sig_defer();
_thread_kern_sched_defer();
if (param->sched_priority != pthread->base_priority) {
/*
@@ -62,7 +61,8 @@ pthread_setschedparam(pthread_t pthread, int policy, struct sched_param *param)
* queue before any adjustments are made to its
* active priority:
*/
if ((pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) != 0) {
if ((pthread != _thread_run) &&
(pthread->state == PS_RUNNING)) {
in_readyq = 1;
old_prio = pthread->active_priority;
PTHREAD_PRIOQ_REMOVE(pthread);
@@ -103,10 +103,10 @@ pthread_setschedparam(pthread_t pthread, int policy, struct sched_param *param)
pthread->attr.sched_policy = policy;
/*
* Undefer and handle pending signals, yielding if
* necessary:
* Renable preemption and yield if a scheduling signal
* arrived while in the critical region:
*/
_thread_kern_sig_undefer();
_thread_kern_sched_undefer();
}
return(ret);
}
+2 -2
View File
@@ -21,7 +21,7 @@
*
* High-level routines relating to use of the user capabilities database
*
* $Id$
* $Id: login_class.c,v 1.9 1998/07/28 01:30:16 ache Exp $
*/
#include <stdio.h>
@@ -163,7 +163,7 @@ substvar(char * var, const struct passwd * pwd, int hlen, int pch, int nlen)
while (*(p += strcspn(p, "~$")) != '\0') {
int l = strlen(p);
if (p > np && *(p-1) == '\\') /* Escaped: */
if (p > var && *(p-1) == '\\') /* Escaped: */
memmove(p - 1, p, l + 1); /* Slide-out the backslash */
else if (*p == '~') {
int v = pch && *(p+1) != '/'; /* Avoid double // */
+6 -4
View File
@@ -4,7 +4,7 @@
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $Id: config.c,v 1.115.2.17 1999/05/14 15:04:45 jkh Exp $
* $Id: config.c,v 1.115.2.19 1999/05/15 15:05:23 jkh Exp $
*
* Copyright (c) 1995
* Jordan Hubbard. All rights reserved.
@@ -514,7 +514,7 @@ configXDesktop(dialogMenuItem *self)
else if (!strcmp(desk, "windowmaker")) {
ret = package_add("windowmaker");
if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("wmaker.inst")) {
write_root_xprofile("xterm &\n[ ! -d $HOME/GNUstep/Library/WindowMaker ] && /usr/X11R6/bin/wmaker.inst && exec /usr/X11R6/bin/wmaker\n");
write_root_xprofile("xterm &\n[ ! -d $HOME/GNUstep/Library/WindowMaker ] && /usr/X11R6/bin/wmaker.inst\nexec /usr/X11R6/bin/wmaker\n");
}
}
else if (!strcmp(desk, "enlightenment")) {
@@ -552,9 +552,11 @@ tryagain:
}
if (file_readable("/var/run/ld.so.hints"))
systemExecute("/sbin/ldconfig -m /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
vsystem("/sbin/ldconfig -m /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
else
systemExecute("/sbin/ldconfig /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
vsystem("/sbin/ldconfig /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
vsystem("/sbin/ldconfig -aout /usr/lib/compat/aout /usr/lib/aout /usr/X11R6/lib/aout /usr/local/lib/aout");
vsystem("/sbin/ifconfig lo0 127.0.0.1");
execfile = string_concat("/usr/X11R6/bin/", config);
if (file_executable(execfile)) {
dialog_clear_norefresh();
+2 -1
View File
@@ -4,7 +4,7 @@
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $Id: package.c,v 1.65.2.7 1999/05/14 14:58:17 jkh Exp $
* $Id: package.c,v 1.65.2.8 1999/05/15 14:38:44 jkh Exp $
*
* Copyright (c) 1995
* Jordan Hubbard. All rights reserved.
@@ -126,6 +126,7 @@ package_extract(Device *dev, char *name, Boolean depended)
/* If necessary, initialize the ldconfig hints */
if (!file_readable("/var/run/ld.so.hints"))
vsystem("ldconfig /usr/lib /usr/local/lib /usr/X11R6/lib");
vsystem("/sbin/ldconfig -aout /usr/lib/compat/aout /usr/lib/aout /usr/X11R6/lib/aout /usr/local/lib/aout");
/* Be initially optimistic */
ret = DITEM_SUCCESS | DITEM_RESTORE;
-34
View File
@@ -1,34 +0,0 @@
\ Example of the file which is automatically loaded by /boot/loader
\ on startup.
\ $Id: loader.rc,v 1.1 1999/05/14 18:06:27 dcs Exp $
cr .( Loading Forth extensions:)
\ Load configuration file words
cr .( - loader.4th...)
include /boot/loader.4th
\ Load the screen manipulation words
cr .( - screen.4th...)
s" /boot/screen.4th" fopen dup fload fclose
\ Load frame support
cr .( - frames.4th...)
s" /boot/frames.4th" fopen dup fload fclose
\ Load our little menu
cr .( - menuconf.4th...)
s" /boot/menuconf.4th" fopen dup fload fclose
\ Initialize loader.4th stuff
cr cr .( Initializing loader.4th...)
initialize drop
\ Show the menu
cr
main_menu
-110
View File
@@ -1,110 +0,0 @@
\ Simple greeting screen, presenting basic options.
\ XXX This is far too trivial - I don't have time now to think
\ XXX about something more fancy... :-/
\ $Id$
: title
f_single
60 11 10 4 box
29 4 at-xy 15 fg 7 bg
." Welcome to BootFORTH!"
me
;
: menu
2 fg
20 7 at-xy
." 1. Start FreeBSD with /boot/stable.conf."
20 8 at-xy
." 2. Start FreeBSD with /boot/current.conf."
20 9 at-xy
." 3. Start FreeBSD with standard configuration. "
20 10 at-xy
." 4. Reboot."
me
;
: tkey ( d -- flag | char )
seconds +
begin 1 while
dup seconds u< if
drop
-1
exit
then
key? if
drop
key
exit
then
repeat
;
: prompt
14 fg
20 12 at-xy
." Enter your option (1,2,3,4): "
10 tkey
dup 32 = if
drop key
then
dup 0< if
drop 51
then
dup emit
me
;
: help_text
10 18 at-xy ." * Choose 1 or 2 to run special configuration file."
10 19 at-xy ." * Choose 3 to proceed with standard bootstrapping."
12 20 at-xy ." See '?' for available commands, and 'words' for"
12 21 at-xy ." complete list of Forth words."
10 22 at-xy ." * Choose 4 in order to warm boot your machine."
;
: (reboot) 0 reboot ;
: main_menu
begin 1 while
clear
f_double
79 23 1 1 box
title
menu
help_text
prompt
cr cr cr
dup 49 = if
drop
1 25 at-xy cr
." Loading /boot/stable.conf. Please wait..." cr
s" /boot/stable.conf" read-conf
boot-conf
then
dup 50 = if
drop
1 25 at-xy cr
." Loading /boot/current.conf. Please wait..." cr
s" /boot/current.conf" read-conf
boot-conf
then
dup 51 = if
drop
1 25 at-xy cr
." Proceeding with standard boot. Please wait..." cr
boot-conf
then
dup 52 = if
drop
1 25 at-xy cr
['] (reboot) catch abort" Error rebooting"
then
20 12 at-xy
." Key " emit ." is not a valid option!"
20 13 at-xy
." Press any key to continue..."
key drop
repeat
;
@@ -1,27 +0,0 @@
kernel, rc.local, and xdm-config are typically softlinks. Plus other
files, of course, depending on how you setup your system.
rc.local and xdm-config might be softlinks into HT.DISKLESS, allowing
you to ease system administration when managing many diskless
workstations. You can also play other tricks, such as I play in
rc.conf.local by having it source ../HT.DISKLESS/rc.conf.local to get
class-based defaults.
Note: the ttys file below contains an example of how to have X startup
on boot.
apollo:/conf/209.157.86.12# ls -la
total 7
drwxr-xr-x 2 root wheel 512 Feb 9 00:27 .
drwxr-xr-x 8 root wheel 512 Feb 8 22:48 ..
lrwxr-xr-x 1 root wheel 20 Feb 8 22:04 fstab -> ../HT.DISKLESS/fstab
lrwxr-xr-x 1 root wheel 17 Jan 24 23:33 kernel -> /kernel.diskless2
-rw-r--r-- 1 root wheel 133 Feb 8 22:04 rc.conf.local
lrwxr-xr-x 1 root wheel 23 Jan 25 00:41 rc.local -> ../HT.DISKLESS/rc.local
-rw------- 1 root wheel 539 Jan 17 15:29 ssh_host_key
-rw-r--r-- 1 root wheel 343 Jan 17 15:29 ssh_host_key.pub
lrwxr-xr-x 1 root wheel 26 Feb 9 00:27 syslog.conf -> ../HT.DISKLESS/syslog.conf
-rw-r--r-- 1 root wheel 1408 Feb 8 19:54 ttys
lrwxr-xr-x 1 root wheel 25 Jan 25 00:38 xdm-config -> ../HT.DISKLESS/xdm-config
@@ -1,9 +0,0 @@
# DISKLESS RC.CONF.LOCAL
#
# Override system standard /etc/rc.conf
. /conf/HT.DISKLESS/rc.conf.local
hostname=test2.backplane.com
start_xdm=NO
Binary file not shown.
@@ -1 +0,0 @@
1024 33 131532587310298436102876167134780549224884868848048954510241288010381123823834489593599651234236801895942903979896941799980786675282403650831462626987993609590967535749256449810953893747928248417183421903403076895749793372279190481189373438759742396152779236777836204647146078686957945395785442097357022574693 [email protected]
@@ -1,5 +0,0 @@
# fstab for diskless machine. Root is already mounted, as is swap.
#
209.157.86.2:/usr /usr nfs ro 0 0
209.157.86.2:/var /var nfs ro 0 0
proc /proc procfs rw 0 0
@@ -1,34 +0,0 @@
# DISKLESS RC.CONF.LOCAL
#
# Override system standard /etc/rc.conf
ldconfig_paths="$ldconfig_paths /usr/krb5/lib"
ldconfig_paths_aout="$ldconfig_paths_aout /usr/krb5/lib/aout"
# Must do NFS mounts early
# Must not attempt to mount root rw
#
early_nfs_mounts="YES"
root_rw_mount="NO"
inetd_enable="NO"
portmap_enable="NO"
router_enable="NO"
cron_enable="NO"
sendmail_enable="NO"
# Enable additional services
#
nfs_client_enable="YES"
lpd_enable="YES"
ntpdate_enable="YES"
ntpdate_flags="apollo.backplane.com"
xntpd_enable="YES"
if [ -f /etc/ipfw.conf ]; then
firewall_enable="YES"
firewall_type="/etc/ipfw.conf"
firewall_quiet="NO"
fi
@@ -1,77 +0,0 @@
#!/bin/sh
if [ -f /etc/rc.conf ]; then
. /etc/rc.conf
fi
# Firewall helper - if we configure the firewall to let through
# ports > 4000, we need to configure the machines as such.
#
sysctl -w net.inet.ip.portrange.first=4000
# Setup spool
#
cat >> /var/spool/lpd/ljet4.ps << EOF
#!/bin/sh
#
gs -q -dSAFER -dNOPAUSE -sDEVICE=ljet4 -r600x600 -dBitsPerPixel=1 \
-sOutputFile=- -
EOF
chmod 755 /var/spool/lpd/ljet4.ps
mkdir /var/spool/ljet4
chown daemon /var/spool/ljet4
# Setup remote source
#
mount_mfs -s 600000 -T qp120at dummy /src
mount apollo:/FreeBSD /FreeBSD
mkdir /src/u3
mkdir /src/u3/usr.obj
# Copy of ssh_host_key* files to where sshd
# expects them, assuming you add to /usr/local/etc/sshd_config:
#
# HostKey /var/db/ssh_host_key
#
# Then restart sshd ( the /usr/local/etc/rc.d script installed by
# the port probably failed due to the lack of host keys )
if [ -f /conf/ME/ssh_host_key ]; then
cp /conf/ME/ssh_host_key* /var/db
else
(cd /var/db; ssh-keygen -f ssh_host_key -P "")
fi
chmod 400 /var/db/ssh_host_key
chmod 644 /var/db/ssh_host_key.pub
/usr/local/sbin/sshd
# Copy home directory so you can login
#
#
mount_mfs -s 65536 -T qp120at dummy /home
if [ -d /home.diskless ]; then
cd /home.diskless
for i in *; do
if [ -f $i/home.tgz ]; then
mkdir /home/$i
chown $i /home/$i
chmod 700 /home/$i
(cd /home/$i; tar xzpf /home.diskless/$i/home.tgz)
homeok=1
fi
done
fi
if [ "${homeok:=0}" = "0" ]; then
echo "ERROR, NO /home.diskless DIRECTORY TO COPY TO /HOME"
sleep 10
fi
@@ -1,3 +0,0 @@
*.err;kern.debug;auth.notice;mail.crit;lpr.info /dev/console
*.err;kern.debug;auth.notice;mail.crit root
*.emerg *
-52
View File
@@ -1,52 +0,0 @@
#
# @(#)ttys 5.1 (Berkeley) 4/17/89
#
# name getty type status comments
#
# This entry needed for asking password when init goes to single-user mode
# If you want to be asked for password, change "secure" to "insecure" here
console none unknown off secure
#
ttyv0 "/usr/X11R6/bin/xdm -nodaemon -config /conf/209.157.86.6/xdm-config" cons25 on secure
# Virtual terminals
ttyv1 "/usr/libexec/getty Pc" cons25 on secure
ttyv2 "/usr/libexec/getty Pc" cons25 on secure
ttyv3 "/usr/libexec/getty Pc" cons25 on secure
# Serial terminals
ttyd0 "/usr/libexec/getty std.9600" unknown off secure
ttyd1 "/usr/libexec/getty std.9600" unknown off secure
ttyd2 "/usr/libexec/getty std.9600" unknown off secure
ttyd3 "/usr/libexec/getty std.9600" unknown off secure
# Pseudo terminals
ttyp0 none network
ttyp1 none network
ttyp2 none network
ttyp3 none network
ttyp4 none network
ttyp5 none network
ttyp6 none network
ttyp7 none network
ttyp8 none network
ttyp9 none network
ttypa none network
ttypb none network
ttypc none network
ttypd none network
ttype none network
ttypf none network
ttypg none network
ttyph none network
ttypi none network
ttypj none network
ttypk none network
ttypl none network
ttypm none network
ttypn none network
ttypo none network
ttypp none network
ttypq none network
ttypr none network
ttyps none network
ttypt none network
ttypu none network
ttypv none network
@@ -1,15 +0,0 @@
! $XConsortium: xdm-conf.cpp,v 1.2 93/09/28 14:30:32 gildea Exp $
DisplayManager.errorLogFile: /var/run/xdm-errors
DisplayManager.pidFile: /var/run/xdm-pid
DisplayManager.servers: /usr/X11R6/lib/X11/xdm/Xservers-1
DisplayManager.keyFile: /usr/X11R6/lib/X11/xdm/xdm-keys
DisplayManager.servers: /usr/X11R6/lib/X11/xdm/Xservers
DisplayManager.accessFile: /usr/X11R6/lib/X11/xdm/Xaccess
DisplayManager._0.authorize: true
DisplayManager._0.setup: /usr/X11R6/lib/X11/xdm/Xsetup_0
DisplayManager._0.startup: /usr/X11R6/lib/X11/xdm/GiveConsole
DisplayManager._0.reset: /usr/X11R6/lib/X11/xdm/TakeConsole
DisplayManager*resources: /usr/X11R6/lib/X11/xdm/Xresources
DisplayManager*session: /usr/X11R6/lib/X11/xdm/Xsession
DisplayManager*authComplain: false
-30
View File
@@ -1,30 +0,0 @@
#
# @(#)aliases 5.3 (Berkeley) 5/24/90
#
# Aliases in this file will NOT be expanded in the header from
# Mail, but WILL be visible over networks or from /bin/mail.
#
# >>>>>>>>>> The program "newaliases" must be run after
# >> NOTE >> this file is updated for any changes to
# >>>>>>>>>> show through to sendmail.
#
# Basic system aliases -- these MUST be present
MAILER-DAEMON: postmaster
postmaster: root
# General redirections for pseudo accounts
bin: root
daemon: root
games: root
ingres: root
nobody: root
system: root
toor: root
uucp: root
usenet: root
root: [email protected]
diablo: dillon
diablo-bugs: dillon
@@ -1,6 +0,0 @@
# @(#)forward.map 1.1 1/17/95
#
# Put addresses to be forwarded here. Example:
#
# [email protected] [email protected]
#
@@ -1,11 +0,0 @@
#
# example:
# fofs.com [email protected]
#
# NOTE: FORWARD.MAP can be used to override NDOMAIN.MAP for specific
# users. NDOMAIN.MAP would then act as a catch-all
#
# NOTE: NDOMAIN.MAP only works to two levels. I.E. if you have an
# entry for fubar.com, then [email protected] will work and
# [email protected] will work, but NOT [email protected]
#
@@ -1,11 +0,0 @@
*.err;kern.debug;auth.notice;mail.crit /dev/console
# *.notice;kern.debug;lpr,auth.info;mail.crit /var/log/messages
*.debug;kern.debug;lpr,auth.info;mail.crit;news.crit /var/log/messages
mail.info /var/log/maillog
news.info /var/log/news
lpr.info /var/log/lpd-errs
cron.* /var/log/cron
#*.err root
#*.notice;auth.debug root
#*.alert root
*.emerg *
-52
View File
@@ -1,52 +0,0 @@
#
# @(#)ttys 5.1 (Berkeley) 4/17/89
#
# name getty type status comments
#
# This entry needed for asking password when init goes to single-user mode
# If you want to be asked for password, change "secure" to "insecure" here
console none unknown off secure
#
ttyv0 "/usr/libexec/getty Pc" cons25 on secure
# Virtual terminals
ttyv1 "/usr/libexec/getty Pc" cons25 on secure
ttyv2 "/usr/libexec/getty Pc" cons25 on secure
ttyv3 "/usr/libexec/getty Pc" cons25 on secure
# Serial terminals
ttyd0 "/usr/libexec/getty std.9600" unknown off secure
ttyd1 "/usr/libexec/getty std.9600" unknown off secure
ttyd2 "/usr/libexec/getty std.9600" unknown off secure
ttyd3 "/usr/libexec/getty std.9600" unknown off secure
# Pseudo terminals
ttyp0 none network
ttyp1 none network
ttyp2 none network
ttyp3 none network
ttyp4 none network
ttyp5 none network
ttyp6 none network
ttyp7 none network
ttyp8 none network
ttyp9 none network
ttypa none network
ttypb none network
ttypc none network
ttypd none network
ttype none network
ttypf none network
ttypg none network
ttyph none network
ttypi none network
ttypj none network
ttypk none network
ttypl none network
ttypm none network
ttypn none network
ttypo none network
ttypp none network
ttypq none network
ttypr none network
ttyps none network
ttypt none network
ttypu none network
ttypv none network
-37
View File
@@ -1,37 +0,0 @@
When templating, /conf/ME is typically a softlink to
/conf/<appropriate-machine>. When doing a diskless boot, /conf/ME is
retargeted by /etc/rc.diskless1 from pointing to the server to pointing
to the client's directory, /conf/<ip-address-of-client>. The retargeting
is accomplished through an MFS -o union mount.
When templating, this softlink should be different for each machine.
When doing a diskless boot, this softlink is typically part of the / NFS
mount from the server and points to the server's conf directory, but gets
retargeted during the /etc/rc.diskless1 phase.
System-wide configuration files must generally be targeted through /conf/ME.
For example, your /etc/rc.conf.local should become a softlink to
/conf/ME/rc.conf.local and your real rc.conf.local should go into the
appropriate /conf/<appropriate-machine> directory. This is also true of
/etc/rc.local, /etc/fstab, /etc/syslog.conf, /etc/ccd.conf, /etc/ipfw.conf,
/etc/motd, /etc/resolv.conf, and possibly even /etc/ttys ( if you want
to start an X session up on boot on certain of your machines ).
When templating, you duplicate your / and /usr partitions on each machine's
local disk from a single master ( assuming /var and /home reside elsewhere ),
EXCEPT for the /conf/ME softlink. The /conf/ME softlink is the only thing
on / that should be different for each machine.
There are often categories of configuration files. For example, all of your
shell machines may use one resolv.conf while all of your mail proxies may
use another. Configuration files can be categorized fairly easily through
/conf/HT.<category> directories. You put the actual configuration file in
/conf/HT.<category> and make a softlink from
/conf/ME/<appropriate-machines>/config-file to "../HT.<category/config-file".
This means that access to these files tends to run through more then one
softlink. The advantage is that for all the complexity of your /conf
directory hierarchy, most of your common config files exist in only one place
in reality.
-157
View File
@@ -1,157 +0,0 @@
BOOTP configuration mechanism
Matthew Dillon
[email protected]
BOOTP kernels automatically configure the machine's IP address, netmask,
optional NFS based swap, and NFS based root mount. The NFS server will
typically export a shared read-only /, /usr, and /var to any number of
workstations. The shared read-only root is typically either the server's
own root or, if you are more security concious, a contrived root.
The key issue with starting up a BOOTP kernel is that you typically want
to export read-only NFS partitions from the server, yet still be able to
customize each workstation ( or not ).
/etc/rc.diskless1 is responsible for doing core mounts and for retargeting
/conf/ME ( part of the read-only root NFS mount ) to /conf/$IP_OF_CLIENT.
/etc/rc.conf.local and /etc/rc.local, along with other machine-specific
configuration files, are typically softlinks to /conf/ME/<filename>.
In the BOOTP workstation /conf/$IP/rc.conf.local, you must typically
turn *OFF* most of the system option defaults in /etc/rc.conf as well
as do additional custom configuration of your environment
The /usr/src/share/examples/diskless directory contains a typical
X session / sshd based workstation configuration. The directories
involved are HT.DISKLESS/ and 192.157.86.12/.
Essentially, the $IP/ directory ( which rc.diskless looks for in
/conf/$IP/ ) contains all the junk. The HT.DISKLESS directory exists
to hold common elements of your custom configuration so you do not have
to repeat those elements for each workstation. The example /conf
structure included here shows how to create a working sshd setup ( so
you can sshd into the diskless workstation ), retarget xdm's pid and error
files to R+W directories if /usr is mounted read-only, and retarget
syslogd and other programs. This example is not designed to run out of
the box and some modifications are required.
>> NOTE << HT.DISKLESS/ttys contains the typical configuration required
to bring X up at boot time. Essentially, it runs xdm in the foreground
with the appropriate arguments rather then a getty on ttyv0. You must
run xdm on ttyv0 in order to prevent xdm racing with getty on a virtual
terminal. Such a race can cause your keyboard to be directed away from
the X session, essentially making the session unusable.
Typically you should start with a clean slate by tar-copying this example
directory to /conf and then hack on it in /conf rather then in
/usr/share/examples/diskless.
BOOTP CLIENT SETUP
Here is a typical kernel configuration. If you have only one ethernet
interface you do not need to wire BOOTP to a specific interface name.
BOOTP requires NFS and NFS_ROOT, and our boot scripts require MFS. If
your /tmp is *not* a softlink to /var/tmp, the scripts also require NULLFS
# BootP
#
options BOOTP # Use BOOTP to obtain IP address/hostname
options BOOTP_NFSROOT # NFS mount root filesystem using BOOTP info
options "BOOTP_NFSV3" # Use NFS v3 to NFS mount rootoptions
options BOOTP_COMPAT # Workaround for broken bootp daemons.
#options "BOOTP_WIRED_TO=de0"
options MFS # Memory File System
options NFS # Network Filesystem
options NFS_ROOT # Nfs can be root
options NULLFS # nullfs to map /var/tmp to /tmp
BOOTP SERVER SETUP
The BOOTP server must be running on the same logical LAN as the the
BOOTP client(s). You need to setup two things:
(1) You need to NFS-export /, /usr, and /var.
(2) You need to run a BOOTP server. DHCPD can do this.
NFS Export:
Here is an example "/etc/exports" file.
/ -ro -maproot=root: -network 192.157.86.0 -mask 255.255.255.192
/usr -ro -maproot=root: -network 192.157.86.0 -mask 255.255.255.192
/var -ro -maproot=root: -network 192.157.86.0 -mask 255.255.255.192
In order to be an NFS server, the server must run portmap, mountd,
nfsd, and rpc.statd. The standard NFS server options in /etc/rc.conf
will work ( you should put your overrides in /etc/rc.conf.local on the
server and not edit the distribution /etc/rc.conf, though ).
BOOTP Server:
This configuration file "/etc/dhcpd.conf" example is for
the '/usr/ports/net/isc-dhcp' dhcpd port.
subnet 192.157.86.0 netmask 255.255.255.192 {
# range if you want to run the core dhcpd service of
# dynamic IP assignment, but it is not used with BOOTP
# workstations
range 192.157.86.32 192.157.86.62;
# misc configuration.
#
option routers 192.157.86.2;
option domain-name-servers 192.157.86.2;
server-name "apollo.fubar.com";
option subnet-mask 255.255.255.192;
option domain-name-servers 192.157.86.2;
option domain-name "fubar.com";
option broadcast-address 192.157.86.63;
option routers 192.157.86.2;
}
host test1 {
hardware ethernet 00:a0:c9:d3:38:25;
fixed-address 192.157.86.11;
option root-path "192.157.86.2:/";
option option-128 "192.157.86.2:/images/swap";
}
host test2 {
# hardware ethernet 00:e0:29:1d:16:09;
hardware ethernet 00:10:5a:a8:94:0e;
fixed-address 192.157.86.12;
option root-path "192.157.86.2:/";
option option-128 "192.157.86.2:/images/swap";
}
SWAP. This example includes options to automatically BOOTP configure
NFS swap on each workstation. In order to use this capabilities you
need to NFS-export a swap directory READ+WRITE to the workstations.
You must then create a swap directory for each workstation you wish to
assign swap to. In this example I created a dummy user 'lander' and
did an NFS export of /images/swap enforcing a UID of 'lander' for
all accesses.
apollo:/usr/ports/net# ls -la /images/swap
total 491786
drwxr-xr-x 2 root wheel 512 Dec 28 07:00 .
drwxr-xr-x 8 root wheel 512 Jan 20 10:54 ..
-rw-r--r-- 1 lander wheel 33554432 Dec 23 14:35 swap.192.157.86.11
-rw-r--r-- 1 lander wheel 335544320 Jan 24 16:55 swap.192.157.86.12
-rw-r--r-- 1 lander wheel 134217728 Jan 21 17:19 swap.192.157.86.6
A swap file is best created with dd:
# create a 32MB swap file for a BOOTP workstation
dd if=/dev/zero of=swap.IPADDRESS bs=1m count=32
It is generally a good idea to give your workstations some swap space,
but not a requirement if they have a lot of memory.
-286
View File
@@ -1,286 +0,0 @@
TEMPLATING machine configurations
Matthew Dillon
[email protected]
This document describes a general mechanism by which you can template
/ and /usr. That is, to keep a 'master template' of / and /usr on a
separate machine which is then used to update the rest of your machines.
Generally speaking, you can't simply mirror /. You might be able to
get away with mirroring /usr. There are two main problems involved with
templating:
(1) Avoiding overwriting run-time generated files
By default, the system maintains a number of files in the root
partition. For example, sendmail will dbm /etc/aliases into
/etc/aliases.db. vipw or chpass or other password related routines
will regenerate the password dbm's /etc/spwd.db, /etc/pwd.db, and
passwd. /etc/namedb/s might contain generated secondaries. And
so forth.
The templating mechanism must avoid copying over such files.
(2) Customizing machines.
Customizing machines is actually considerably simpler. You create
a configuration hierarchy and convert the configuration files that
have to be customized into softlinks that run through a special
softlink in the configuration directory. This will work for every
configuration file except possibly /etc/master.passwd
For example, /etc/resolv.conf would be turned into a softlink to
/conf/ME/resolv.conf, and /conf/ME itself would be a softlink to
/conf/<HOSTNAME>. The actual resolv.conf configuration file
would reside in /conf/<HOSTNAME>.
If you have a lot of hosts, some configuration files may be commonly
classified. For example, all your shell machines might have the
same /etc/resolv.conf. The solution is to make
/conf/<HOSTNAME>/resolv.conf a softlink to a common directory, say
/conf/HT.SHELL/resolv.conf. It may sound a little messy, but this
sort of categorization actually makes the sysadmins job much, much
easier.
The /conf/ directory hierarchy is stored on the template and
distributed to all the machines along with the rest of the root
partition.
This type of customization is taken from my direct experience
instituting such a system at BEST. At the time, BEST had over 45
machines managed from a single template.
RUN-TIME GENERATED OR MODIFIED FILES IN / or /USR
/etc/aliases.db
/etc/master.passwd
/etc/spwd.db
/etc/pwd.db
/etc/passwd
/etc/namedb/s
/root/.history
/root/.ssh/identity
/root/.ssh/identity.pub
/root/.ssh/random_seed
/root/.ssh/known_hosts
/conf/ME
/kernel* ( note 2 )
/dev ( note 3 )
/var ( note 4 )
/home ( note 4 )
/lost+found
/usr/lost+found
/usr/home ( note 4 )
/usr/crash ( note 5 )
/usr/obj ( note 5 )
/usr/ports ( note 5 )
/usr/src ( note 5 )
/usr/local/crack ( note 5 )
/usr/X11R6/lib/X11/xdm/xdm-errors ( note 6 )
/usr/X11R6/lib/X11/xdm/xdm-pid ( note 6 )
/usr/local/etc/ssh_host_key ( note 6 )
/usr/local/etc/ssh_host_key.pub ( note 6 )
/usr/local/etc/ssh_random_seed ( note 6 )
/conf/ME ( note 7 )
note 2: You typically want to update kernels manually and *NOT*
template them as a safety measure. This also allows you to run
different kernels on different machines or.
note 3: /dev must be updated manually. Some devices, such as tty's and
pty's, use the access and/or modify time and/or user/group
operationally and regenerating the devices on the fly would be
bad.
note 4: /var and /home are usually separately mounted partitions and
thus would not fall under the template, but as a safety measure
the template copier refuse to copy directories named 'home'.
note 5: These are directories that are as often created directly on
/usr as they are separately-mounted partitions. You typically
do not want to template such directories.
note 6: Note that you can solve the problem of xdm and sshd creating
files in /usr. With xdm, edit /usr/X11R6/lib/xdm/xdm-config
and change the errorLogFile and pidFile config lines.
With sshd, add 'HostKey' and 'RandomSeed' directives to specify
/var/db for the location of the host key and run-time sshd
random seed:
HostKey /var/db/ssh_host_key
RandomSeed /var/db/ssh_random_seed
note 7: In this example, /conf/ME is the machine customizer and must
be pointed to the /conf/<full-host-name>/ directory, which is
different for each machine. Thus, the /conf/ME softlink
should never be overwritten by the templating copy.
TYPICAL CUSTOMIZED CONFIGRATION SOFTLINKS
The following files typically need to be turned into softlinks
to /conf/ME/<filename>:
/etc/ccd.conf -> /conf/ME/ccd.conf
/etc/ipfw.conf ...
/etc/fstab
/etc/motd
/etc/resolv.conf
/etc/aliases
/etc/sendmail.cw
/etc/organization
/etc/named.conf
/etc/rc.conf.local
/etc/printcap
/etc/inetd.conf
/etc/login.conf
/etc/gettytab
/etc/ntp.conf
/etc/exports
/root/.k5login -> /conf/ME/root/.k5login
And, of course, /conf/ME is usually a softlink to the appropriate
/conf/<full-host-name>/. Depending on your system configuration,
there may be other files not listed above that you have to worry about.
In many cases, /conf/ME/filename is itself a softlink to
"../HT.xxxx/filename", where HT.xxxx is something like HT.STD ... this
added complexity actually makes it easier to manage multiple
classifications of machines.
DELETION OF FILES
Any file found on the template destination that does not exist in the
source and is not listed as an exception by the source should be deleted.
However, deletion can be dangerous and cpdup will ask for confirmation
by default. Once you know you aren't going to blow things up, you can
turn this feature off and update your systems automatically from cron.
By formalizing the delete operation, you can be 100% sure that it is
possible to recreate / and /usr on any machine with only the original
template and a backup of the ( relatively few ) explicitly-excepted
files. The most common mistake a sysop makes is to make a change to a
file in / or /usr on a target machine instead of the template machine.
If the target machine is updated once a night from cron, the sysop
quickly learns not to do this ( because his changes get overwritten
overnight ). With a manual update, these sorts of mistakes can propogate
for weeks or months before they are caught.
TEMPLATE COPYING AND SAFETY
THE CPDUP PROGRAM
The 'cpdup' program is a program which efficiently duplicates a directory
tree. The program copies source to destination, duplicating devices,
softlinks, hardlinks, files, modification times, uid, gid, flags, perms,
and so forth. The program incorporates several major features:
* The program refuses, absolutely, to cross partition boundries.
i.e. if you were copying the template /usr from an NFS mount to
your /usr, and you had a mount point called /usr/home, the
template copying program would *NOT* descend into /usr/home on
the destination.
This is a safety.
* The program accesses a file called .cpignore in each directory
it descending into on the source to obtain a list of exceptions
for that directory -- that is, files not to copy or mess with.
This is a templating function.
* The program refuses to delete a directory on the destination
being replaced by a softlink or file on the source.
This is a safety mechanism
* The program is capable of maintaing MD5 check cache files and
doing an MD5 check between source and destination during the
scan.
* The program is capable of deleting files/directories on the
destination that do not exist on the source, but asks for
confirmation by default.
This is a templating and a safety mechanism.
* The program uses a copy-to-tmp-and-rename methodology allowing
it to be used to update live filesystems.
This is a templating mechanism.
* The program, by default, tries to determine if a copy is required
by checking modify times, file size, perms, and other stat
elements. If the elements match, it does not bother to copy
( unless an MD5 check is being made, in which case it must read
the destination file ).
You typically run cpdup on the target machine. The target machine
temporarily mounts the template machine's / and /usr via NFS, read-only,
and runs cpdup to update / and /usr. If you use this methodology note
that THERE ARE SECURITY CONSIDERATIONS! See 'SECURITY CONSIDERATIONS WITH
NFS' below.
Whatever script you use that does the NFS mounts should ensure that the
mount succeeded before continuing with the cpdup.
You should create .cpignore files in the appropriate directories on the
template machine's / and /usr partitions so as not to overwrite active
files on the target. The most critical .cpignore files should be
protected with 'chflags schg .cpignore'. Specifically, the ones in /
and /etc, but possibly others as well. For example, the .cpignore
hierarchy for protect /root is:
# /root/.cpignore contains
.history
# /root/.ssh/.cpignore contains
random_seed
known_hosts
authorized_keys
identity
identity.pub
WHEN INITIALLY CONVERTING A TARGET MACHINE TO USE TEMPLATING, ALWAYS
MAKE A FULL BACKUP OF THE TARGET MACHINE FIRST! You may accidently delete
files on the target during the conversion due to forgetting to enter
items into appropriate .cpignore files on the source.
SECURITY CONSIDERATIONS WITH NFS ROOT EXPORT FROM TEMPLATE MACHINE
SECURITY CONSIDERATIONS WITH NFS USR EXPORT FROM TEMPLATE MACHINE
There are some serious security considerations that must be taken into
account when exporting / and /usr on the template machine.
* only export read-only
* the password file ( aka vipw ) may not contain any crypted passwords
at all. You MUST use ssh or kerberos to access the template machine.
You can get away with giving only root a crypted password, but only
if you disallow network root logins and only allow direct root
logins on the console.
* The machine's private ssh_host_key usually resides in /usr/local/etc.
You must move this key to /var/db. You can softlink link so no
modification of sshd_config is required.
* The machine's private ~root/.ssh/identity file is also exposed by
the NFS export, you should move this file to /var/db as well and
put a softlink in ~root/.ssh.
* DON'T EXPORT /var ! Either that, or don't put the private keys
in /var/db ... put them somewhere else.
* You may want to redirect the location of the random_seed file, which
can be done by editing ~root/.ssh/sshd_config and
/usr/local/etc/sshd_config so it is not exposed either.
-Matt
Matthew Dillon
[email protected]
+2 -2
View File
@@ -32,11 +32,11 @@
# SUCH DAMAGE.
#
# @(#)newvers.sh 8.1 (Berkeley) 4/20/94
# $Id: newvers.sh,v 1.41.2.6 1999/05/14 14:31:56 jkh Exp $
# $Id: newvers.sh,v 1.41.2.5 1999/05/08 21:55:41 obrien Exp $
TYPE="FreeBSD"
REVISION="3.2"
BRANCH="STABLE"
BRANCH="RELEASE"
RELEASE="${REVISION}-${BRANCH}"
SNAPDATE=""
if [ "X${SNAPDATE}" != "X" ]; then
-62
View File
@@ -1,62 +0,0 @@
The oltr driver uses objects and microcode from Olicom's
OC-3300 PowerMACH Works Kit.
As the Linux driver says..
==================================================================
*
* This driver uses the Token Ring Low Level Driver (TRlld,
* PowerMach Works) as the lower level driver. The PMW kit is
* (C) Olicom. The executable object may be distributed along
* with this driver for the purpose of linking this driver.
*
=================================================================
The low level driver is combined with a FreeBSD specific driver
supplied in source, which provides all OS dependent functions.
files from olicom are:
trlld.o - Olicom low-level driver interface
trlldmac.o - TMS 380 Microcode for Olicom TMS380 based cards
trlldbm.o - "bullseye" Microcode for Olicom "bullseye" based cards
trlldhm.o - "hawkeye" Microcode for Olicom "hawkeye" based cards
The file trlld.o is stored in uuencode format as trlld.o.uu
It represents a state machine of some kind that has no OS dependencies
and communicates with the firmware on the cards via a proprietary interface.
All communication with this module is achieved via functions supplied in
the FreeBSD specific driver.
The other 3 files have been encoded using file2c(1)
and represent only microcode to be loaded into the appropriate board
when found.
Here is the release notice from Olicom regarding these files:
-------------------------------------------------------------------------------
OC-3300 PowerMach Works and its components are wholly owned products of
Olicom A/S
Nybrovej 114
2800 Lyngby
Denmark
(45) 45 27 00 00
and are used and distributed with permission. (#SS022499)
-------------------------------------------------------------------------------
A supporting email is also included.
---------- Forwarded message ----------
Date: Wed, 24 Feb 1999 17:07:14 +0100
From: Starla Scott <[email protected]>
To: 'Larry Lile' <[email protected]>
Subject: RE: FreeBSD Token-ring driver
Larry,
You may freely distribute the driver and/or kit. However, we do request that
you include an acknowledgement of Olicom's copyright and ownership as
related to your driver.
Thanks,
Starla
Olicom Tech Support
------------------------------------------------------------------------------
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-892
View File
@@ -1,892 +0,0 @@
/*
****************************** trlld.h ***********************************
*
* Copyright (c) 1997
* OLICOM A/S
* Denmark
*
* All Rights Reserved
*
* This source file is subject to the terms and conditions of the
* OLICOM Software License Agreement which restricts the manner
* in which it may be used.
*
*---------------------------------------------------------------------------
*
* Description: PowerMACH Works header file
*
*---------------------------------------------------------------------------
* $Log: O:/USR/PROJECT/trlld/libsrc/include/trlld.h_v $
*
* Rev 1.8 10 Dec 1998 12:24:52 JHM
* version 1.2.0,prominfo structure with shorts.
*
* Rev 1.7 25 Nov 1998 16:18:48 JHM
* Bullseye mac, 100MBPS, mactype in config structure,
* 3540 adapter, TRlldTransmitFree, TRlldReceiveFree,
* TRlldAdapterName
*
* Rev 1.6 23 Oct 1998 16:00:36 JHM
* hawkeye adapter types
*
* Rev 1.5 11 Aug 1998 12:22:06 JHM
* split hawkeye types into PCI4,5,6
*
* Rev 1.4 10 Jul 1998 14:39:22 JHM
* OC_3140,OC_3250
*
* Rev 1.3 18 Jun 1998 11:32:20 JHM
* AddMemory,OC_3250
*
* Rev 1.2 18 Apr 1998 15:11:20 JHM
*
* Rev 1.1 09 Dec 1997 18:17:52 JHM
* rel111: TRlldDataPtr_t
*
* Rev 1.0 24 Nov 1997 11:08:58 JHM
* Initial revision.
Rev 1.5 18 Jun 1997 11:31:36 JHM
Checks for version
Rev 1.4 13 Jun 1997 13:47:34 JHM
Rev 1.3 13 Jun 1997 13:27:56 JHM
DTR support, version change
Rev 1.2 12 Jun 1997 11:43:20 JHM
TRLLD_INTERRUPT_TIMEOUT defined
Rev 1.1 11 Apr 1997 15:24:18 JHM
replaced tabs with spaces
Rev 1.0 11 Apr 1997 14:43:04 JHM
Initial revision.
*
****************************************************************************
*/
#ifndef TRLLD_H
#define TRLLD_H
/* Data buffer pointers are always 32 bits.
For 16:16 it is segment:offset while it for 32:32 is a linear address. */
#ifdef TRlldSmall
#define TRlldDataPtr_t unsigned char far *
#define TRlldWordDataPtr_t unsigned short far *
#define TRlldDWordDataPtr_t unsigned long far *
#else
#define TRlldDataPtr_t unsigned char *
#define TRlldWordDataPtr_t unsigned short *
#define TRlldDWordDataPtr_t unsigned long *
#endif
#ifdef __WATCOMC__
#define CDECL _cdecl
#else
#define CDECL
#endif
/*****************************************************************************/
/* */
/* Firmware */
/* */
/*****************************************************************************/
extern unsigned char TRlldMacCode[]; /* 3115,17,18,29,33,36,37 */
extern unsigned char TRlldHawkeyeMac[]; /* 3139,3140,3141,3250 */
extern unsigned char TRlldBullseyeMac[]; /* 3540 */
/*****************************************************************************/
/* */
/* Maximal numbers of concurrent receive and transmit slots */
/* */
/*****************************************************************************/
#define TRLLD_MAX_RECEIVE 32
#define TRLLD_MAX_TRANSMIT 32
/*****************************************************************************/
/* */
/* Maximal frame sizes */
/* */
/*****************************************************************************/
#define TRLLD_MAXFRAME_100MBPS 18000
#define TRLLD_MAXFRAME_16MBPS 18000
#define TRLLD_MAXFRAME_4MBPS 4500
/*****************************************************************************/
/* */
/* TRlldStatus contains the adapter status used in a DriverStatus call-back. */
/* */
/*****************************************************************************/
struct OnWireInformation {
unsigned short RingStatus;
unsigned short Speed;
unsigned short AccessProtocol;
unsigned short Reserved;
};
typedef struct TRlldStatus {
unsigned short Type;
unsigned char Closed;
unsigned char AccessProtocol;
unsigned short MaxFrameSize;
unsigned short Reserved;
union {
unsigned short OnWireRingStatus; /* for compability */
unsigned short SelftestStatus;
unsigned short InitStatus;
unsigned short RingStatus;
unsigned short AdapterCheck[4];
unsigned short InternalError[4];
unsigned short PromRemovedCause;
unsigned short AdapterTimeout;
struct OnWireInformation OnWireInformation;
} Specification;
} TRlldStatus_t;
/* values of TRlldStatus.Type */
#define TRLLD_STS_ON_WIRE 0
#define TRLLD_STS_SELFTEST_STATUS 1
#define TRLLD_STS_INIT_STATUS 2
#define TRLLD_STS_RING_STATUS 3
#define TRLLD_STS_ADAPTER_CHECK 4
#define TRLLD_STS_PROMISCUOUS_STOPPED 5
#define TRLLD_STS_LLD_ERROR 6
#define TRLLD_STS_ADAPTER_TIMEOUT 7
/* values of TRlldStatus.Closed */
#define TRLLD_STS_STATUS_OK 0
#define TRLLD_STS_STATUS_CLOSED 1
/* values of TRlldStatus.AccessProtocol */
#define TRLLD_ACCESS_UNKNOWN 0
#define TRLLD_ACCESS_TKP 1
#define TRLLD_ACCESS_TXI 2
/* values of TRlldStatus.SelftestStatus */
#define TRLLD_ST_OK 0
#define TRLLD_ST_ERROR 0x0100 /* actual errors are 010x, where x is */
/* 0: Initial Test Error */
/* 1: Adapter Software Checksum Error */
/* 2: Adapter RAM Error */
/* 4: Instruction Test Error */
/* 5: Protocol Handler/RI Hw Error */
/* 6: System Interface Register Error */
#define TRLLD_ST_TIMEOUT 0x0200 /* The adapter did not complete */
/* selftest after download */
/* values of TRlldStatus.Specification.InitStatus */
/* the most likely cause of an init error (whatever the code) is a wrong */
/* physical or virtual address of the adapter block in TRlldAdapterInit */
#define TRLLD_INIT_ERROR 0x100 /* actual errors are 010x, where x is */
/* 1: Invalid init block (LLD error) */
/* 2: Invalid options (LLD error) */
/* 3: Invalid rcv burst (LLD error) */
/* 4: Invalid xmt burst (LLD error) */
/* 5: Invalid DMA threshold (LLDerror)*/
/* 6: Invalid scb addr */
/* 7: Invalid ssb addr */
/* 8: DIO parity error (HW error) */
/* 9: DMA timeout (May be interrupt
failing if PIO mode or PCI2) */
/* A: DMA parity error (HW error) */
/* B: DMA bus error (HW error) */
/* C: DMA data error */
/* D: Adapter check */
#define TRLLD_INIT_TIMEOUT 0x200 /* adapter init did not complete */
#define TRLLD_INIT_DMA_ERROR 0x300 /* adapter cannot access sys memory */
#define TRLLD_INIT_INTR_ERROR 0x400 /* adapter cannot interrupt */
#define TRLLD_OPEN_TIMEOUT 0x500 /* adapter open did not complete */
/* within 30 seconds */
#define TRLLD_OPEN_ERROR 0x600 /* actual errors are 06xx, where the */
/* bits in x mean: */
/* 01: Invalid open options (LLDerror)*/
/* 04: TxBuffer count error (LLDerror)*/
/* 10: Buffer size error (LLD error) */
/* 20: List size error (LLD error) */
/* 40: Node address error */
#define TRLLD_OPEN_REPEAT 0x700 /* actual errors are 07xy, where */
/* x is the open phase: */
/* 1: Lobe media test */
/* 2: Physical Insertion */
/* 3: Address verification */
/* 4: Participation in ring poll */
/* 5: Request Initialization */
/* 9: Request registration (TXI) */
/* A: Lobe Media Test (TXI) */
/* B: Address verification (TXI) */
/* y is the type of error: */
/* 1: Function failure (No Cable ?) */
/* 2: Signal loss */
/* 5: Timeout */
/* 6: Ring failure (TKP) */
/* 6: Protocol error (TXI) */
/* 7: Ring beaconing */
/* 8: Duplicate Node Address (TKP) */
/* 8: Insert Denied (TXI) */
/* 9: Request Initialization (TKP) */
/* 9: Heart beat failure (TXI) */
/* A: Remove received */
/* B: C-port address changed (TXI) */
/* C: Wire Fault (TKP) */
/* D: Auto Speed, 1. on ring (TKP) */
/* E: Speed sense failed */
/* When opening with FORCE_TXI and only classic token ring attachment is */
/* possible, the error is Request Registration/Timeout or 0x795 */
#define TRLLD_OPEN_1ST_ON_RING 0x800 /* Speed sense is active, but no other*/
/* station is present to set the speed*/
/* values of TRlldStatus.Specification.RingStatus */
#define TRLLD_RS_SIGNAL_LOSS 0x8000
#define TRLLD_RS_HARD_ERROR 0x4000
#define TRLLD_RS_SOFT_ERROR 0x2000
#define TRLLD_RS_TRANSMIT_BEACON 0x1000
#define TRLLD_RS_LOBE_WIRE_FAULT 0x0800
#define TRLLD_RS_AUTO_REMOVAL_ERROR 0x0400
#define TRLLD_RS_REMOVE_RECEIVED 0x0100
#define TRLLD_RS_COUNTER_OVERFLOW 0x0080
#define TRLLD_RS_SINGLE_STATION 0x0040
#define TRLLD_RS_RING_RECOVERY 0x0020
/* values of TRlldStatus.Specification.AdapterCheck */
/* MISSING */
/* values of TRlldStatus.Specification.PromRemovedCause */
#define TRLLD_PROM_REMOVE_RECEIVED 1
#define TRLLD_PROM_POLL_FAILURE 2
#define TRLLD_PROM_BUFFER_SIZE 3
/* values of TRlldStatus.Specification.InternalError */
#define TRLLD_INTERNAL_PIO 1 /* A PIO transfer to or from adapter */
/* did not complete */
#define TRLLD_INTERNAL_TX 2 /* Trouble with clean up of tx frames */
#define TRLLD_INTERNAL_RX 3 /* Trouble with clean up of receive */
/* fragments */
#define TRLLD_INTERNAL_CMD 4 /* error response from adapter */
#define TRLLD_INTERNAL_STATE 5 /* event happened in unexpected state */
/* values of TRlldStatus.Specification.AdapterTimeout */
#define TRLLD_COMMAND_TIMEOUT 1
#define TRLLD_TRANSMIT_TIMEOUT 2
#define TRLLD_INTERRUPT_TIMEOUT 3
/*****************************************************************************/
/* */
/* TRlldStatistics contains the adapter statistics returned to Driver */
/* in TRlldStatistics calls and DriverStatistics call-backs */
/* */
/*****************************************************************************/
typedef struct TRlldStatistics {
unsigned long LineErrors;
unsigned long InternalErrors; /* Not maintained by TMS based boards */
unsigned long BurstErrors;
unsigned long ARIFCIErrors;
unsigned long AbortDelimiters; /* Not maintained by TMS based boards */
unsigned long LostFrames;
unsigned long CongestionErrors;
unsigned long FrameCopiedErrors;
unsigned long FrequencyErrors; /* Not maintained by TMS based boards */
unsigned long TokenErrors;
unsigned long DMABusErrors; /* Not maintained by 3139 */
unsigned long DMAParityErrors; /* Not maintained by 3139 */
unsigned long ReceiveLongFrame; /* Not maintained by TMS based boards */
unsigned long ReceiveCRCErrors; /* Not maintained by TMS based boards */
unsigned long ReceiveOverflow; /* Not maintained by TMS based boards */
unsigned long TransmitUnderrun; /* Not maintained by TMS based boards */
unsigned long UnderrunLock; /* Not maintained by TMS based boards */
unsigned long OverflowReset;
unsigned char UpstreamNeighbour[6];
unsigned short RingNumber;
unsigned char BeaconingUpstreamNeighbour[6];
unsigned short padding;
} TRlldStatistics_t;
/*****************************************************************************/
/* */
/* TRlldDriver contains the Driver call-backs */
/* */
/*****************************************************************************/
typedef struct TRlldDriver {
unsigned long TRlldVersion;
#ifndef TRlldInlineIO
void (CDECL * DriverOutByte)(unsigned short IOAddress,
unsigned char Value);
void (CDECL * DriverOutWord)(unsigned short IOAddress,
unsigned short Value);
void (CDECL * DriverOutDWord)(unsigned short IOAddress,
unsigned long Value);
void (CDECL * DriverRepOutByte)(unsigned short IOAddress,
TRlldDataPtr_t DataPointer,
int ByteCount);
void (CDECL * DriverRepOutWord)(unsigned short IOAddress,
TRlldWordDataPtr_t DataPointer,
int WordCount);
void (CDECL * DriverRepOutDWord)(unsigned short IOAddress,
TRlldDWordDataPtr_t DataPointer,
int DWordCount);
unsigned char (CDECL * DriverInByte)(unsigned short IOAddress);
unsigned short (CDECL * DriverInWord)(unsigned short IOAddress);
unsigned long (CDECL * DriverInDWord)(unsigned short IOAddress);
void (CDECL * DriverRepInByte)(unsigned short IOAddress,
TRlldDataPtr_t DataPointer,
int ByteCount);
void (CDECL * DriverRepInWord)(unsigned short IOAddress,
TRlldWordDataPtr_t DataPointer,
int WordCount);
void (CDECL * DriverRepInDWord)(unsigned short IOAddress,
TRlldDWordDataPtr_t DataPointer,
int DWordCount);
#endif
void (CDECL * DriverSuspend)(unsigned short MicroSeconds);
void (CDECL * DriverStatus)(void * DriverHandle,
TRlldStatus_t * Status);
void (CDECL * DriverCloseCmpltd)(void * DriverHandle);
void (CDECL * DriverStatistics)(void * DriverHandle,
TRlldStatistics_t * Statistics);
void (CDECL * DriverTxFrameCmpltd)(void * DriverHandle,
void * FrameHandle,
int TxStatus);
void (CDECL * DriverRcvFrameCmpltd)(void * DriverHandle,
int ByteCount,
int FragmentCount,
void * FragmentHandle,
int RcvStatus);
} TRlldDriver_t;
/* Version and model control */
#define TRLLD_VERSION_INLINEIO 0x8000
#define TRLLD_VERSION_SMALL 0x4000
#ifdef TRlldInlineIO
#ifdef TRlldSmall
#define TRLLD_VERSION 0x4120
#else
#define TRLLD_VERSION 0x0120
#endif
#else
#ifdef TRlldSmall
#define TRLLD_VERSION 0xC120
#else
#define TRLLD_VERSION 0x8120
#endif
#endif
/*****************************************************************************/
/* */
/* TRlldAdapterConfig contains the properties found for an adapter */
/* used when finding and defining adapters to use */
/* */
/*****************************************************************************/
struct pnp_id {
unsigned short vendor;
unsigned short device;
};
struct pci_id {
unsigned short vendor;
unsigned short device;
unsigned char revision;
unsigned char reserved_byte;
unsigned short reserved_word;
};
struct pcmcia_id {
/* unknown as yet */
unsigned char x;
};
struct pci_slot {
unsigned short bus_no;
unsigned short device_no;
};
struct pcmcia_socket {
/* unknown as yet */
unsigned char x;
};
typedef struct TRlldAdapterConfig {
unsigned char type;
unsigned char bus;
unsigned short magic;
union {
struct pnp_id pnp;
unsigned long eisa;
unsigned short mca;
struct pci_id pci;
struct pcmcia_id pcmcia;
} id;
union {
unsigned short csn;
unsigned short eisa;
unsigned short mca;
struct pci_slot pci;
struct pcmcia_socket pcmcia;
} slot;
unsigned short iobase0;
unsigned short iolength0;
unsigned short iobase1;
unsigned short iolength1;
unsigned long memorybase;
unsigned short memorylength;
unsigned char mode;
unsigned char xmode;
unsigned char interruptlevel;
unsigned char dmalevel;
unsigned char macaddress[6];
unsigned long prombase;
unsigned char speed;
unsigned char cachelinesize;
unsigned short pcicommand;
unsigned char mactype;
unsigned char reserved[3];
} TRlldAdapterConfig_t;
/* values of TRlldAdapterConfig.Type */
#define TRLLD_ADAPTER_XT 0 /* not supported */
#define TRLLD_ADAPTER_ISA1 1 /* OC-3115 */
#define TRLLD_ADAPTER_ISA2 2 /* OC-3117 */
#define TRLLD_ADAPTER_ISA3 3 /* OC-3118 */
#define TRLLD_ADAPTER_MCA1 4 /* OC-3129 id A84 */
#define TRLLD_ADAPTER_MCA2 5 /* OC-3129 id A85 */
#define TRLLD_ADAPTER_MCA3 6 /* OC-3129 id A86 */
#define TRLLD_ADAPTER_EISA1 7 /* OC-3133 id 0109833D */
#define TRLLD_ADAPTER_EISA2 8 /* OC-3133 id 0209833D */
#define TRLLD_ADAPTER_EISA3 9 /* OC-3135 not supported */
#define TRLLD_ADAPTER_PCI1 10 /* OC-3136 id 108d0001 rev 1 */
#define TRLLD_ADAPTER_PCI2 11 /* OC-3136 id 108d0001 rev 2 */
#define TRLLD_ADAPTER_PCI3 12 /* OC-3137 id 108d0001 rev 3 */
#define TRLLD_ADAPTER_PCI4 13 /* OC-3139 id 108d0004 rev 2 */
#define TRLLD_ADAPTER_PCI5 14 /* OC-3140 id 108d0004 rev 3 */
#define TRLLD_ADAPTER_PCI6 15 /* OC-3141 id 108d0007 rev 1 */
#define TRLLD_ADAPTER_PCI7 19 /* OC-3540 id 108d0008 rev 1 */
#ifdef PCMCIA
#define TRLLD_ADAPTER_PCCARD1 16 /* OC-3220 */
#define TRLLD_ADAPTER_PCCARD2 17 /* OC-3221,OC-3230,OC-3232 */
#endif
#define TRLLD_ADAPTER_PCCARD3 18 /* OC-3250 id 108d0005 rev 1 */
/* values of TRlldAdapterConfig.Bus */
#define TRLLD_BUS_ISA 1
#define TRLLD_BUS_EISA 2
#define TRLLD_BUS_MCA 3
#define TRLLD_BUS_PCI 4
#define TRLLD_BUS_PCMCIA 5
/* values of TRlldAdapterConfig.mode */
#define TRLLD_MODE_16M 0x01 /* needs data buffers below 16 M */
#define TRLLD_MODE_PHYSICAL 0x02 /* needs valid physical addresses */
#define TRLLD_MODE_FIXED_CFG 0x04 /* cannot be reconfigured */
#define TRLLD_MODE_SHORT_SLOT 0x08 /* in short ISA slot, cannot use DMA */
#define TRLLD_MODE_CANNOT_DISABLE 0x10 /* can not disable interrupt */
#define TRLLD_MODE_SHARE_INTERRUPT 0x20 /* may share interrupt */
#define TRLLD_MODE_MEMORY 0x40 /* is configured with a memory window*/
/* values of TRlldAdapterConfig.dma */
#define TRLLD_DMA_PIO 4 /* other values signifies the DMA channel */
#define TRLLD_DMA_MASTER 0xff /* to use */
/* values of TRlldAdapterConfig.mactype */
/* download with: */
#define TRLLD_MAC_TMS 1 /* TRlldMACCode */
#define TRLLD_MAC_HAWKEYE 2 /* TRlldHawkeyeMAC */
#define TRLLD_MAC_BULLSEYE 3 /* TRlldBullseyeMAC */
typedef void * TRlldAdapter_t;
typedef void * TRlldAdapterType_t;
#ifndef MAX_FRAGMENTS
#define MAX_FRAGMENTS 32
#endif
typedef struct TRlldTransmit {
unsigned short FragmentCount;
unsigned short TRlldTransmitReserved;
struct TRlldTransmitFragment {
unsigned long PhysicalAddress;
TRlldDataPtr_t VirtualAddress;
unsigned short count;
unsigned short TRlldTransmitFragmentReserved;
} TransmitFragment[MAX_FRAGMENTS];
} TRlldTransmit_t;
int CDECL TRlldAdapterSize(void);
int CDECL TRlldInit(int TypeCount,
TRlldAdapterType_t * AdapterTypeTable);
extern TRlldAdapterType_t CDECL TRlld3115; /* ISA adapters */
extern TRlldAdapterType_t CDECL TRlld3117;
extern TRlldAdapterType_t CDECL TRlld3118;
extern TRlldAdapterType_t CDECL TRlld3129; /* MCA adapters */
extern TRlldAdapterType_t CDECL TRlld3133; /* EISA adapters */
extern TRlldAdapterType_t CDECL TRlld3136; /* PCI adapters */
extern TRlldAdapterType_t CDECL TRlld3137;
extern TRlldAdapterType_t CDECL TRlld3139; /* Hawkeye adapters */
extern TRlldAdapterType_t CDECL TRlld3540; /* BUllseye adapter */
#define T3115 &TRlld3115
#define T3117 &TRlld3117
#define T3118 &TRlld3118
#define T3129 &TRlld3129
#define T3133 &TRlld3133
#define T3136 &TRlld3136
#define T3137 &TRlld3137
#define T3139 &TRlld3139
#define T3540 &TRlld3540
/* Only for Boot Prom Page Zero code */
extern TRlldAdapterType_t CDECL TRlld3115Boot; /* ISA adapters */
extern TRlldAdapterType_t CDECL TRlld3117Boot;
extern TRlldAdapterType_t CDECL TRlld3118Boot;
extern TRlldAdapterType_t CDECL TRlld3129Boot; /* MCA adapters */
extern TRlldAdapterType_t CDECL TRlld3133Boot; /* EISA adapters */
extern TRlldAdapterType_t CDECL TRlld3136Boot; /* PCI adapters */
extern TRlldAdapterType_t CDECL TRlld3137Boot;
extern TRlldAdapterType_t CDECL TRlld3139Boot; /* Hawkeye adapters */
extern TRlldAdapterType_t CDECL TRlld3540Boot; /* Bullseye adapters */
#define B3115 &TRlld3115Boot
#define B3117 &TRlld3117Boot
#define B3118 &TRlld3118Boot
#define B3129 &TRlld3129Boot
#define B3133 &TRlld3133Boot
#define B3136 &TRlld3136Boot
#define B3137 &TRlld3137Boot
#define B3139 &TRlld3139Boot
#define B3540 &TRlld3540Boot
#define TRLLD_INIT_OK 0
#define TRLLD_INIT_UNKNOWN 5
int CDECL TRlldAdapterInit(TRlldDriver_t * DriverDefinition,
TRlldAdapter_t * TRlldAdapter,
unsigned long TRlldAdapterPhysical,
void * DriverHandle,
TRlldAdapterConfig_t * config);
#define TRLLD_INIT_OK 0
#define TRLLD_INIT_NOT_FOUND 1
#define TRLLD_INIT_UNSUPPORTED 2
#define TRLLD_INIT_PHYS16 3
#define TRLLD_INIT_VERSION 4
int CDECL TRlldSetSpeed(TRlldAdapter_t * adapter,
unsigned char speed);
#define TRLLD_SPEED_4MBPS 4
#define TRLLD_SPEED_16MBPS 16
#define TRLLD_SPEED_100MBPS 100
int CDECL TRlldSetInterrupt(TRlldAdapter_t * adapter,
unsigned char interruptlevel);
int CDECL TRlldSetDMA(TRlldAdapter_t * adapter,
unsigned char dma, unsigned char * mode);
#define TRLLD_CONFIG_OK 0
#define TRLLD_CONFIG_STATE 1
#define TRLLD_CONFIG_ILLEGAL 2
#define TRLLD_CONFIG_FAILED 3
int CDECL TRlldSetSpecial(TRlldAdapter_t * adapter,
unsigned short param1, unsigned short param2,
unsigned short param3, unsigned short param4);
int CDECL TRlldAddMemory(TRlldAdapter_t * adapter,
TRlldDataPtr_t virtual,
unsigned long physical,
long size);
int CDECL TRlldDisable(TRlldAdapter_t * adapter);
#define TRLLD_OK 0
#define TRLLD_NOT_SUPPORTED 1
void CDECL TRlldEnable(TRlldAdapter_t * adapter);
int CDECL TRlldInterruptPresent(TRlldAdapter_t * adapter);
#define TRLLD_NO_INTERRUPT 0
#define TRLLD_INTERRUPT 1
int CDECL TRlldInterruptService(TRlldAdapter_t * adapter);
int CDECL TRlldInterruptPreService(TRlldAdapter_t * adapter);
void CDECL TRlldInterruptPostService(TRlldAdapter_t * adapter);
int CDECL TRlldPoll(TRlldAdapter_t * adapter);
int CDECL TRlldDownload(TRlldAdapter_t * adapter,
char * DownLoadCode);
#define TRLLD_DOWNLOAD_OK 0
#define TRLLD_DOWNLOAD_ERROR 1
#define TRLLD_STATE 2
typedef int (CDECL * GetCode_t)(void * handle, unsigned char * maccodebyte);
int CDECL TRlldStreamDownload(TRlldAdapter_t * adapter,
GetCode_t procedure, void * handle);
int CDECL TRlldOpen(TRlldAdapter_t * adapter,
unsigned char * MACAddress,
unsigned long GroupAddress,
unsigned long FunctionalAddress,
unsigned short MaxFrameSize,
unsigned short OpenModes);
#define TRLLD_OPEN_OK 0
#define TRLLD_OPEN_STATE 1
#define TRLLD_OPEN_ADDRESS_ERROR 2
#define TRLLD_OPEN_MODE_ERROR 3
#define TRLLD_OPEN_MEMORY 4
#define TRLLD_MODE_TX_STATUS 0x01
#define TRLLD_MODE_RX_SINGLE 0x02
#define TRLLD_MODE_FORCE_TKP 0x04
#define TRLLD_MODE_FORCE_TXI 0x08
#define TRLLD_MODE_TX_CRC 0x10
void CDECL TRlldClose(TRlldAdapter_t * adapter, int immediate);
void CDECL TRlldSetGroupAddress(TRlldAdapter_t * adapter,
unsigned long GroupAddress);
void CDECL TRlldSetFunctionalAddress(TRlldAdapter_t * adapter,
unsigned long FunctionalAddress);
void CDECL TRlldSetPromiscuousMode(TRlldAdapter_t * adapter,
unsigned char mode);
/* mode bits */
#define TRLLD_PROM_LLC 1
#define TRLLD_PROM_MAC 2
#define TRLLD_PROM_ERRORFRAMES 4
int CDECL TRlldGetStatistics(TRlldAdapter_t * adapter,
TRlldStatistics_t * statistics,
int immediate);
#define TRLLD_IMMEDIATE_STATISTICS 1
#define TRLLD_STATISTICS_RETRIEVED 0
#define TRLLD_STATISTICS_PENDING 1
int CDECL TRlldTransmitFrame(TRlldAdapter_t * adapter,
TRlldTransmit_t * TransmitFrame,
void * FrameHandle);
#define TRLLD_TRANSMIT_OK 0
#define TRLLD_TRANSMIT_NOT_OPEN 1
#define TRLLD_TRANSMIT_TOO_MANY 2
#define TRLLD_TRANSMIT_MAX16 3
#define TRLLD_TRANSMIT_SIZE 4
#define TRLLD_TRANSMIT_EMPTY 5
/* completion flags */
#define TRLLD_TX_OK 0
#define TRLLD_TX_NOT_PROCESSED 1
#define TRLLD_TX_NOT_RECOGNIZED 2
#define TRLLD_TX_NOT_COPIED 3
/* number of free transmit fragments */
int CDECL TRlldTransmitFree(TRlldAdapter_t * adapter);
int CDECL TRlldReceiveFragment(TRlldAdapter_t * adapter,
TRlldDataPtr_t FragmentStart,
unsigned long FragmentPhysical,
int count,
void * FragmentHandle);
#define TRLLD_RECEIVE_OK 0
#define TRLLD_RECEIVE_NOT_OPEN 1
#define TRLLD_RECEIVE_TOO_MANY 2
#define TRLLD_RECEIVE_SIZE 3
#define TRLLD_RECEIVE_MAX16 4
/* completion flags */
#define TRLLD_RCV_OK 0
#define TRLLD_RCV_NO_DATA 1
#define TRLLD_RCV_ERROR 2 /* Only when TRLLD_PROM_ERRORFRAMES */
#define TRLLD_RCV_LONG 3
/* number of free receive fragments */
int CDECL TRlldReceiveFree(TRlldAdapter_t * adapter);
int CDECL TRlldFind(TRlldDriver_t * driver,
TRlldAdapterConfig_t * config_table,
unsigned long type_mask,
int max);
/* type mask bits */
#define OC_3115 0x0001
#define OC_3117 0x0002
#define OC_3118 0x0004
#define OC_3129 0x0008
#define OC_3133 0x0010
#define OC_3136 0x0040
#define OC_3137 0x0080
#define OC_3139 0x0100
#define OC_3140 0x0200
#define OC_3141 0x0400
#define OC_3540 0x0800
#ifdef PCMCIA
#define OC_3220 0x0800
#define OC_3221 0x1000
#define OC_3230 0x2000
#define OC_3232 0x4000
#endif
#define OC_3250 0x8000
int CDECL TRlldIOAddressConfig(TRlldDriver_t * driver,
TRlldAdapterConfig_t * config,
unsigned short address);
#define TRLLD_FIND_OK 1
#define TRLLD_FIND_ERROR 0
#define TRLLD_FIND_VERSION -1
int CDECL TRlldEISASlotConfig(TRlldDriver_t * driver,
TRlldAdapterConfig_t * config,
int slot);
int CDECL TRlldMCASlotConfig(TRlldDriver_t * driver,
TRlldAdapterConfig_t * config,
int slot);
int CDECL TRlldPCIConfig(TRlldDriver_t * driver,
TRlldAdapterConfig_t * config,
char * PCIConfigurationSpace);
#define TRLLD_PCICONFIG_OK 0
#define TRLLD_PCICONFIG_FAIL 1
#define TRLLD_PCICONFIG_SET_COMMAND 2
#define TRLLD_PCICONFIG_VERSION 3
int CDECL TRlldFindPCI(TRlldDriver_t * driver,
TRlldAdapterConfig_t * config_table,
unsigned long type_mask,
int max);
#ifdef PCMCIA
typedef void * PCCardHandle_t;
typedef int (CDECL * GetTupleData_t)(PCCardHandle_t handle,
unsigned short TupleIdent,
char * TupleData,
int length);
int CDECL TRlldPCCardConfig(TRlldDriver_t * driver,
TRlldAdapterConfig_t * config,
unsigned short address,
int irq,
GetTupleData_t GetTuple,
PCCardHandle_t handle);
#define TRLLD_PCCARD_CONFIG_OK 0
#define TRLLD_PCCARD_CONFIG_FAIL 1
#endif
/* Boot Prom Support */
typedef struct TRlldPromInfo {
unsigned short PromIdent;
short PromPages;
short PromPageSize;
} TRlldPromInfo_t;
int CDECL TRlldMapBootProm(TRlldAdapter_t * adapter,
TRlldDataPtr_t prompointer);
#define TRLLD_PROM_OK 0
#define TRLLD_PROM_FAILED 3
int CDECL TRlldGetPromInfo(TRlldAdapter_t * adapter, TRlldPromInfo_t * info);
#define TRLLD_PROM_OK 0
#define TRLLD_PROM_NOT_MOUNTED 1
#define TRLLD_PROM_NOT_MAPPED 2
void CDECL TRlldSetPromPage(TRlldAdapter_t * adapter, int page);
int CDECL TRlldSetMemoryUse(TRlldAdapter_t * adapter, int use);
#define TRLLD_PROM_TO_MEMORY 0
#define TRLLD_REGISTERS_TO_MEMORY 1
#define TRLLD_MEMORY_USE_OK 0
#define TRLLD_MEMORY_USE_NO_MEMORY 1
#define TRLLD_MEMORY_USE_STATE 2
#define TRLLD_MEMORY_USE_ILLEGAL 3
int CDECL TRlldPromErase(TRlldAdapter_t * adapter,
void (CDECL * delay)(int milliseconds));
#define TRLLD_PROM_OK 0
#define TRLLD_PROM_NOT_MOUNTED 1
#define TRLLD_PROM_NOT_MAPPED 2
#define TRLLD_PROM_FAILED 3
int CDECL TRlldPromWrite(TRlldAdapter_t * adapter, char * data,
int offset, int count);
#define TRLLD_PROM_OK 0
#define TRLLD_PROM_NOT_MOUNTED 1
#define TRLLD_PROM_NOT_MAPPED 2
#define TRLLD_PROM_FAILED 3
#define TRLLD_PROM_ILLEGAL 4
void CDECL TRlldEmergency(TRlldAdapter_t * adapter);
/* Convert from TRlldAdapterConfig.type to name string */
char * CDECL TRlldAdapterName(int type);
#endif
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-320
View File
@@ -1,320 +0,0 @@
Introduction
This package constitutes the alpha distribution of the soft update
code updates for the fast filesystem.
For More information on what Soft Updates is, see:
http://www.ece.cmu.edu/~ganger/papers/CSE-TR-254-95/
Status
My `filesystem torture tests' (described below) run for days without
a hitch (no panic's, hangs, filesystem corruption, or memory leaks).
However, I have had several panic's reported to me by folks that
are field testing the code which I have not yet been able to
reproduce or fix. Although these panic's are rare and do not cause
filesystem corruption, the code should only be put into production
on systems where the system administrator is aware that it is being
run, and knows how to turn it off if problems arise. Thus, you may
hand out this code to others, but please ensure that this status
message is included with any distributions. Please also include
the file ffs_softdep.stub.c in any distributions so that folks that
cannot abide by the need to redistribute source will not be left
with a kernel that will not link. It will resolve all the calls
into the soft update code and simply ignores the request to enable
them. Thus you will be able to ensure that your other hooks have
not broken anything and that your kernel is softdep-ready for those
that wish to use them. Please report problems back to me with
kernel backtraces of panics if possible. This is massively complex
code, and people only have to have their filesystems hosed once or
twice to avoid future changes like the plague. I want to find and
fix as many bugs as soon as possible so as to get the code rock
solid before it gets widely released. Please report any bugs that
you uncover to [email protected].
Performance
Running the Andrew Benchmarks yields the following raw data:
Phase Normal Softdep What it does
1 3s <1s Creating directories
2 8s 4s Copying files
3 6s 6s Recursive directory stats
4 8s 9s Scanning each file
5 25s 25s Compilation
Normal: 19.9u 29.2s 0:52.8 135+630io
Softdep: 20.3u 28.5s 0:47.8 103+363io
Another interesting datapoint are my `filesystem torture tests'.
They consist of 1000 runs of the andrew benchmarks, 1000 copy and
removes of /etc with randomly selected pauses of 0-60 seconds
between each copy and remove, and 500 find from / with randomly
selected pauses of 100 seconds between each run). The run of the
torture test compares as follows:
With soft updates: writes: 6 sync, 1,113,686 async; run time 19hr, 50min
Normal filesystem: writes: 1,459,147 sync, 487,031 async; run time 27hr, 15min
The upshot is 42% less I/O and 28% shorter running time.
Another interesting test point is a full MAKEDEV. Because it runs
as a shell script, it becomes mostly limited by the execution speed
of the machine on which it runs. Here are the numbers:
With soft updates:
labrat# time ./MAKEDEV std
2.2u 32.6s 0:34.82 100.0% 0+0k 11+36io 0pf+0w
labrat# ls | wc
522 522 3317
Without soft updates:
labrat# time ./MAKEDEV std
2.0u 40.5s 0:42.53 100.0% 0+0k 11+1221io 0pf+0w
labrat# ls | wc
522 522 3317
Of course, some of the system time is being pushed
to the syncer process, but that is a different story.
To show a benchmark designed to highlight the soft update code
consider a tar of zero-sized files and an rm -rf of a directory tree
that has at least 50 files or so at each level. Running a test with
a directory tree containing 28 directories holding 202 empty files
produces the following numbers:
With soft updates:
tar: 0.0u 0.5s 0:00.65 76.9% 0+0k 0+44io 0pf+0w (0 sync, 33 async writes)
rm: 0.0u 0.2s 0:00.20 100.0% 0+0k 0+37io 0pf+0w (0 sync, 72 async writes)
Normal filesystem:
tar: 0.0u 1.1s 0:07.27 16.5% 0+0k 60+586io 0pf+0w (523 sync, 0 async writes)
rm: 0.0u 0.5s 0:01.84 29.3% 0+0k 0+318io 0pf+0w (258 sync, 65 async writes)
The large reduction in writes is because inodes are clustered, so
most of a block gets allocated, then the whole block is written
out once rather than having the same block written once for each
inode allocated from it. Similarly each directory block is written
once rather than once for each new directory entry. Effectively
what the update code is doing is allocating a bunch of inodes
and directory entries without writing anything, then ensuring that
the block containing the inodes is written first followed by the
directory block that references them. If there were data in the
files it would further ensure that the data blocks were written
before their inodes claimed them.
Copyright Restrictions
Please familiarize yourself with the copyright restrictions
contained at the top of either the sys/ufs/ffs/softdep.h or
sys/ufs/ffs/ffs_softdep.c file. The key provision is similar
to the one used by the DB 2.0 package and goes as follows:
Redistributions in any form must be accompanied by information
on how to obtain complete source code for any accompanying
software that uses the this software. This source code must
either be included in the distribution or be available for
no more than the cost of distribution plus a nominal fee,
and must be freely redistributable under reasonable
conditions. For an executable file, complete source code
means the source code for all modules it contains. It does
not mean source code for modules or files that typically
accompany the operating system on which the executable file
runs, e.g., standard library modules or system header files.
The idea is to allow those of you freely redistributing your source
to use it while retaining for myself the right to peddle it for
money to the commercial UNIX vendors. Note that I have included a
stub file ffs_softdep.c.stub that is freely redistributable so that
you can put in all the necessary hooks to run the full soft updates
code, but still allow vendors that want to maintain proprietary
source to have a working system. I do plan to release the code with
a `Berkeley style' copyright once I have peddled it around to the
commercial vendors. If you have concerns about this copyright,
feel free to contact me with them and we can try to resolve any
difficulties.
Soft Dependency Operation
The soft update implementation does NOT require ANY changes
to the on-disk format of your filesystems. Furthermore it is
not used by default for any filesystems. It must be enabled on
a filesystem by filesystem basis by running tunefs to set a
bit in the superblock indicating that the filesystem should be
managed using soft updates. If you wish to stop using
soft updates due to performance or reliability reasons,
you can simply run tunefs on it again to turn off the bit and
revert to normal operation. The additional dynamic memory load
placed on the kernel malloc arena is approximately equal to
the amount of memory used by vnodes plus inodes (for a system
with 1000 vnodes, the additional peak memory load is about 300K).
Kernel Changes
There are two new changes to the kernel functionality that are not
contained in in the soft update files. The first is a `trickle
sync' facility running in the kernel as process 3. This trickle
sync process replaces the traditional `update' program (which should
be commented out of the /etc/rc startup script). When a vnode is
first written it is placed 30 seconds down on the trickle sync
queue. If it still exists and has dirty data when it reaches the
top of the queue, it is sync'ed. This approach evens out the load
on the underlying I/O system and avoids writing short-lived files.
The papers on trickle-sync tend to favor aging based on buffers
rather than files. However, I sync on file age rather than buffer
age because the data structures are much smaller as there are
typically far fewer files than buffers. Although this can make the
I/O spikey when a big file times out, it is still much better than
the wholesale sync's that were happening before. It also adapts
much better to the soft update code where I want to control
aging to improve performance (inodes age in 10 seconds, directories
in 15 seconds, files in 30 seconds). This ensures that most
dependencies are gone (e.g., inodes are written when directory
entries want to go to disk) reducing the amount of rollback that
is needed.
The other main kernel change is to split the vnode freelist into
two separate lists. One for vnodes that are still being used to
identify buffers and the other for those vnodes no longer identifying
any buffers. The latter list is used by getnewvnode in preference
to the former.
Packaging of Kernel Changes
The sys subdirectory contains the changes and additions to the
kernel. My goal in writing this code was to minimize the changes
that need to be made to the kernel. Thus, most of the new code
is contained in the two new files softdep.h and ffs_softdep.c.
The rest of the kernel changes are simply inserting hooks to
call into these two new files. Although there has been some
structural reorganization of the filesystem code to accommodate
gathering the information required by the soft update code,
the actual ordering of filesystem operations when soft updates
are disabled is unchanged.
The kernel changes are packaged as a set of diffs. As I am
doing my development in BSD/OS, the diffs are relative to the
BSD/OS versions of the files. Because BSD/OS recently had
4.4BSD-Lite2 merged into it, the Lite2 files are a good starting
point for figuring out the changes. There are 40 files that
require change plus the two new files. Most of these files have
only a few lines of changes in them. However, four files have
fairly extensive changes: kern/vfs_subr.c, ufs/ufs/ufs_lookup.c,
ufs/ufs/ufs_vnops.c, and ufs/ffs/ffs_alloc.c. For these four
files, I have provided the original Lite2 version, the Lite2
version with the diffs merged in, and the diffs between the
BSD/OS and merged version. Even so, I expect that there will
be some difficulty in doing the merge; I am certainly willing
to assist in helping get the code merged into your system.
Packaging of Utility Changes
The utilities subdirectory contains the changes and additions
to the utilities. There are diffs to three utilities enclosed:
tunefs - add a flag to enable and disable soft updates
mount - print out whether soft updates are enabled and
also statistics on number of sync and async writes
fsck - tighter checks on acceptable errors and a slightly
different policy for what to put in lost+found on
filesystems using soft updates
In addition you should recompile vmstat so as to get reports
on the 13 new memory types used by the soft update code.
It is not necessary to use the new version of fsck, however it
would aid in my debugging if you do. Also, because of the time
lag between deleting a directory entry and the inode it
references, you will find a lot more files showing up in your
lost+found if you do not use the new version. Note that the
new version checks for the soft update flag in the superblock
and only uses the new algorithms if it is set. So, it will run
unchanged on the filesystems that are not using soft updates.
Operation
Once you have booted a kernel that incorporates the soft update
code and installed the updated utilities, do the following:
1) Comment out the update program in /etc/rc.
2) Run `tunefs -n enable' on one or more test filesystems.
3) Mount these filesystems and then type `mount' to ensure that
they have been enabled for soft updates.
4) Copy the test directory to a softdep filesystem, chdir into
it and run `./doit'. You may want to check out each of the
three subtests individually first: doit1 - andrew benchmarks,
doit2 - copy and removal of /etc, doit3 - find from /.
====
Additional notes from Feb 13
hen removing huge directories of files, it is possible to get
the incore state arbitrarily far ahead of the disk. Maintaining
all the associated depedency information can exhaust the kernel
malloc arena. To avoid this senario, I have put some limits on
the soft update code so that it will not be allowed to rampage
through all of the kernel memory. I enclose below the relevant
patches to vnode.h and vfs_subr.c (which allow the soft update
code to speed up the filesystem syncer process). I have also
included the diffs for ffs_softdep.c. I hope to make a pass over
ffs_softdep.c to isolate the differences with my standard version
so that these diffs are less painful to incorporate.
Since I know you like to play with tuning, I have put the relevant
knobs on sysctl debug variables. The tuning knobs can be viewed
with `sysctl debug' and set with `sysctl -w debug.<name>=value'.
The knobs are as follows:
debug.max_softdeps - limit on any given resource
debug.tickdelay - ticks to delay before allocating
debug.max_limit_hit - number of times tickdelay imposed
debug.rush_requests - number of rush requests to filesystem syncer
The max_softdeps limit is derived from vnodesdesired which in
turn is sized based on the amount of memory on the machine.
When the limit is hit, a process requesting a resource first
tries to speed up the filesystem syncer process. Such a
request is recorded as a rush_request. After syncdelay / 2
unserviced rush requests (typically 15) are in the filesystem
syncers queue (i.e., it is more than 15 seconds behind in its
work), the process requesting the memory is put to sleep for
tickdelay seconds. Such a delay is recorded in max_limit_hit.
Following this delay it is granted its memory without further
delay. I have tried the following experiments in which I
delete an MH directory containing 16,703 files:
Run # 1 2 3
max_softdeps 4496 4496 4496
tickdelay 100 == 1 sec 20 == 0.2 sec 2 == 0.02 sec
max_limit_hit 16 == 16 sec 27 == 5.4 sec 203 == 4.1 sec
rush_requests 147 102 93
run time 57 sec 46 sec 45 sec
I/O's 781 859 936
When run with no limits, it completes in 40 seconds. So, the
time spent in delay is directly added to the bottom line.
Shortening the tick delay does cut down the total running time,
but at the expense of generating more total I/O operations
due to the rush orders being sent to the filesystem syncer.
Although the number of rush orders decreases with a shorter
tick delay, there are more requests in each order, hence the
increase in I/O count. Also, although the I/O count does rise
with a shorter delay, it is still at least an order of magnitude
less than without soft updates. Anyway, you may want to play
around with these value to see what works best and to see if
you can get an insight into how best to tune them. If you get
out of memory panic's, then you have max_softdeps set too high.
The max_limit_hit and rush_requests show be reset to zero
before each run. The minimum legal value for tickdelay is 2
(if you set it below that, the code will use 2).
-548
View File
@@ -1,548 +0,0 @@
/*
* Copyright 1998 Marshall Kirk McKusick. All Rights Reserved.
*
* The soft updates code is derived from the appendix of a University
* of Michigan technical report (Gregory R. Ganger and Yale N. Patt,
* "Soft Updates: A Solution to the Metadata Update Problem in File
* Systems", CSE-TR-254-95, August 1995).
*
* The following are the copyrights and redistribution conditions that
* apply to this copy of the soft update software. For a license
* to use, redistribute or sell the soft update software under
* conditions other than those described here, please contact the
* author at one of the following addresses:
*
* Marshall Kirk McKusick mckusick@mckusick.com
* 1614 Oxford Street +1-510-843-9542
* Berkeley, CA 94709-1608
* USA
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. None of the names of McKusick, Ganger, Patt, or the University of
* Michigan may be used to endorse or promote products derived from
* this software without specific prior written permission.
* 4. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for any accompanying software
* that uses this software. This source code must either be included
* in the distribution or be available for no more than the cost of
* distribution plus a nominal fee, and must be freely redistributable
* under reasonable conditions. For an executable file, complete
* source code means the source code for all modules it contains.
* It does not mean source code for modules or files that typically
* accompany the operating system on which the executable file runs,
* e.g., standard library modules or system header files.
*
* THIS SOFTWARE IS PROVIDED BY MARSHALL KIRK MCKUSICK ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL MARSHALL KIRK MCKUSICK BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)softdep.h 9.6 (McKusick) 2/25/99
* $Id: softdep.h,v 1.5 1999/03/02 00:19:47 mckusick Exp $
*/
#include <sys/queue.h>
/*
* Allocation dependencies are handled with undo/redo on the in-memory
* copy of the data. A particular data dependency is eliminated when
* it is ALLCOMPLETE: that is ATTACHED, DEPCOMPLETE, and COMPLETE.
*
* ATTACHED means that the data is not currently being written to
* disk. UNDONE means that the data has been rolled back to a safe
* state for writing to the disk. When the I/O completes, the data is
* restored to its current form and the state reverts to ATTACHED.
* The data must be locked throughout the rollback, I/O, and roll
* forward so that the rolled back information is never visible to
* user processes. The COMPLETE flag indicates that the item has been
* written. For example, a dependency that requires that an inode be
* written will be marked COMPLETE after the inode has been written
* to disk. The DEPCOMPLETE flag indicates the completion of any other
* dependencies such as the writing of a cylinder group map has been
* completed. A dependency structure may be freed only when both it
* and its dependencies have completed and any rollbacks that are in
* progress have finished as indicated by the set of ALLCOMPLETE flags
* all being set. The two MKDIR flags indicate additional dependencies
* that must be done when creating a new directory. MKDIR_BODY is
* cleared when the directory data block containing the "." and ".."
* entries has been written. MKDIR_PARENT is cleared when the parent
* inode with the increased link count for ".." has been written. When
* both MKDIR flags have been cleared, the DEPCOMPLETE flag is set to
* indicate that the directory dependencies have been completed. The
* writing of the directory inode itself sets the COMPLETE flag which
* then allows the directory entry for the new directory to be written
* to disk. The RMDIR flag marks a dirrem structure as representing
* the removal of a directory rather than a file. When the removal
* dependencies are completed, additional work needs to be done
* (truncation of the "." and ".." entries, an additional decrement
* of the associated inode, and a decrement of the parent inode). The
* DIRCHG flag marks a diradd structure as representing the changing
* of an existing entry rather than the addition of a new one. When
* the update is complete the dirrem associated with the inode for
* the old name must be added to the worklist to do the necessary
* reference count decrement. The GOINGAWAY flag indicates that the
* data structure is frozen from further change until its dependencies
* have been completed and its resources freed after which it will be
* discarded. The IOSTARTED flag prevents multiple calls to the I/O
* start routine from doing multiple rollbacks. The ONWORKLIST flag
* shows whether the structure is currently linked onto a worklist.
*/
#define ATTACHED 0x0001
#define UNDONE 0x0002
#define COMPLETE 0x0004
#define DEPCOMPLETE 0x0008
#define MKDIR_PARENT 0x0010
#define MKDIR_BODY 0x0020
#define RMDIR 0x0040
#define DIRCHG 0x0080
#define GOINGAWAY 0x0100
#define IOSTARTED 0x0200
#define ONWORKLIST 0x8000
#define ALLCOMPLETE (ATTACHED | COMPLETE | DEPCOMPLETE)
/*
* The workitem queue.
*
* It is sometimes useful and/or necessary to clean up certain dependencies
* in the background rather than during execution of an application process
* or interrupt service routine. To realize this, we append dependency
* structures corresponding to such tasks to a "workitem" queue. In a soft
* updates implementation, most pending workitems should not wait for more
* than a couple of seconds, so the filesystem syncer process awakens once
* per second to process the items on the queue.
*/
/* LIST_HEAD(workhead, worklist); -- declared in buf.h */
/*
* Each request can be linked onto a work queue through its worklist structure.
* To avoid the need for a pointer to the structure itself, this structure
* MUST be declared FIRST in each type in which it appears! If more than one
* worklist is needed in the structure, then a wk_data field must be added
* and the macros below changed to use it.
*/
struct worklist {
LIST_ENTRY(worklist) wk_list; /* list of work requests */
unsigned short wk_type; /* type of request */
unsigned short wk_state; /* state flags */
};
#define WK_DATA(wk) ((void *)(wk))
#define WK_PAGEDEP(wk) ((struct pagedep *)(wk))
#define WK_INODEDEP(wk) ((struct inodedep *)(wk))
#define WK_NEWBLK(wk) ((struct newblk *)(wk))
#define WK_BMSAFEMAP(wk) ((struct bmsafemap *)(wk))
#define WK_ALLOCDIRECT(wk) ((struct allocdirect *)(wk))
#define WK_INDIRDEP(wk) ((struct indirdep *)(wk))
#define WK_ALLOCINDIR(wk) ((struct allocindir *)(wk))
#define WK_FREEFRAG(wk) ((struct freefrag *)(wk))
#define WK_FREEBLKS(wk) ((struct freeblks *)(wk))
#define WK_FREEFILE(wk) ((struct freefile *)(wk))
#define WK_DIRADD(wk) ((struct diradd *)(wk))
#define WK_MKDIR(wk) ((struct mkdir *)(wk))
#define WK_DIRREM(wk) ((struct dirrem *)(wk))
/*
* Various types of lists
*/
LIST_HEAD(dirremhd, dirrem);
LIST_HEAD(diraddhd, diradd);
LIST_HEAD(newblkhd, newblk);
LIST_HEAD(inodedephd, inodedep);
LIST_HEAD(allocindirhd, allocindir);
LIST_HEAD(allocdirecthd, allocdirect);
TAILQ_HEAD(allocdirectlst, allocdirect);
/*
* The "pagedep" structure tracks the various dependencies related to
* a particular directory page. If a directory page has any dependencies,
* it will have a pagedep linked to its associated buffer. The
* pd_dirremhd list holds the list of dirrem requests which decrement
* inode reference counts. These requests are processed after the
* directory page with the corresponding zero'ed entries has been
* written. The pd_diraddhd list maintains the list of diradd requests
* which cannot be committed until their corresponding inode has been
* written to disk. Because a directory may have many new entries
* being created, several lists are maintained hashed on bits of the
* offset of the entry into the directory page to keep the lists from
* getting too long. Once a new directory entry has been cleared to
* be written, it is moved to the pd_pendinghd list. After the new
* entry has been written to disk it is removed from the pd_pendinghd
* list, any removed operations are done, and the dependency structure
* is freed.
*/
#define DAHASHSZ 6
#define DIRADDHASH(offset) (((offset) >> 2) % DAHASHSZ)
struct pagedep {
struct worklist pd_list; /* page buffer */
# define pd_state pd_list.wk_state /* check for multiple I/O starts */
LIST_ENTRY(pagedep) pd_hash; /* hashed lookup */
struct mount *pd_mnt; /* associated mount point */
ino_t pd_ino; /* associated file */
ufs_lbn_t pd_lbn; /* block within file */
struct dirremhd pd_dirremhd; /* dirrem's waiting for page */
struct diraddhd pd_diraddhd[DAHASHSZ]; /* diradd dir entry updates */
struct diraddhd pd_pendinghd; /* directory entries awaiting write */
};
/*
* The "inodedep" structure tracks the set of dependencies associated
* with an inode. One task that it must manage is delayed operations
* (i.e., work requests that must be held until the inodedep's associated
* inode has been written to disk). Getting an inode from its incore
* state to the disk requires two steps to be taken by the filesystem
* in this order: first the inode must be copied to its disk buffer by
* the VOP_UPDATE operation; second the inode's buffer must be written
* to disk. To ensure that both operations have happened in the required
* order, the inodedep maintains two lists. Delayed operations are
* placed on the id_inowait list. When the VOP_UPDATE is done, all
* operations on the id_inowait list are moved to the id_bufwait list.
* When the buffer is written, the items on the id_bufwait list can be
* safely moved to the work queue to be processed. A second task of the
* inodedep structure is to track the status of block allocation within
* the inode. Each block that is allocated is represented by an
* "allocdirect" structure (see below). It is linked onto the id_newinoupdt
* list until both its contents and its allocation in the cylinder
* group map have been written to disk. Once these dependencies have been
* satisfied, it is removed from the id_newinoupdt list and any followup
* actions such as releasing the previous block or fragment are placed
* on the id_inowait list. When an inode is updated (a VOP_UPDATE is
* done), the "inodedep" structure is linked onto the buffer through
* its worklist. Thus, it will be notified when the buffer is about
* to be written and when it is done. At the update time, all the
* elements on the id_newinoupdt list are moved to the id_inoupdt list
* since those changes are now relevant to the copy of the inode in the
* buffer. Also at update time, the tasks on the id_inowait list are
* moved to the id_bufwait list so that they will be executed when
* the updated inode has been written to disk. When the buffer containing
* the inode is written to disk, any updates listed on the id_inoupdt
* list are rolled back as they are not yet safe. Following the write,
* the changes are once again rolled forward and any actions on the
* id_bufwait list are processed (since those actions are now safe).
* The entries on the id_inoupdt and id_newinoupdt lists must be kept
* sorted by logical block number to speed the calculation of the size
* of the rolled back inode (see explanation in initiate_write_inodeblock).
* When a directory entry is created, it is represented by a diradd.
* The diradd is added to the id_inowait list as it cannot be safely
* written to disk until the inode that it represents is on disk. After
* the inode is written, the id_bufwait list is processed and the diradd
* entries are moved to the id_pendinghd list where they remain until
* the directory block containing the name has been written to disk.
* The purpose of keeping the entries on the id_pendinghd list is so that
* the softdep_fsync function can find and push the inode's directory
* name(s) as part of the fsync operation for that file.
*/
struct inodedep {
struct worklist id_list; /* buffer holding inode block */
# define id_state id_list.wk_state /* inode dependency state */
LIST_ENTRY(inodedep) id_hash; /* hashed lookup */
struct fs *id_fs; /* associated filesystem */
ino_t id_ino; /* dependent inode */
nlink_t id_nlinkdelta; /* saved effective link count */
struct dinode *id_savedino; /* saved dinode contents */
LIST_ENTRY(inodedep) id_deps; /* bmsafemap's list of inodedep's */
struct buf *id_buf; /* related bmsafemap (if pending) */
off_t id_savedsize; /* file size saved during rollback */
struct workhead id_pendinghd; /* entries awaiting directory write */
struct workhead id_bufwait; /* operations after inode written */
struct workhead id_inowait; /* operations waiting inode update */
struct allocdirectlst id_inoupdt; /* updates before inode written */
struct allocdirectlst id_newinoupdt; /* updates when inode written */
};
/*
* A "newblk" structure is attached to a bmsafemap structure when a block
* or fragment is allocated from a cylinder group. Its state is set to
* DEPCOMPLETE when its cylinder group map is written. It is consumed by
* an associated allocdirect or allocindir allocation which will attach
* themselves to the bmsafemap structure if the newblk's DEPCOMPLETE flag
* is not set (i.e., its cylinder group map has not been written).
*/
struct newblk {
LIST_ENTRY(newblk) nb_hash; /* hashed lookup */
struct fs *nb_fs; /* associated filesystem */
ufs_daddr_t nb_newblkno; /* allocated block number */
int nb_state; /* state of bitmap dependency */
LIST_ENTRY(newblk) nb_deps; /* bmsafemap's list of newblk's */
struct bmsafemap *nb_bmsafemap; /* associated bmsafemap */
};
/*
* A "bmsafemap" structure maintains a list of dependency structures
* that depend on the update of a particular cylinder group map.
* It has lists for newblks, allocdirects, allocindirs, and inodedeps.
* It is attached to the buffer of a cylinder group block when any of
* these things are allocated from the cylinder group. It is freed
* after the cylinder group map is written and the state of its
* dependencies are updated with DEPCOMPLETE to indicate that it has
* been processed.
*/
struct bmsafemap {
struct worklist sm_list; /* cylgrp buffer */
struct buf *sm_buf; /* associated buffer */
struct allocdirecthd sm_allocdirecthd; /* allocdirect deps */
struct allocindirhd sm_allocindirhd; /* allocindir deps */
struct inodedephd sm_inodedephd; /* inodedep deps */
struct newblkhd sm_newblkhd; /* newblk deps */
};
/*
* An "allocdirect" structure is attached to an "inodedep" when a new block
* or fragment is allocated and pointed to by the inode described by
* "inodedep". The worklist is linked to the buffer that holds the block.
* When the block is first allocated, it is linked to the bmsafemap
* structure associated with the buffer holding the cylinder group map
* from which it was allocated. When the cylinder group map is written
* to disk, ad_state has the DEPCOMPLETE flag set. When the block itself
* is written, the COMPLETE flag is set. Once both the cylinder group map
* and the data itself have been written, it is safe to write the inode
* that claims the block. If there was a previous fragment that had been
* allocated before the file was increased in size, the old fragment may
* be freed once the inode claiming the new block is written to disk.
* This ad_fragfree request is attached to the id_inowait list of the
* associated inodedep (pointed to by ad_inodedep) for processing after
* the inode is written.
*/
struct allocdirect {
struct worklist ad_list; /* buffer holding block */
# define ad_state ad_list.wk_state /* block pointer state */
TAILQ_ENTRY(allocdirect) ad_next; /* inodedep's list of allocdirect's */
ufs_lbn_t ad_lbn; /* block within file */
ufs_daddr_t ad_newblkno; /* new value of block pointer */
ufs_daddr_t ad_oldblkno; /* old value of block pointer */
long ad_newsize; /* size of new block */
long ad_oldsize; /* size of old block */
LIST_ENTRY(allocdirect) ad_deps; /* bmsafemap's list of allocdirect's */
struct buf *ad_buf; /* cylgrp buffer (if pending) */
struct inodedep *ad_inodedep; /* associated inodedep */
struct freefrag *ad_freefrag; /* fragment to be freed (if any) */
};
/*
* A single "indirdep" structure manages all allocation dependencies for
* pointers in an indirect block. The up-to-date state of the indirect
* block is stored in ir_savedata. The set of pointers that may be safely
* written to the disk is stored in ir_safecopy. The state field is used
* only to track whether the buffer is currently being written (in which
* case it is not safe to update ir_safecopy). Ir_deplisthd contains the
* list of allocindir structures, one for each block that needs to be
* written to disk. Once the block and its bitmap allocation have been
* written the safecopy can be updated to reflect the allocation and the
* allocindir structure freed. If ir_state indicates that an I/O on the
* indirect block is in progress when ir_safecopy is to be updated, the
* update is deferred by placing the allocindir on the ir_donehd list.
* When the I/O on the indirect block completes, the entries on the
* ir_donehd list are processed by updating their corresponding ir_safecopy
* pointers and then freeing the allocindir structure.
*/
struct indirdep {
struct worklist ir_list; /* buffer holding indirect block */
# define ir_state ir_list.wk_state /* indirect block pointer state */
caddr_t ir_saveddata; /* buffer cache contents */
struct buf *ir_savebp; /* buffer holding safe copy */
struct allocindirhd ir_donehd; /* done waiting to update safecopy */
struct allocindirhd ir_deplisthd; /* allocindir deps for this block */
};
/*
* An "allocindir" structure is attached to an "indirdep" when a new block
* is allocated and pointed to by the indirect block described by the
* "indirdep". The worklist is linked to the buffer that holds the new block.
* When the block is first allocated, it is linked to the bmsafemap
* structure associated with the buffer holding the cylinder group map
* from which it was allocated. When the cylinder group map is written
* to disk, ai_state has the DEPCOMPLETE flag set. When the block itself
* is written, the COMPLETE flag is set. Once both the cylinder group map
* and the data itself have been written, it is safe to write the entry in
* the indirect block that claims the block; the "allocindir" dependency
* can then be freed as it is no longer applicable.
*/
struct allocindir {
struct worklist ai_list; /* buffer holding indirect block */
# define ai_state ai_list.wk_state /* indirect block pointer state */
LIST_ENTRY(allocindir) ai_next; /* indirdep's list of allocindir's */
int ai_offset; /* pointer offset in indirect block */
ufs_daddr_t ai_newblkno; /* new block pointer value */
ufs_daddr_t ai_oldblkno; /* old block pointer value */
struct freefrag *ai_freefrag; /* block to be freed when complete */
struct indirdep *ai_indirdep; /* address of associated indirdep */
LIST_ENTRY(allocindir) ai_deps; /* bmsafemap's list of allocindir's */
struct buf *ai_buf; /* cylgrp buffer (if pending) */
};
/*
* A "freefrag" structure is attached to an "inodedep" when a previously
* allocated fragment is replaced with a larger fragment, rather than extended.
* The "freefrag" structure is constructed and attached when the replacement
* block is first allocated. It is processed after the inode claiming the
* bigger block that replaces it has been written to disk. Note that the
* ff_state field is is used to store the uid, so may lose data. However,
* the uid is used only in printing an error message, so is not critical.
* Keeping it in a short keeps the data structure down to 32 bytes.
*/
struct freefrag {
struct worklist ff_list; /* id_inowait or delayed worklist */
# define ff_state ff_list.wk_state /* owning user; should be uid_t */
struct vnode *ff_devvp; /* filesystem device vnode */
struct fs *ff_fs; /* addr of superblock */
ufs_daddr_t ff_blkno; /* fragment physical block number */
long ff_fragsize; /* size of fragment being deleted */
ino_t ff_inum; /* owning inode number */
};
/*
* A "freeblks" structure is attached to an "inodedep" when the
* corresponding file's length is reduced to zero. It records all
* the information needed to free the blocks of a file after its
* zero'ed inode has been written to disk.
*/
struct freeblks {
struct worklist fb_list; /* id_inowait or delayed worklist */
ino_t fb_previousinum; /* inode of previous owner of blocks */
struct vnode *fb_devvp; /* filesystem device vnode */
struct fs *fb_fs; /* addr of superblock */
off_t fb_oldsize; /* previous file size */
off_t fb_newsize; /* new file size */
int fb_chkcnt; /* used to check cnt of blks released */
uid_t fb_uid; /* uid of previous owner of blocks */
ufs_daddr_t fb_dblks[NDADDR]; /* direct blk ptrs to deallocate */
ufs_daddr_t fb_iblks[NIADDR]; /* indirect blk ptrs to deallocate */
};
/*
* A "freefile" structure is attached to an inode when its
* link count is reduced to zero. It marks the inode as free in
* the cylinder group map after the zero'ed inode has been written
* to disk and any associated blocks and fragments have been freed.
*/
struct freefile {
struct worklist fx_list; /* id_inowait or delayed worklist */
mode_t fx_mode; /* mode of inode */
ino_t fx_oldinum; /* inum of the unlinked file */
struct vnode *fx_devvp; /* filesystem device vnode */
struct fs *fx_fs; /* addr of superblock */
};
/*
* A "diradd" structure is linked to an "inodedep" id_inowait list when a
* new directory entry is allocated that references the inode described
* by "inodedep". When the inode itself is written (either the initial
* allocation for new inodes or with the increased link count for
* existing inodes), the COMPLETE flag is set in da_state. If the entry
* is for a newly allocated inode, the "inodedep" structure is associated
* with a bmsafemap which prevents the inode from being written to disk
* until the cylinder group has been updated. Thus the da_state COMPLETE
* flag cannot be set until the inode bitmap dependency has been removed.
* When creating a new file, it is safe to write the directory entry that
* claims the inode once the referenced inode has been written. Since
* writing the inode clears the bitmap dependencies, the DEPCOMPLETE flag
* in the diradd can be set unconditionally when creating a file. When
* creating a directory, there are two additional dependencies described by
* mkdir structures (see their description below). When these dependencies
* are resolved the DEPCOMPLETE flag is set in the diradd structure.
* If there are multiple links created to the same inode, there will be
* a separate diradd structure created for each link. The diradd is
* linked onto the pg_diraddhd list of the pagedep for the directory
* page that contains the entry. When a directory page is written,
* the pg_diraddhd list is traversed to rollback any entries that are
* not yet ready to be written to disk. If a directory entry is being
* changed (by rename) rather than added, the DIRCHG flag is set and
* the da_previous entry points to the entry that will be "removed"
* once the new entry has been committed. During rollback, entries
* with da_previous are replaced with the previous inode number rather
* than zero.
*
* The overlaying of da_pagedep and da_previous is done to keep the
* structure down to 32 bytes in size on a 32-bit machine. If a
* da_previous entry is present, the pointer to its pagedep is available
* in the associated dirrem entry. If the DIRCHG flag is set, the
* da_previous entry is valid; if not set the da_pagedep entry is valid.
* The DIRCHG flag never changes; it is set when the structure is created
* if appropriate and is never cleared.
*/
struct diradd {
struct worklist da_list; /* id_inowait or id_pendinghd list */
# define da_state da_list.wk_state /* state of the new directory entry */
LIST_ENTRY(diradd) da_pdlist; /* pagedep holding directory block */
doff_t da_offset; /* offset of new dir entry in dir blk */
ino_t da_newinum; /* inode number for the new dir entry */
union {
struct dirrem *dau_previous; /* entry being replaced in dir change */
struct pagedep *dau_pagedep; /* pagedep dependency for addition */
} da_un;
};
#define da_previous da_un.dau_previous
#define da_pagedep da_un.dau_pagedep
/*
* Two "mkdir" structures are needed to track the additional dependencies
* associated with creating a new directory entry. Normally a directory
* addition can be committed as soon as the newly referenced inode has been
* written to disk with its increased link count. When a directory is
* created there are two additional dependencies: writing the directory
* data block containing the "." and ".." entries (MKDIR_BODY) and writing
* the parent inode with the increased link count for ".." (MKDIR_PARENT).
* These additional dependencies are tracked by two mkdir structures that
* reference the associated "diradd" structure. When they have completed,
* they set the DEPCOMPLETE flag on the diradd so that it knows that its
* extra dependencies have been completed. The md_state field is used only
* to identify which type of dependency the mkdir structure is tracking.
* It is not used in the mainline code for any purpose other than consistency
* checking. All the mkdir structures in the system are linked together on
* a list. This list is needed so that a diradd can find its associated
* mkdir structures and deallocate them if it is prematurely freed (as for
* example if a mkdir is immediately followed by a rmdir of the same directory).
* Here, the free of the diradd must traverse the list to find the associated
* mkdir structures that reference it. The deletion would be faster if the
* diradd structure were simply augmented to have two pointers that referenced
* the associated mkdir's. However, this would increase the size of the diradd
* structure from 32 to 64-bits to speed a very infrequent operation.
*/
struct mkdir {
struct worklist md_list; /* id_inowait or buffer holding dir */
# define md_state md_list.wk_state /* type: MKDIR_PARENT or MKDIR_BODY */
struct diradd *md_diradd; /* associated diradd */
struct buf *md_buf; /* MKDIR_BODY: buffer holding dir */
LIST_ENTRY(mkdir) md_mkdirs; /* list of all mkdirs */
};
LIST_HEAD(mkdirlist, mkdir) mkdirlisthd;
/*
* A "dirrem" structure describes an operation to decrement the link
* count on an inode. The dirrem structure is attached to the pg_dirremhd
* list of the pagedep for the directory page that contains the entry.
* It is processed after the directory page with the deleted entry has
* been written to disk.
*
* The overlaying of dm_pagedep and dm_dirinum is done to keep the
* structure down to 32 bytes in size on a 32-bit machine. It works
* because they are never used concurrently.
*/
struct dirrem {
struct worklist dm_list; /* delayed worklist */
# define dm_state dm_list.wk_state /* state of the old directory entry */
LIST_ENTRY(dirrem) dm_next; /* pagedep's list of dirrem's */
struct mount *dm_mnt; /* associated mount point */
ino_t dm_oldinum; /* inum of the removed dir entry */
union {
struct pagedep *dmu_pagedep; /* pagedep dependency for remove */
ino_t dmu_dirinum; /* parent inode number (for rmdir) */
} dm_un;
};
#define dm_pagedep dm_un.dmu_pagedep
#define dm_dirinum dm_un.dmu_dirinum
+612 -366
View File
File diff suppressed because it is too large. Load diff
+84 -53
View File
@@ -3,7 +3,7 @@
* SCSI controllers. This is used to implement product specific
* probe and attach routines.
*
* Copyright (c) 1994, 1995, 1996, 1997, 1998 Justin T. Gibbs.
* Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999 Justin T. Gibbs.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aic7xxx.h,v 1.5 1999/01/14 06:14:15 gibbs Exp $
* $Id: aic7xxx.h,v 1.5.2.1 1999/03/07 00:40:47 gibbs Exp $
*/
#ifndef _AIC7XXX_H_
@@ -45,20 +45,29 @@
#include <pci/pcivar.h> /* for pcici_t */
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
/*
* The maximum transfer per S/G segment.
*/
#define AHC_MAXTRANSFER_SIZE 0x00ffffff /* limited by 24bit counter */
#define AHC_NSEG 32 /* The number of dma segments supported.
* AHC_NSEG can be maxed out at 256 entries,
* but the kernel will never need to transfer
* such a large (1MB) request. To reduce the
* driver's memory consumption, we reduce the
* max to 32. 16 would work if all transfers
* are paged alined since the kernel will only
* generate at most a 64k transfer, but to
* handle non-page aligned transfers, you need
* 17, so we round to the next power of two
* to make allocating SG space easy and
* efficient.
*/
/*
* The number of dma segments supported. The current implementation limits
* us to 255 S/G entries (this may change to be unlimited at some point).
* To reduce the driver's memory consumption, we further limit the number
* supported to be sufficient to handle the largest mapping supported by
* the kernel, MAXPHYS. Assuming the transfer is as fragmented as possible
* and unaligned, this turns out to be the number of paged sized transfers
* in MAXPHYS plus an extra element to handle any unaligned residual.
*/
#define AHC_NSEG (MIN(btoc(MAXPHYS) + 1, 255))
#define AHC_SCB_MAX 255 /*
* Up to 255 SCBs on some types of aic7xxx
@@ -75,9 +84,7 @@
* wrap point of an 8bit counter.
*/
#if defined(__FreeBSD__)
extern u_long ahc_unit;
#endif
struct ahc_dma_seg {
u_int32_t addr;
@@ -112,16 +119,17 @@ typedef enum {
AHC_SG_PRELOAD = 0x0080, /* Can perform auto-SG preload */
AHC_SPIOCAP = 0x0100, /* Has a Serial Port I/O Cap Register */
AHC_MULTI_TID = 0x0200, /* Has bitmask of TIDs for select-in */
AHC_HS_MAILBOX = 0x0400, /* Has HS_MAILBOX register */
AHC_AIC7770_FE = AHC_FENONE,
AHC_AIC7850_FE = AHC_FENONE|AHC_SPIOCAP,
AHC_AIC7860_FE = AHC_ULTRA|AHC_SPIOCAP,
AHC_AIC7870_FE = AHC_FENONE,
AHC_AIC7880_FE = AHC_ULTRA,
AHC_AIC7890_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA2|AHC_QUEUE_REGS
|AHC_SG_PRELOAD|AHC_MULTI_TID,
|AHC_SG_PRELOAD|AHC_MULTI_TID|AHC_HS_MAILBOX,
AHC_AIC7895_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA,
AHC_AIC7896_FE = AHC_MORE_SRAM|AHC_CMD_CHAN|AHC_ULTRA2|AHC_QUEUE_REGS
|AHC_SG_PRELOAD|AHC_MULTI_TID,
|AHC_SG_PRELOAD|AHC_MULTI_TID|AHC_HS_MAILBOX,
} ahc_feature;
typedef enum {
@@ -138,7 +146,6 @@ typedef enum {
* SRAM, we use the default target
* settings.
*/
AHC_INDIRECT_PAGING = 0x008,
AHC_SHARED_SRAM = 0x010,
AHC_LARGE_SEEPROM = 0x020,/* Uses C56_66 not C46 */
AHC_RESET_BUS_A = 0x040,
@@ -228,28 +235,13 @@ struct hardware_scb {
struct scb {
struct hardware_scb *hscb;
STAILQ_ENTRY(scb) links; /* for chaining */
SLIST_ENTRY(scb) links; /* for chaining */
union ccb *ccb; /* the ccb for this cmd */
scb_flag flags;
bus_dmamap_t dmamap;
struct ahc_dma_seg *ahc_dma;/* Pointer to SG segments */
u_int32_t ahc_dmaphys;/* Phsical address of SG list */
u_int sg_count;/* How full ahc_dma_seg is */
};
struct scb_data {
struct hardware_scb *hscbs; /* Array of hardware SCBs */
struct scb *scbarray[AHC_SCB_MAX]; /* Array of kernel SCBs */
STAILQ_HEAD(, scb) free_scbs; /*
* Pool of SCBs ready to be assigned
* commands to execute.
*/
u_int8_t numscbs;
u_int8_t maxhscbs; /* Number of SCBs on the card */
u_int8_t maxscbs; /*
* Max SCBs we allocate total including
* any that will force us to page SCBs
*/
scb_flag flags;
bus_dmamap_t dmamap;
struct ahc_dma_seg *sg_list;
bus_addr_t sg_list_phys;
u_int sg_count;/* How full ahc_dma_seg is */
};
/*
@@ -402,10 +394,45 @@ typedef enum {
MSG_TYPE_TARGET_MSGIN = 0x04
} ahc_msg_type;
struct sg_map_node {
bus_dmamap_t sg_dmamap;
bus_addr_t sg_physaddr;
struct ahc_dma_seg* sg_vaddr;
SLIST_ENTRY(sg_map_node) links;
};
struct scb_data {
struct hardware_scb *hscbs; /* Array of hardware SCBs */
struct scb *scbarray; /* Array of kernel SCBs */
SLIST_HEAD(, scb) free_scbs; /*
* Pool of SCBs ready to be assigned
* commands to execute.
*/
struct scsi_sense_data *sense; /* Per SCB sense data */
/*
* "Bus" addresses of our data structures.
*/
bus_dma_tag_t hscb_dmat; /* dmat for our hardware SCB array */
bus_dmamap_t hscb_dmamap;
bus_addr_t hscb_busaddr;
bus_dma_tag_t sense_dmat;
bus_dmamap_t sense_dmamap;
bus_addr_t sense_busaddr;
bus_dma_tag_t sg_dmat; /* dmat for our sg segments */
SLIST_HEAD(, sg_map_node) sg_maps;
u_int8_t numscbs;
u_int8_t maxhscbs; /* Number of SCBs on the card */
u_int8_t init_level; /*
* How far we've initialized
* this structure.
*/
};
struct ahc_softc {
bus_space_tag_t tag;
bus_space_handle_t bsh;
bus_dma_tag_t dmat;
bus_dma_tag_t buffer_dmat; /* dmat for buffer I/O */
struct scb_data *scb_data;
/*
@@ -447,14 +474,14 @@ struct ahc_softc {
/* Command Queues */
u_int8_t qoutfifonext;
u_int8_t qinfifonext;
u_int8_t qoutfifo[256];
u_int8_t qinfifo[256];
u_int8_t *qoutfifo;
u_int8_t *qinfifo;
/*
* 256 byte array storing the SCBID of outstanding
* untagged SCBs indexed by TCL.
*/
u_int8_t untagged_scbs[256];
u_int8_t *untagged_scbs;
/*
* Hooks into the XPT.
@@ -501,13 +528,16 @@ struct ahc_softc {
u_int msgout_index; /* Current index in msgout */
u_int msgin_index; /* Current index in msgin */
bus_dma_tag_t parent_dmat;
bus_dma_tag_t shared_data_dmat;
bus_dmamap_t shared_data_dmamap;
bus_addr_t shared_data_busaddr;
/* Number of enabled target mode device on this card */
u_int enabled_luns;
/*
* "Bus" addresses of our data structures.
*/
u_int32_t hscb_busaddr;
/* Initialization level of this data structure */
u_int init_level;
};
struct full_ahc_softc {
@@ -530,10 +560,11 @@ extern int ahc_debug; /* Initialized in i386/scsi/aic7xxx.c */
char *ahc_name(struct ahc_softc *ahc);
struct ahc_softc *ahc_alloc(int unit, u_int32_t io_base,
vm_offset_t maddr, ahc_chip chip,
ahc_feature features, ahc_flag flags,
struct scb_data *scb_data);
struct ahc_softc*
ahc_alloc(int unit, u_int32_t io_base, vm_offset_t maddr,
bus_dma_tag_t parent_dmat, ahc_chip chip,
ahc_feature features, ahc_flag flags,
struct scb_data *scb_data);
int ahc_reset(struct ahc_softc *ahc);
void ahc_free(struct ahc_softc *);
int ahc_probe_scbs(struct ahc_softc *);
+12 -1
View File
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aic7xxx.reg,v 1.12.2.1 1999/03/07 00:40:47 gibbs Exp $
* $Id: aic7xxx.reg,v 1.12.2.2 1999/03/08 22:44:36 gibbs Exp $
*/
/*
@@ -669,6 +669,16 @@ register DSPCISTATUS {
mask DFTHRSH_100 0xc0
}
/* aic7890/91/96/97 only */
register HS_MAILBOX {
address 0x086
mask HOST_MAILBOX 0xF0
mask SEQ_MAILBOX 0x0F
}
const HOST_MAILBOX_SHIFT 4
const SEQ_MAILBOX_SHIFT 0
/*
* Host Control (p. 3-47) R/W
* Overall host control of the device.
@@ -727,6 +737,7 @@ register INTSTAT {
mask NO_IDENT 0x20|SEQINT /* no IDENTIFY after reconnect*/
mask NO_MATCH 0x30|SEQINT /* no cmd match for reconnect */
mask ABORT_REQUESTED 0x50|SEQINT /* Reconect of aborted SCB */
mask UPDATE_TMSG_REQ 0x60|SEQINT /* Update TMSG_REQ values */
mask BAD_STATUS 0x70|SEQINT /* Bad status from target */
mask RESIDUAL 0x80|SEQINT /* Residual byte count != 0 */
mask TRACE_POINT 0x90|SEQINT
+13 -1
View File
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aic7xxx.seq,v 1.84.2.2 1999/03/07 00:40:47 gibbs Exp $
* $Id: aic7xxx.seq,v 1.84.2.3 1999/03/23 07:41:27 gibbs Exp $
*/
#include <dev/aic7xxx/aic7xxx.reg>
@@ -1025,6 +1025,18 @@ p_mesgout:
mov FUNCTION1, SCB_TCL;
mov A, FUNCTION1;
mov SINDEX, TARGET_MSG_REQUEST[0];
if ((ahc->features & AHC_HS_MAILBOX) != 0) {
/*
* Work around a pausing bug in at least the aic7890.
* If the host needs to update the TARGET_MSG_REQUEST
* bit field, it will set the HS_MAILBOX to 1. In
* response, we pause with a specific interrupt code
* asking for the mask to be updated before we continue.
* Ugh.
*/
test HS_MAILBOX, 0xF0 jz . + 2;
mvi INTSTAT, UPDATE_TMSG_REQ;
}
if ((ahc->features & AHC_TWIN) != 0) {
/* Second Channel uses high byte bits */
test SCB_TCL, SELBUSB jz . + 2;
+11 -9
View File
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aicasm_symbol.c,v 1.4 1997/09/27 19:37:30 gibbs Exp $
* $Id: aicasm_symbol.c,v 1.5 1998/09/15 07:24:17 gibbs Exp $
*/
@@ -128,10 +128,10 @@ symtable_close()
DBT data;
while (symtable->seq(symtable, &key, &data, R_FIRST) == 0) {
symbol_t *cursym;
symbol_t *stored_ptr;
cursym = *(symbol_t **)data.data;
symbol_delete(cursym);
memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
symbol_delete(stored_ptr);
}
symtable->close(symtable);
}
@@ -145,9 +145,10 @@ symbol_t *
symtable_get(name)
char *name;
{
DBT key;
DBT data;
int retval;
symbol_t *stored_ptr;
DBT key;
DBT data;
int retval;
key.data = (void *)name;
key.size = strlen(name);
@@ -176,7 +177,8 @@ symtable_get(name)
/* NOTREACHED */
}
}
return (*(symbol_t **)data.data);
memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
return (stored_ptr);
}
symbol_node_t *
@@ -327,7 +329,7 @@ symtable_dump(ofile)
while (symtable->seq(symtable, &key, &data, flag) == 0) {
symbol_t *cursym;
cursym = *(symbol_t **)data.data;
memcpy(&cursym, data.data, sizeof(cursym));
switch(cursym->type) {
case REGISTER:
case SCBLOC:
File diff suppressed because it is too large. Load diff
-296
View File
@@ -1,296 +0,0 @@
/*-
* Copyright (c) 1998, 1999 Scott Mitchell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: if_xereg.h,v 1.3 1999/02/22 14:00:53 root Exp $
*/
/*
* Register definitions for Xircom CreditCard Ethernet adapters. See if_xe.c
* for details of supported hardware. Adapted from Werner Koch's 'xirc2ps'
* driver for Linux and the FreeBSD 'xl' driver (for the MII support).
*/
#include "xe.h"
#if NXE > 0
/*
* Common registers
*/
#define XE_CR 0 /* Command register (write) */
#define XE_ESR 0 /* Ethernet status register (read) */
#define XE_PSR 1 /* Page select register */
#define XE_EDP 4 /* Ethernet data port */
#define XE_ISR 6 /* Interrupt status register */
/*
* Command register values
*/
#define XE_CR_TX_PACKET 0x01
#define XE_CR_SOFT_RESET 0x02
#define XE_CR_ENABLE_INTR 0x04
#define XE_CR_FORCE_INTR 0x08
#define XE_CR_CLEAR_FIFO 0x10
#define XE_CR_CLEAR_OVERRUN 0x20
#define XE_CR_RESTART_TX 0x40
/*
* Status register values
*/
#define XE_ESR_FULL_PKT_RX 0x01
#define XE_ESR_PKT_REJECT 0x04
#define XE_ESR_TX_PENDING 0x08
#define XE_ESR_BAD_POLARITY 0x10
#define XE_ESR_MEDIA_SELECT 0x20
/*
* Interrupt register values
*/
#define XE_ISR_TX_OVERFLOW 0x01
#define XE_ISR_TX_PACKET 0x02
#define XE_ISR_MAC_INTR 0x04
#define XE_ISR_TX_RES 0x08
#define XE_ISR_RX_PACKET 0x20
#define XE_ISR_RX_REJECT 0x40
#define XE_ISR_FORCE_INTR 0x80
/*
* Page 0 registers
*/
#define XE_TSO 8 /* Transmit space open */
#define XE_TRS 10 /* Transmit reservation size */
#define XE_DOR 12 /* Data offset register (write) */
#define XE_RSR 12 /* Receive status register (read) */
#define XE_PTR 13 /* Packets transmitted register (read) */
#define XE_RBC 14 /* Received byte count (read) */
/*
* RSR values
*/
#define XE_RSR_PHYS_PKT 0x01
#define XE_RSR_BCAST_PKT 0x02
#define XE_RSR_LONG_PKT 0x04
#define XE_RSR_ALIGN_ERR 0x10
#define XE_RSR_CRC_ERR 0x20
#define XE_RSR_RX_OK 0x80
/*
* Page 1 registers
*/
#define XE_IMR0 12 /* Interrupt mask register, part 1 */
#define XE_IMR1 13 /* Interrupt mask register, part 2 */
#define XE_ECR 14 /* Ethernet configuration register */
/*
* ECR values
*/
#define XE_ECR_FULL_DUPLEX 0x04
#define XE_ECR_LONG_TPCABLE 0x08
#define XE_ECR_NO_POLCOL 0x10
#define XE_ECR_NO_LINKPULSE 0x20
#define XE_ECR_NO_AUTOTX 0x40
/*
* Page 2 registers
*/
#define XE_RBS 8 /* Receive buffer start */
#define XE_LED 10 /* LED configuration register */
#define XE_MSR 12 /* Mohawk specfic register (Mohawk = CE3) */
#define XE_GPR2 13 /* General purpose register 2 */
/*
* Page 4 registers
*/
#define XE_GPR0 8 /* General purpose register 0 */
#define XE_GPR1 9 /* General purpose register 1 */
#define XE_BOV 10 /* Bonding version register */
#define XE_LMA 12 /* Local memory address */
#define XE_LMD 14 /* Local memory data */
/*
* Page 5 registers
*/
#define XE_RHS 10 /* Receive host start address */
/*
* Page 0x40 registers
*/
#define XE_OCR 8 /* The Other command register */
#define XE_RXS0 9 /* Receive status 0 */
#define XE_TXS0 11 /* Transmit status 0 */
#define XE_TXS1 12 /* Transmit status 1 */
#define XE_RXM0 13 /* Receive mask register 0 */
#define XE_TXM0 14 /* Transmit mask register 0 */
#define XE_TXM1 15 /* Transmit mask register 1 */
/*
* OCR values
*/
#define XE_OCR_TX 0x01
#define XE_OCR_RX_ENABLE 0x04
#define XE_OCR_RX_DISABLE 0x08
#define XE_OCR_ABORT 0x10
#define XE_OCR_ONLINE 0x20
#define XE_OCR_ACK_INTR 0x40
#define XE_OCR_OFFLINE 0x80
/*
* Page 0x42 registers
*/
#define XE_SWC0 8 /* Software configuration register 0 */
#define XE_SWC1 9 /* Software configuration register 1 */
#define XE_BOC 10 /* Back-off configuration */
/*
* Page 0x44 registers
*/
#define XE_TDR0 8 /* Time domain reflectometry register 0 */
#define XE_TDR1 9 /* Time domain reflectometry register 1 */
#define XE_RXC0 10 /* Receive byte count low */
#define XE_RXC1 11 /* Receive byte count high */
/*
* Page 0x45 registers
*/
#define XE_REV 15 /* Revision (read) */
/*
* Page 0x50 registers
*/
#define XE_IAR 8 /* Individual address register */
/*
* Pages 0x43, 0x46-0x4f and 0x51-0x5e apparently don't exist.
* The remainder of 0x0-0x8 and 0x40-0x5f exist, but I have no
* idea what's on most of them.
*/
/*
* Definitions for the Micro Linear ML6692 100Base-TX PHY, which handles the
* 100Mbit functionality of CE3 type cards, including media autonegotiation.
* It appears to be mostly compatible with the National Semiconductor
* DP83840A, but with a much smaller register set. Please refer to the data
* sheets for these devices for the definitive word on what all this stuff
* means :)
*
* Note that the ML6692 has no 10Mbit capability -- that is handled by another
* chip that we don't know anything about.
*
* Most of these definitions were adapted from the xl driver.
*/
/*
* Masks for the MII-related bits in GPR2. For some reason read and write
* data are on separate bits.
*/
#define XE_MII_CLK 0x01
#define XE_MII_DIR 0x08
#define XE_MII_WRD 0x02
#define XE_MII_RDD 0x20
/*
* MII command (etc) bit strings.
*/
#define XE_MII_STARTDELIM 0x01
#define XE_MII_READOP 0x02
#define XE_MII_WRITEOP 0x01
#define XE_MII_TURNAROUND 0x02
/*
* PHY registers.
*/
#define PHY_BMCR 0x00 /* Basic Mode Control Register */
#define PHY_BMSR 0x01 /* Basic Mode Status Register */
#define PHY_ANAR 0x04 /* Auto-Negotiation Advertisment Register */
#define PHY_LPAR 0x05 /* Auto-Negotiation Link Partner Ability Register */
#define PHY_ANER 0x06 /* Auto-Negotiation Expansion Register */
#define PHY_BMCR_RESET 0x8000 /* Soft reset PHY. Self-clearing */
#define PHY_BMCR_LOOPBK 0x4000 /* Enable loopback */
#define PHY_BMCR_SPEEDSEL 0x2000 /* 1=100Mbps, 0=10Mbps */
#define PHY_BMCR_AUTONEGENBL 0x1000 /* Auto-negotiation enabled */
#define PHY_BMCR_ISOLATE 0x0400 /* Isolate ML6692 from MII */
#define PHY_BMCR_AUTONEGRSTR 0x0200 /* Restart auto-negotiation. Self-clearing */
#define PHY_BMCR_DUPLEX 0x0100 /* Full duplex operation */
#define PHY_BMCR_COLLTEST 0x0080 /* Enable collision test */
#define PHY_BMSR_100BT4 0x8000 /* 100Base-T4 capable */
#define PHY_BMSR_100BTXFULL 0x4000 /* 100Base-TX full duplex capable */
#define PHY_BMSR_100BTXHALF 0x2000 /* 100Base-TX half duplex capable */
#define PHY_BMSR_10BTFULL 0x1000 /* 10Base-T full duplex capable */
#define PHY_BMSR_10BTHALF 0x0800 /* 10Base-T half duplex capable */
#define PHY_BMSR_AUTONEGCOMP 0x0020 /* Auto-negotiation complete */
#define PHY_BMSR_CANAUTONEG 0x0008 /* Auto-negotiation supported */
#define PHY_BMSR_LINKSTAT 0x0004 /* Link is up */
#define PHY_BMSR_EXTENDED 0x0001 /* Extended register capabilities */
#define PHY_ANAR_NEXTPAGE 0x8000 /* Additional link code word pages */
#define PHY_ANAR_TLRFLT 0x2000 /* Remote wire fault detected */
#define PHY_ANAR_100BT4 0x0200 /* 100Base-T4 capable */
#define PHY_ANAR_100BTXFULL 0x0100 /* 100Base-TX full duplex capable */
#define PHY_ANAR_100BTXHALF 0x0080 /* 100Base-TX half duplex capable */
#define PHY_ANAR_10BTFULL 0x0040 /* 10Base-T full duplex capable */
#define PHY_ANAR_10BTHALF 0x0020 /* 10Base-T half duplex capable */
#define PHY_ANAR_PROTO4 0x0010 /* Protocol selection (00001 = 802.3) */
#define PHY_ANAR_PROTO3 0x0008
#define PHY_ANAR_PROTO2 0x0004
#define PHY_ANAR_PROTO1 0x0002
#define PHY_ANAR_PROTO0 0x0001
#define PHY_LPAR_NEXTPAGE 0x8000 /* Additional link code word pages */
#define PHY_LPAR_LPACK 0x4000 /* Link partner acknowledged receipt */
#define PHY_LPAR_TLRFLT 0x2000 /* Remote wire fault detected */
#define PHY_LPAR_100BT4 0x0200 /* 100Base-T4 capable */
#define PHY_LPAR_100BTXFULL 0x0100 /* 100Base-TX full duplex capable */
#define PHY_LPAR_100BTXHALF 0x0080 /* 100Base-TX half duplex capable */
#define PHY_LPAR_10BTFULL 0x0040 /* 10Base-T full duplex capable */
#define PHY_LPAR_10BTHALF 0x0020 /* 10Base-T half duplex capable */
#define PHY_LPAR_PROTO4 0x0010 /* Protocol selection (00001 = 802.3) */
#define PHY_LPAR_PROTO3 0x0008
#define PHY_LPAR_PROTO2 0x0004
#define PHY_LPAR_PROTO1 0x0002
#define PHY_LPAR_PROTO0 0x0001
#define PHY_ANER_MLFAULT 0x0010 /* More than one link is up! */
#define PHY_ANER_LPNPABLE 0x0008 /* Link partner supports next page */
#define PHY_ANER_NPABLE 0x0004 /* Local port supports next page */
#define PHY_ANER_PAGERX 0x0002 /* Page received */
#define PHY_ANER_LPAUTONEG 0x0001 /* Link partner can auto-negotiate */
#endif /* NXE > 0 */
+21 -25
View File
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ahc_eisa.c,v 1.4 1998/12/15 08:24:45 gibbs Exp $
* $Id: ahc_eisa.c,v 1.4.2.1 1999/03/07 00:41:38 gibbs Exp $
*/
#include "eisa.h"
@@ -61,14 +61,14 @@
#define AHC_EISA_IOSIZE 0x100
#define INTDEF 0x5cul /* Interrupt Definition Register */
static int aic7770probe(void);
static int aic7770_attach(struct eisa_device *e_dev);
static int aic7770_probe(void);
static int aic7770_attach(struct eisa_device *e_dev);
static void aha2840_load_seeprom(struct ahc_softc *ahc);
static struct eisa_driver ahc_eisa_driver =
{
"ahc",
aic7770probe,
aic7770_probe,
aic7770_attach,
/*shutdown*/NULL,
&ahc_unit
@@ -79,8 +79,7 @@ DATA_SET (eisadriver_set, ahc_eisa_driver);
static const char *aic7770_match(eisa_id_t type);
static const char*
aic7770_match(type)
eisa_id_t type;
aic7770_match(eisa_id_t type)
{
switch (type) {
case EISA_DEVICE_ID_ADAPTEC_AIC7770:
@@ -100,20 +99,20 @@ aic7770_match(type)
}
static int
aic7770probe(void)
aic7770_probe()
{
u_int32_t iobase;
u_int32_t irq;
u_int8_t intdef;
u_int8_t hcntrl;
struct eisa_device *e_dev;
int count;
int count;
e_dev = NULL;
count = 0;
while ((e_dev = eisa_match_dev(e_dev, aic7770_match))) {
iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE)
+ AHC_EISA_SLOT_OFFSET;
+ AHC_EISA_SLOT_OFFSET;
/* Pause the card preseving the IRQ type */
hcntrl = inb(iobase + HCNTRL) & IRQMS;
@@ -124,7 +123,7 @@ aic7770probe(void)
intdef = inb(INTDEF + iobase);
irq = intdef & 0xf;
switch (irq) {
case 9:
case 9:
case 10:
case 11:
case 12:
@@ -134,7 +133,7 @@ aic7770probe(void)
default:
printf("aic7770 at slot %d: illegal "
"irq setting %d\n", e_dev->ioconf.slot,
intdef);
intdef);
irq = 0;
break;
}
@@ -151,7 +150,7 @@ static int
aic7770_attach(struct eisa_device *e_dev)
{
ahc_chip chip;
bus_dma_tag_t parent_dmat;
struct ahc_softc *ahc;
resvaddr_t *iospace;
int unit = e_dev->unit;
@@ -180,15 +179,8 @@ aic7770_attach(struct eisa_device *e_dev)
default:
printf("aic7770_attach: Unknown device type!\n");
return -1;
break;
}
if (!(ahc = ahc_alloc(unit, iospace->addr, NULL,
chip, AHC_AIC7770_FE, AHC_FNONE, NULL)))
return -1;
ahc->channel = 'A';
ahc->channel_b = 'B';
/* XXX Should be a child of the EISA bus dma tag */
error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/0,
/*boundary*/0,
@@ -198,15 +190,20 @@ aic7770_attach(struct eisa_device *e_dev)
/*maxsize*/MAXBSIZE,
/*nsegments*/AHC_NSEG,
/*maxsegsz*/AHC_MAXTRANSFER_SIZE,
/*flags*/BUS_DMA_ALLOCNOW, &ahc->dmat);
/*flags*/BUS_DMA_ALLOCNOW, &parent_dmat);
if (error != 0) {
printf("%s: Could not allocate DMA tag - error %d\n",
ahc_name(ahc), error);
ahc_free(ahc);
printf("ahc_eisa_attach: Could not allocate DMA tag "
"- error %d\n", error);
return -1;
}
if (!(ahc = ahc_alloc(unit, iospace->addr, NULL, parent_dmat,
chip, AHC_AIC7770_FE, AHC_FNONE, NULL)))
return -1;
ahc->channel = 'A';
ahc->channel_b = 'B';
eisa_reg_start(e_dev);
if (eisa_reg_iospace(e_dev, iospace)) {
@@ -224,7 +221,7 @@ aic7770_attach(struct eisa_device *e_dev)
* IRQ sharing if it's set.
*/
if (eisa_reg_intr(e_dev, irq, ahc_intr, (void *)ahc, &cam_imask,
/*shared ==*/ahc->pause & IRQMS)) {
/*shared ==*/ahc->pause & IRQMS)) {
ahc_free(ahc);
return -1;
}
@@ -473,5 +470,4 @@ aha2840_load_seeprom(struct ahc_softc *ahc)
ahc->flags |= AHC_TERM_ENB_A;
}
}
#endif /* NEISA > 0 */
-281
View File
@@ -1,281 +0,0 @@
/*
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: if_wavelan_ieee.h,v 1.4 1999/04/27 02:02:41 wpaul Exp $
*/
#ifndef _IF_WAVELAN_IEEE_H
#define _IF_WAVELAN_IEEE_H
/*
* This header defines a simple command interface to the FreeBSD
* WaveLAN/IEEE driver (wi) driver, which is used to set certain
* device-specific parameters which can't be easily managed through
* ifconfig(8). No, sysctl(2) is not the answer. I said a _simple_
* interface, didn't I.
*/
#ifndef SIOCSWAVELAN
#define SIOCSWAVELAN SIOCSIFGENERIC
#endif
#ifndef SIOCGWAVELAN
#define SIOCGWAVELAN SIOCGIFGENERIC
#endif
/*
* Technically I don't think there's a limit to a record
* length. The largest record is the one that contains the CIS
* data, which is 240 words long, so 256 should be a safe
* value.
*/
#define WI_MAX_DATALEN 512
struct wi_req {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_val[WI_MAX_DATALEN];
};
/*
* Private LTV records (interpreted only by the driver). This is
* a minor kludge to allow reading the interface statistics from
* the driver.
*/
#define WI_RID_IFACE_STATS 0x0100
#define WI_RID_MGMT_XMIT 0x0200
struct wi_80211_hdr {
u_int16_t frame_ctl;
u_int16_t dur_id;
u_int8_t addr1[6];
u_int8_t addr2[6];
u_int8_t addr3[6];
u_int16_t seq_ctl;
u_int8_t addr4[6];
};
#define WI_FCTL_VERS 0x0002
#define WI_FCTL_FTYPE 0x000C
#define WI_FCTL_STYPE 0x00F0
#define WI_FCTL_TODS 0x0100
#define WI_FCTL_FROMDS 0x0200
#define WI_FCTL_MOREFRAGS 0x0400
#define WI_FCTL_RETRY 0x0800
#define WI_FCTL_PM 0x1000
#define WI_FCTL_MOREDATA 0x2000
#define WI_FCTL_WEP 0x4000
#define WI_FCTL_ORDER 0x8000
#define WI_FTYPE_MGMT 0x0000
#define WI_FTYPE_CTL 0x0004
#define WI_FTYPE_DATA 0x0008
#define WI_STYPE_MGMT_ASREQ 0x0000 /* association request */
#define WI_STYPE_MGMT_ASRESP 0x0010 /* association response */
#define WI_STYPE_MGMT_REASREQ 0x0020 /* reassociation request */
#define WI_STYPE_MGMT_REASRESP 0x0030 /* reassociation response */
#define WI_STYPE_MGMT_PROBEREQ 0x0040 /* probe request */
#define WI_STYPE_MGMT_PROBERESP 0x0050 /* probe response */
#define WI_STYPE_MGMT_BEACON 0x0080 /* beacon */
#define WI_STYPE_MGMT_ATIM 0x0090 /* announcement traffic ind msg */
#define WI_STYPE_MGMT_DISAS 0x00A0 /* disassociation */
#define WI_STYPE_MGMT_AUTH 0x00B0 /* authentication */
#define WI_STYPE_MGMT_DEAUTH 0x00C0 /* deauthentication */
struct wi_mgmt_hdr {
u_int16_t frame_ctl;
u_int16_t duration;
u_int8_t dst_addr[6];
u_int8_t src_addr[6];
u_int8_t bssid[6];
u_int16_t seq_ctl;
};
#ifndef KERNEL
struct wi_counters {
u_int32_t wi_tx_unicast_frames;
u_int32_t wi_tx_multicast_frames;
u_int32_t wi_tx_fragments;
u_int32_t wi_tx_unicast_octets;
u_int32_t wi_tx_multicast_octets;
u_int32_t wi_tx_deferred_xmits;
u_int32_t wi_tx_single_retries;
u_int32_t wi_tx_multi_retries;
u_int32_t wi_tx_retry_limit;
u_int32_t wi_tx_discards;
u_int32_t wi_rx_unicast_frames;
u_int32_t wi_rx_multicast_frames;
u_int32_t wi_rx_fragments;
u_int32_t wi_rx_unicast_octets;
u_int32_t wi_rx_multicast_octets;
u_int32_t wi_rx_fcs_errors;
u_int32_t wi_rx_discards_nobuf;
u_int32_t wi_tx_discards_wrong_sa;
u_int32_t wi_rx_WEP_cant_decrypt;
u_int32_t wi_rx_msg_in_msg_frags;
u_int32_t wi_rx_msg_in_bad_msg_frags;
};
/*
* These are all the LTV record types that we can read or write
* from the WaveLAN. Not all of them are temendously useful, but I
* list as many as I know about here for completeness.
*/
#define WI_RID_DNLD_BUF 0xFD01
#define WI_RID_MEMSZ 0xFD02
#define WI_RID_DOMAINS 0xFD11
#define WI_RID_CIS 0xFD13
#define WI_RID_COMMQUAL 0xFD43
#define WI_RID_SCALETHRESH 0xFD46
#define WI_RID_PCF 0xFD87
/*
* Network parameters, static configuration entities.
*/
#define WI_RID_PORTTYPE 0xFC00 /* Connection control characteristics */
#define WI_RID_MAC_NODE 0xFC01 /* MAC address of this station */
#define WI_RID_DESIRED_SSID 0xFC02 /* Service Set ID for connection */
#define WI_RID_OWN_CHNL 0xFC03 /* Comm channel for BSS creation */
#define WI_RID_OWN_SSID 0xFC04 /* IBSS creation ID */
#define WI_RID_OWN_ATIM_WIN 0xFC05 /* ATIM window time for IBSS creation */
#define WI_RID_SYSTEM_SCALE 0xFC06 /* scale that specifies AP density */
#define WI_RID_MAX_DATALEN 0xFC07 /* Max len of MAC frame body data */
#define WI_RID_MAC_WDS 0xFC08 /* MAC addr of corresponding WDS node */
#define WI_RID_PM_ENABLED 0xFC09 /* ESS power management enable */
#define WI_RID_PM_EPS 0xFC0A /* PM EPS/PS mode */
#define WI_RID_MCAST_RX 0xFC0B /* ESS PM mcast reception */
#define WI_RID_MAX_SLEEP 0xFC0C /* max sleep time for ESS PM */
#define WI_RID_HOLDOVER 0xFC0D /* holdover time for ESS PM */
#define WI_RID_NODENAME 0xFC0E /* ID name of this node for diag */
#define WI_RID_DTIM_PERIOD 0xFC10 /* beacon interval between DTIMs */
#define WI_RID_WDS_ADDR1 0xFC11 /* port 1 MAC of WDS link node */
#define WI_RID_WDS_ADDR2 0xFC12 /* port 1 MAC of WDS link node */
#define WI_RID_WDS_ADDR3 0xFC13 /* port 1 MAC of WDS link node */
#define WI_RID_WDS_ADDR4 0xFC14 /* port 1 MAC of WDS link node */
#define WI_RID_WDS_ADDR5 0xFC15 /* port 1 MAC of WDS link node */
#define WI_RID_WDS_ADDR6 0xFC16 /* port 1 MAC of WDS link node */
#define WI_RID_MCAST_PM_BUF 0xFC17 /* PM buffering of mcast */
/*
* Network parameters, dynamic configuration entities
*/
#define WI_RID_MCAST_LIST 0xFC80 /* list of multicast addrs */
#define WI_RID_CREATE_IBSS 0xFC81 /* create IBSS */
#define WI_RID_FRAG_THRESH 0xFC82 /* frag len, unicast msg xmit */
#define WI_RID_RTS_THRESH 0xFC83 /* frame len for RTS/CTS handshake */
#define WI_RID_TX_RATE 0xFC84 /* data rate for message xmit */
#define WI_RID_PROMISC 0xFC85 /* enable promisc mode */
#define WI_RID_FRAG_THRESH0 0xFC90
#define WI_RID_FRAG_THRESH1 0xFC91
#define WI_RID_FRAG_THRESH2 0xFC92
#define WI_RID_FRAG_THRESH3 0xFC93
#define WI_RID_FRAG_THRESH4 0xFC94
#define WI_RID_FRAG_THRESH5 0xFC95
#define WI_RID_FRAG_THRESH6 0xFC96
#define WI_RID_RTS_THRESH0 0xFC97
#define WI_RID_RTS_THRESH1 0xFC98
#define WI_RID_RTS_THRESH2 0xFC99
#define WI_RID_RTS_THRESH3 0xFC9A
#define WI_RID_RTS_THRESH4 0xFC9B
#define WI_RID_RTS_THRESH5 0xFC9C
#define WI_RID_RTS_THRESH6 0xFC9D
#define WI_RID_TX_RATE0 0xFC9E
#define WI_RID_TX_RATE1 0xFC9F
#define WI_RID_TX_RATE2 0xFCA0
#define WI_RID_TX_RATE3 0xFCA1
#define WI_RID_TX_RATE4 0xFCA2
#define WI_RID_TX_RATE5 0xFCA3
#define WI_RID_TX_RATE6 0xFCA4
#define WI_RID_TICK_TIME 0xFCE0
/*
* NIC information
*/
#define WI_RID_FIRM_ID 0xFD02 /* Primary func firmware ID. */
#define WI_RID_PRI_SUP_RANGE 0xFD03 /* primary supplier compatibility */
#define WI_RID_CIF_ACT_RANGE 0xFD04 /* controller sup. compatibility */
#define WI_RID_SERIALNO 0xFD0A /* card serial number */
#define WI_RID_CARD_ID 0xFD0B /* card identification */
#define WI_RID_MFI_SUP_RANGE 0xFD0C /* modem supplier compatibility */
#define WI_RID_CFI_SUP_RANGE 0xFD0D /* controller sup. compatibility */
#define WI_RID_CHANNEL_LIST 0xFD10 /* allowd comm. frequencies. */
#define WI_RID_REG_DOMAINS 0xFD11 /* list of intendted regulatory doms */
#define WI_RID_TEMP_TYPE 0xFD12 /* hw temp range code */
#define WI_RID_CIS 0xFD13 /* PC card info struct */
#define WI_RID_STA_IDENEITY 0xFD20 /* station funcs firmware ident */
#define WI_RID_STA_SUP_RANGE 0xFD21 /* station supplier compat */
#define WI_RID_MFI_ACT_RANGE 0xFD22
#define WI_RID_CFI_ACT_RANGE 0xFD33
/*
* MAC information
*/
#define WI_RID_PORT_STAT 0xFD40 /* actual MAC port con control stat */
#define WI_RID_CURRENT_SSID 0xFD41 /* ID of actually connected SS */
#define WI_RID_CURRENT_BSSID 0xFD42 /* ID of actually connected BSS */
#define WI_RID_COMMS_QUALITY 0xFD43 /* quality of BSS connection */
#define WI_RID_CUR_TX_RATE 0xFD44 /* current TX rate */
#define WI_RID_OWN_BEACON_INT 0xFD45 /* beacon xmit time for BSS creation */
#define WI_RID_CUR_SCALE_THRESH 0xFD46 /* actual system scane thresh setting */
#define WI_RID_PROT_RESP_TIME 0xFD47 /* time to wait for resp to req msg */
#define WI_RID_SHORT_RTR_LIM 0xFD48 /* max tx attempts for short frames */
#define WI_RID_LONG_RTS_LIM 0xFD49 /* max tx attempts for long frames */
#define WI_RID_MAX_TX_LIFE 0xFD4A /* max tx frame handling duration */
#define WI_RID_MAX_RX_LIFE 0xFD4B /* max rx frame handling duration */
#define WI_RID_CF_POLL 0xFD4C /* contention free pollable ind */
#define WI_RID_AUTH_ALGS 0xFD4D /* auth algorithms available */
#define WI_RID_AUTH_TYPE 0xFD4E /* availanle auth types */
#define WI_RID_WEP_AVAIL 0xFD4F /* WEP privacy option available */
#define WI_RID_CUR_TX_RATE1 0xFD80
#define WI_RID_CUR_TX_RATE2 0xFD81
#define WI_RID_CUR_TX_RATE3 0xFD82
#define WI_RID_CUR_TX_RATE4 0xFD83
#define WI_RID_CUR_TX_RATE5 0xFD84
#define WI_RID_CUR_TX_RATE6 0xFD85
#define WI_RID_OWN_MAC 0xFD86 /* unique local MAC addr */
#define WI_RID_PCI_INFO 0xFD87 /* point coordination func cap */
/*
* Modem information
*/
#define WI_RID_PHY_TYPE 0xFDC0 /* phys layer type indication */
#define WI_RID_CURRENT_CHAN 0xFDC1 /* current frequency */
#define WI_RID_PWR_STATE 0xFDC2 /* pwr consumption status */
#define WI_RID_CCA_MODE 0xFDC3 /* clear chan assess mode indication */
#define WI_RID_CCA_TIME 0xFDC4 /* clear chan assess time */
#define WI_RID_MAC_PROC_DELAY 0xFDC5 /* MAC processing delay time */
#define WI_RID_DATA_RATES 0xFDC6 /* supported data rates */
#endif
#endif
-599
View File
@@ -1,599 +0,0 @@
/*
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: if_wireg.h,v 1.31 1999/05/07 03:14:21 wpaul Exp $
*/
struct wi_counters {
u_int32_t wi_tx_unicast_frames;
u_int32_t wi_tx_multicast_frames;
u_int32_t wi_tx_fragments;
u_int32_t wi_tx_unicast_octets;
u_int32_t wi_tx_multicast_octets;
u_int32_t wi_tx_deferred_xmits;
u_int32_t wi_tx_single_retries;
u_int32_t wi_tx_multi_retries;
u_int32_t wi_tx_retry_limit;
u_int32_t wi_tx_discards;
u_int32_t wi_rx_unicast_frames;
u_int32_t wi_rx_multicast_frames;
u_int32_t wi_rx_fragments;
u_int32_t wi_rx_unicast_octets;
u_int32_t wi_rx_multicast_octets;
u_int32_t wi_rx_fcs_errors;
u_int32_t wi_rx_discards_nobuf;
u_int32_t wi_tx_discards_wrong_sa;
u_int32_t wi_rx_WEP_cant_decrypt;
u_int32_t wi_rx_msg_in_msg_frags;
u_int32_t wi_rx_msg_in_bad_msg_frags;
};
struct wi_softc {
struct arpcom arpcom;
struct ifmedia ifmedia;
int wi_unit;
bus_space_handle_t wi_bhandle;
bus_space_tag_t wi_btag;
int wi_tx_data_id;
int wi_tx_mgmt_id;
int wi_gone;
int wi_if_flags;
u_int16_t wi_ptype;
u_int16_t wi_portnum;
u_int16_t wi_max_data_len;
u_int16_t wi_rts_thresh;
u_int16_t wi_ap_density;
u_int16_t wi_tx_rate;
u_int16_t wi_create_ibss;
u_int16_t wi_channel;
u_int16_t wi_pm_enabled;
u_int16_t wi_max_sleep;
char wi_node_name[32];
char wi_net_name[32];
char wi_ibss_name[32];
u_int8_t wi_txbuf[1536];
struct wi_counters wi_stats;
struct callout_handle wi_stat_ch;
};
#define WI_TIMEOUT 65536
#define WI_PORT0 0
#define WI_PORT1 1
#define WI_PORT2 2
#define WI_PORT3 3
#define WI_PORT4 4
#define WI_PORT5 5
/* Default port: 0 (only 0 exists on stations) */
#define WI_DEFAULT_PORT (WI_PORT0 << 8)
/* Default TX rate: 2Mbps, auto fallback */
#define WI_DEFAULT_TX_RATE 3
/* Default network name: ANY */
#define WI_DEFAULT_NETNAME "ANY"
#define WI_DEFAULT_AP_DENSITY 1
#define WI_DEFAULT_RTS_THRESH 2347
#define WI_DEFAULT_DATALEN 2304
#define WI_DEFAULT_CREATE_IBSS 0
#define WI_DEFAULT_PM_ENABLED 0
#define WI_DEFAULT_MAX_SLEEP 100
#define WI_DEFAULT_NODENAME "FreeBSD WaveLAN/IEEE node"
#define WI_DEFAULT_IBSS "FreeBSD IBSS"
#define WI_DEFAULT_CHAN 3
/*
* register space access macros
*/
#define CSR_WRITE_4(sc, reg, val) \
bus_space_write_4(sc->wi_btag, sc->wi_bhandle, reg, val)
#define CSR_WRITE_2(sc, reg, val) \
bus_space_write_2(sc->wi_btag, sc->wi_bhandle, reg, val)
#define CSR_WRITE_1(sc, reg, val) \
bus_space_write_1(sc->wi_btag, sc->wi_bhandle, reg, val)
#define CSR_READ_4(sc, reg) \
bus_space_read_4(sc->wi_btag, sc->wi_bhandle, reg)
#define CSR_READ_2(sc, reg) \
bus_space_read_2(sc->wi_btag, sc->wi_bhandle, reg)
#define CSR_READ_1(sc, reg) \
bus_space_read_1(sc->wi_btag, sc->wi_bhandle, reg)
/*
* The WaveLAN/IEEE cards contain an 802.11 MAC controller which Lucent
* calls 'Hermes.' In typical fashion, getting documentation about this
* controller is about as easy as squeezing blood from a stone. Here
* is more or less what I know:
*
* - The Hermes controller is firmware driven, and the host interacts
* with the Hermes via a firmware interface, which can change.
*
* - The Hermes is described in a document called: "Hermes Firmware
* WaveLAN/IEEE Station Functions," document #010245, which of course
* Lucent will not release without an NDA.
*
* - Lucent has created a library called HCF (Hardware Control Functions)
* though which it wants developers to interact with the card. The HCF
* is needlessly complex, ill conceived and badly documented. Actually,
* the comments in the HCP code itself aren't bad, but the publically
* available manual that comes with it is awful, probably due largely to
* the fact that it has been emasculated in order to hide information
* that Lucent wants to keep proprietary. The purpose of the HCF seems
* to be to insulate the driver programmer from the Hermes itself so that
* Lucent has an excuse not to release programming in for it.
*
* - Lucent only makes available documentation and code for 'HCF Light'
* which is a stripped down version of HCF with certain features not
* implemented, most notably support for 802.11 frames.
*
* - The HCF code which I have seen blows goats. Whoever decided to
* use a 132 column format should be shot.
*
* Rather than actually use the Lucent HCF library, I have stripped all
* the useful information from it and used it to create a driver in the
* usual BSD form. Note: I don't want to hear anybody whining about the
* fact that the Lucent code is GPLed and mine isn't. I did not actually
* put any of Lucent's code in this driver: I only used it as a reference
* to obtain information about the underlying hardware. The Hermes
* programming interface is not GPLed, so bite me.
*/
/*
* Size of Hermes I/O space.
*/
#define WI_IOSIZ 0x40
/*
* Hermes register definitions and what little I know about them.
*/
/* Hermes command/status registers. */
#define WI_COMMAND 0x00
#define WI_PARAM0 0x02
#define WI_PARAM1 0x04
#define WI_PARAM2 0x06
#define WI_STATUS 0x08
#define WI_RESP0 0x0A
#define WI_RESP1 0x0C
#define WI_RESP2 0x0E
/* Command register values. */
#define WI_CMD_BUSY 0x8000 /* busy bit */
#define WI_CMD_INI 0x0000 /* initialize */
#define WI_CMD_ENABLE 0x0001 /* enable */
#define WI_CMD_DISABLE 0x0002 /* disable */
#define WI_CMD_DIAG 0x0003
#define WI_CMD_ALLOC_MEM 0x000A /* allocate NIC memory */
#define WI_CMD_TX 0x000B /* transmit */
#define WI_CMD_NOTIFY 0x0010
#define WI_CMD_INQUIRE 0x0011
#define WI_CMD_ACCESS 0x0021
#define WI_CMD_PROGRAM 0x0022
#define WI_CMD_CODE_MASK 0x003F
/*
* Reclaim qualifier bit, applicable to the
* TX and INQUIRE commands.
*/
#define WI_RECLAIM 0x0100 /* reclaim NIC memory */
/*
* ACCESS command qualifier bits.
*/
#define WI_ACCESS_READ 0x0000
#define WI_ACCESS_WRITE 0x0100
/*
* PROGRAM command qualifier bits.
*/
#define WI_PROGRAM_DISABLE 0x0000
#define WI_PROGRAM_ENABLE_RAM 0x0100
#define WI_PROGRAM_ENABLE_NVRAM 0x0200
#define WI_PROGRAM_NVRAM 0x0300
/* Status register values */
#define WI_STAT_CMD_CODE 0x003F
#define WI_STAT_DIAG_ERR 0x0100
#define WI_STAT_INQ_ERR 0x0500
#define WI_STAT_CMD_RESULT 0x7F00
/* memory handle management registers */
#define WI_INFO_FID 0x10
#define WI_RX_FID 0x20
#define WI_ALLOC_FID 0x22
#define WI_TX_CMP_FID 0x24
/*
* Buffer Access Path (BAP) registers.
* These are I/O channels. I believe you can use each one for
* any desired purpose independently of the other. In general
* though, we use BAP1 for reading and writing LTV records and
* reading received data frames, and BAP0 for writing transmit
* frames. This is a convention though, not a rule.
*/
#define WI_SEL0 0x18
#define WI_SEL1 0x1A
#define WI_OFF0 0x1C
#define WI_OFF1 0x1E
#define WI_DATA0 0x36
#define WI_DATA1 0x38
#define WI_BAP0 WI_DATA0
#define WI_BAP1 WI_DATA1
#define WI_OFF_BUSY 0x8000
#define WI_OFF_ERR 0x4000
#define WI_OFF_DATAOFF 0x0FFF
/* Event registers */
#define WI_EVENT_STAT 0x30 /* Event status */
#define WI_INT_EN 0x32 /* Interrupt enable/disable */
#define WI_EVENT_ACK 0x34 /* Ack event */
/* Events */
#define WI_EV_TICK 0x8000 /* aux timer tick */
#define WI_EV_RES 0x4000 /* controller h/w error (time out) */
#define WI_EV_INFO_DROP 0x2000 /* no RAM to build unsolicited frame */
#define WI_EV_NO_CARD 0x0800 /* card removed (hunh?) */
#define WI_EV_DUIF_RX 0x0400 /* wavelan management packet received */
#define WI_EV_INFO 0x0080 /* async info frame */
#define WI_EV_CMD 0x0010 /* command completed */
#define WI_EV_ALLOC 0x0008 /* async alloc/reclaim completed */
#define WI_EV_TX_EXC 0x0004 /* async xmit completed with failure */
#define WI_EV_TX 0x0002 /* async xmit completed succesfully */
#define WI_EV_RX 0x0001 /* async rx completed */
#define WI_INTRS \
(WI_EV_RX|WI_EV_TX|WI_EV_TX_EXC|WI_EV_ALLOC|WI_EV_INFO|WI_EV_INFO_DROP)
/* Host software registers */
#define WI_SW0 0x28
#define WI_SW1 0x2A
#define WI_SW2 0x2C
#define WI_SW3 0x2E
#define WI_CNTL 0x14
#define WI_CNTL_AUX_ENA 0xC000
#define WI_CNTL_AUX_ENA_STAT 0xC000
#define WI_CNTL_AUX_DIS_STAT 0x0000
#define WI_CNTL_AUX_ENA_CNTL 0x8000
#define WI_CNTL_AUX_DIS_CNTL 0x4000
#define WI_AUX_PAGE 0x3A
#define WI_AUX_OFFSET 0x3C
#define WI_AUX_DATA 0x3E
/*
* One form of communication with the Hermes is with what Lucent calls
* LTV records, where LTV stands for Length, Type and Value. The length
* and type are 16 bits and are in native byte order. The value is in
* multiples of 16 bits and is in little endian byte order.
*/
struct wi_ltv_gen {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_val;
};
struct wi_ltv_str {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_str[17];
};
#define WI_SETVAL(recno, val) \
do { \
struct wi_ltv_gen g; \
\
g.wi_len = 2; \
g.wi_type = recno; \
g.wi_val = val; \
wi_write_record(sc, &g); \
} while (0)
#define WI_SETSTR(recno, str) \
do { \
struct wi_ltv_str s; \
int l; \
\
l = (strlen(str) + 1) & ~0x1; \
bzero((char *)&s, sizeof(s)); \
s.wi_len = (l / 2) + 2; \
s.wi_type = recno; \
s.wi_str[0] = strlen(str); \
bcopy(str, (char *)&s.wi_str[1], strlen(str)); \
wi_write_record(sc, (struct wi_ltv_gen *)&s); \
} while (0)
/*
* Download buffer location and length (0xFD01).
*/
#define WI_RID_DNLD_BUF 0xFD01
struct wi_ltv_dnld_buf {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_buf_pg; /* page addr of intermediate dl buf*/
u_int16_t wi_buf_off; /* offset of idb */
u_int16_t wi_buf_len; /* len of idb */
};
/*
* Mem sizes (0xFD02).
*/
#define WI_RID_MEMSZ 0xFD02
struct wi_ltv_memsz {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_mem_ram;
u_int16_t wi_mem_nvram;
};
/*
* List of intended regulatory domains (0xFD11).
*/
#define WI_RID_DOMAINS 0xFD11
struct wi_ltv_domains {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_domains[6];
};
/*
* CIS struct (0xFD13).
*/
#define WI_RID_CIS 0xFD13
struct wi_ltv_cis {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_cis[240];
};
/*
* Communications quality (0xFD43).
*/
#define WI_RID_COMMQUAL 0xFD43
struct wi_ltv_commqual {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_coms_qual;
u_int16_t wi_sig_lvl;
u_int16_t wi_noise_lvl;
};
/*
* Actual system scale thresholds (0xFD46).
*/
#define WI_RID_SYSTEM_SCALE 0xFC06
#define WI_RID_SCALETHRESH 0xFD46
struct wi_ltv_scalethresh {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_energy_detect;
u_int16_t wi_carrier_detect;
u_int16_t wi_defer;
u_int16_t wi_cell_search;
u_int16_t wi_out_of_range;
u_int16_t wi_delta_snr;
};
/*
* PCF info struct (0xFD87).
*/
#define WI_RID_PCF 0xFD87
struct wi_ltv_pcf {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_energy_detect;
u_int16_t wi_carrier_detect;
u_int16_t wi_defer;
u_int16_t wi_cell_search;
u_int16_t wi_range;
};
/*
* Connection control characteristics.
* 1 == Basic Service Set (BSS)
* 2 == Wireless Distribudion System (WDS)
* 3 == Pseudo IBSS
*/
#define WI_RID_PORTTYPE 0xFC00
#define WI_PORTTYPE_BSS 0x1
#define WI_PORTTYPE_WDS 0x2
#define WI_PORTTYPE_ADHOC 0x3
/*
* Mac addresses.
*/
#define WI_RID_MAC_NODE 0xFC01
#define WI_RID_MAC_WDS 0xFC08
struct wi_ltv_macaddr {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_mac_addr[3];
};
/*
* Station set identification (SSID).
*/
#define WI_RID_DESIRED_SSID 0xFC02
#define WI_RID_OWN_SSID 0xFC04
struct wi_ltv_ssid {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_id[17];
};
/*
* Set communications channel (radio frequency).
*/
#define WI_RID_OWN_CHNL 0xFC03
/*
* Frame data size.
*/
#define WI_RID_MAX_DATALEN 0xFC07
/*
* ESS power management enable
*/
#define WI_RID_PM_ENABLED 0xFC09
/*
* ESS max PM sleep internal
*/
#define WI_RID_MAX_SLEEP 0xFC0C
/*
* Set our station name.
*/
#define WI_RID_NODENAME 0xFC0E
struct wi_ltv_nodename {
u_int16_t wi_len;
u_int16_t wi_type;
u_int16_t wi_nodename[17];
};
/*
* Multicast addresses to be put in filter. We're
* allowed up to 16 addresses in the filter.
*/
#define WI_RID_MCAST 0xFC80
struct wi_ltv_mcast {
u_int16_t wi_len;
u_int16_t wi_type;
struct ether_addr wi_mcast[16];
};
/*
* Create IBSS.
*/
#define WI_RID_CREATE_IBSS 0xFC81
#define WI_RID_FRAG_THRESH 0xFC82
#define WI_RID_RTS_THRESH 0xFC83
/*
* TX rate control
* 0 == Fixed 1mbps
* 1 == Fixed 2mbps
* 2 == auto fallback
*/
#define WI_RID_TX_RATE 0xFC84
/*
* promiscuous mode.
*/
#define WI_RID_PROMISC 0xFC85
/*
* Auxiliary Timer tick interval
*/
#define WI_RID_TICK_TIME 0xFCE0
/*
* Information frame types.
*/
#define WI_INFO_NOTIFY 0xF000 /* Handover address */
#define WI_INFO_COUNTERS 0xF100 /* Statistics counters */
#define WI_INFO_SCAN_RESULTS 0xF101 /* Scan results */
#define WI_INFO_LINK_STAT 0xF200 /* Link status */
#define WI_INFO_ASSOC_STAT 0xF201 /* Association status */
/*
* Hermes transmit/receive frame structure
*/
struct wi_frame {
u_int16_t wi_status; /* 0x00 */
u_int32_t wi_rsvd0; /* 0x02 */
u_int16_t wi_q_info; /* 0x06 */
u_int16_t wi_rsvd1; /* 0x08 */
u_int16_t wi_tx_ctl; /* 0x0C */
u_int16_t wi_frame_ctl; /* 0x0E */
u_int16_t wi_id; /* 0x10 */
u_int8_t wi_addr1[6]; /* 0x12 */
u_int8_t wi_addr2[6]; /* 0x18 */
u_int8_t wi_addr3[6]; /* 0x1E */
u_int16_t wi_seq_ctl; /* 0x24 */
u_int8_t wi_addr4[6]; /* 0x26 */
u_int16_t wi_dat_len; /* 0x2C */
u_int8_t wi_dst_addr[6]; /* 0x2E */
u_int8_t wi_src_addr[6]; /* 0x34 */
u_int16_t wi_len; /* 0x3A */
u_int16_t wi_dat[3]; /* 0x3C */ /* SNAP header */
u_int16_t wi_type; /* 0x42 */
};
#define WI_802_3_OFFSET 0x2E
#define WI_802_11_OFFSET 0x44
#define WI_802_11_OFFSET_RAW 0x3C
#define WI_STAT_BADCRC 0x0001
#define WI_STAT_UNDECRYPTABLE 0x0002
#define WI_STAT_ERRSTAT 0x0003
#define WI_STAT_MAC_PORT 0x0700
#define WI_STAT_1042 0x2000 /* RFC1042 encoded */
#define WI_STAT_TUNNEL 0x4000 /* Bridge-tunnel encoded */
#define WI_STAT_WMP_MSG 0x6000 /* WaveLAN-II management protocol */
#define WI_RXSTAT_MSG_TYPE 0xE000
#define WI_ENC_TX_802_3 0x00
#define WI_ENC_TX_802_11 0x11
#define WI_ENC_TX_E_II 0x0E
#define WI_ENC_TX_1042 0x00
#define WI_ENC_TX_TUNNEL 0xF8
#define WI_TXCNTL_MACPORT 0x00FF
#define WI_TXCNTL_STRUCTTYPE 0xFF00
/*
* SNAP (sub-network access protocol) constants for transmission
* of IP datagrams over IEEE 802 networks, taken from RFC1042.
* We need these for the LLC/SNAP header fields in the TX/RX frame
* structure.
*/
#define WI_SNAP_K1 0xaa /* assigned global SAP for SNAP */
#define WI_SNAP_K2 0x00
#define WI_SNAP_CONTROL 0x03 /* unnumbered information format */
#define WI_SNAP_WORD0 (WI_SNAP_K1 | (WI_SNAP_K1 << 8))
#define WI_SNAP_WORD1 (WI_SNAP_K2 | (WI_SNAP_CONTROL << 8))
#define WI_SNAPHDR_LEN 0x6
-4
View File
@@ -1,4 +0,0 @@
source .gdbinit.kernel
source .gdbinit.vinum.paths
source .gdbinit.vinum
asf
-5
View File
@@ -1,5 +0,0 @@
source .gdbinit.kernel
source .gdbinit.vinum.paths
source .gdbinit.vinum
tr
asf
-410
View File
@@ -1,410 +0,0 @@
/*
* Copyright (c) 1998, Larry Lile
* All rights reserved.
*
* For latest sources and information on this driver, please
* go to http://anarchy.stdio.com.
*
* Questions, comments or suggestions should be directed to
* Larry Lile <lile@stdio.com>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: if_iso88025subr.c,v 1.5 1999/01/09 22:45:58 lile Exp $
*
*/
/*
*
* General ISO 802.5 (Token Ring) support routines
*
*/
#include "opt_inet.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/netisr.h>
#include <net/route.h>
#include <net/if_llc.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_arp.h>
#include <net/iso88025.h>
#ifdef INET
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
#endif
#if NBPFILTER > 0
#include <net/bpf.h>
#include <net/bpfdesc.h>
#endif
#include <machine/clock.h>
#include <machine/md_var.h>
#include <i386/isa/isa_device.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <sys/kernel.h>
#include <net/iso88025.h>
void
iso88025_ifattach(ifp)
register struct ifnet *ifp;
{
register struct ifaddr *ifa = NULL;
register struct sockaddr_dl *sdl;
ifp->if_type = IFT_ISO88025;
ifp->if_addrlen = 6;
ifp->if_hdrlen=18;
if (ifp->if_baudrate == 0)
ifp->if_baudrate = 16000000; /* 1, 4, or 16Mbit default? */
if (ifp->if_mtu == 0)
ifp->if_mtu = ISO88025_DEFAULT_MTU;
ifa = ifnet_addrs[ifp->if_index - 1];
if (ifa == 0) {
printf("iso88025_ifattach: no lladdr!\n");
return;
}
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
sdl->sdl_type = IFT_ISO88025;
sdl->sdl_alen = ifp->if_addrlen;
bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
}
int
iso88025_ioctl(struct ifnet *ifp, int command, caddr_t data)
{
struct ifaddr *ifa = (struct ifaddr *) data;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0;
switch (command) {
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
switch (ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
ifp->if_init(ifp->if_softc); /* before arpwhohas */
arp_ifinit((struct arpcom *)ifp, ifa);
break;
#endif
default:
ifp->if_init(ifp->if_softc);
break;
}
break;
case SIOCGIFADDR:
{
struct sockaddr *sa;
sa = (struct sockaddr *) & ifr->ifr_data;
bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
(caddr_t) sa->sa_data, ISO88025_ADDR_LEN);
}
break;
case SIOCSIFMTU:
/*
* Set the interface MTU.
*/
if (ifr->ifr_mtu > ISO88025MTU) {
error = EINVAL;
} else {
ifp->if_mtu = ifr->ifr_mtu;
}
break;
}
return (error);
}
/*
* ISO88025 encapsulation
*/
int
iso88025_output(ifp, m0, dst, rt0)
register struct ifnet *ifp;
struct mbuf *m0;
struct sockaddr *dst;
struct rtentry *rt0;
{
register struct iso88025_header *th;
struct iso88025_header gen_th;
register struct iso88025_sockaddr_data *sd = (struct iso88025_sockaddr_data *)dst->sa_data;
register struct llc *l;
register struct sockaddr_dl *sdl = NULL;
int s, error = 0, rif_len = 0;
u_char edst[6];
register struct mbuf *m = m0;
register struct rtentry *rt;
int len = m->m_pkthdr.len, loop_copy = 0;
struct arpcom *ac = (struct arpcom *)ifp;
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
senderr(ENETDOWN);
rt = rt0;
if (rt) {
if ((rt->rt_flags & RTF_UP) == 0) {
rt0 = rt = rtalloc1(dst, 1, 0UL);
if (rt0)
rt->rt_refcnt--;
else
senderr(EHOSTUNREACH);
}
if (rt->rt_flags & RTF_GATEWAY) {
if (rt->rt_gwroute == 0)
goto lookup;
if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
rtfree(rt); rt = rt0;
lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
0UL);
if ((rt = rt->rt_gwroute) == 0)
senderr(EHOSTUNREACH);
}
}
if (rt->rt_flags & RTF_REJECT)
if (rt->rt_rmx.rmx_expire == 0 ||
time_second < rt->rt_rmx.rmx_expire)
senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
}
/* Calculate routing info length based on arp table entry */
if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway))
if (sdl->sdl_rcf != NULL)
rif_len = (ntohs(sdl->sdl_rcf) & 0x1f00) >> 8;
/* Generate a generic 802.5 header for the packet */
gen_th.ac = 0x10;
gen_th.fc = 0x40;
memcpy(gen_th.iso88025_shost, ac->ac_enaddr, sizeof(ac->ac_enaddr));
if (rif_len) {
gen_th.iso88025_shost[0] |= 0x80;
if (rif_len > 2) {
gen_th.rcf = sdl->sdl_rcf;
memcpy(gen_th.rseg, sdl->sdl_route, rif_len - 2);
}
}
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
if (!arpresolve(ac, rt, m, dst, edst, rt0))
return (0); /* if not yet resolved */
/* Add LLC and SNAP headers */
M_PREPEND(m, 8, M_DONTWAIT)
if (m == 0)
senderr(ENOBUFS);
l = mtod(m, struct llc *);
l->llc_un.type_snap.ether_type = htons(ETHERTYPE_IP);
l->llc_dsap = 0xaa;
l->llc_ssap = 0xaa;
l->llc_un.type_snap.control = 0x3;
l->llc_un.type_snap.org_code[0] = 0x0;
l->llc_un.type_snap.org_code[1] = 0x0;
l->llc_un.type_snap.org_code[2] = 0x0;
memcpy(gen_th.iso88025_dhost, edst, sizeof(edst));
break;
#endif
case AF_UNSPEC:
/*
* For AF_UNSPEC sockaddr.sa_data must contain all of the
* mac information needed to send the packet. This allows
* full mac, llc, and source routing function to be controlled.
* llc and source routing information must already be in the
* mbuf provided, ac/fc are set in sa_data. sockaddr.sa_data
* should be a iso88025_sockaddr_data structure see iso88025.h
*/
loop_copy = -1;
sd = (struct iso88025_sockaddr_data *)dst->sa_data;
gen_th.ac = sd->ac;
gen_th.fc = sd->fc;
memcpy(gen_th.iso88025_dhost, sd->ether_dhost, sizeof(sd->ether_dhost));
memcpy(gen_th.iso88025_shost, sd->ether_shost, sizeof(sd->ether_shost));
rif_len = 0;
break;
default:
printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
dst->sa_family);
senderr(EAFNOSUPPORT);
}
/*
* Add local net header. If no space in first mbuf,
* allocate another.
*/
M_PREPEND(m, ISO88025_HDR_LEN + rif_len, M_DONTWAIT);
if (m == 0)
senderr(ENOBUFS);
/* Copy as much of the generic header as is needed into the mbuf */
th = mtod(m, struct iso88025_header *);
memcpy(th, &gen_th, ISO88025_HDR_LEN + rif_len);
/*
* If a simplex interface, and the packet is being sent to our
* Ethernet address or a broadcast address, loopback a copy.
* XXX To make a simplex device behave exactly like a duplex
* device, we should copy in the case of sending to our own
* ethernet address (thus letting the original actually appear
* on the wire). However, we don't do that here for security
* reasons and compatibility with the original behavior.
*/
if ((ifp->if_flags & IFF_SIMPLEX) &&
(loop_copy != -1)) {
if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
/*printf("iso88025_output: if_simloop broadcast.\n");*/
(void) if_simloop(ifp, n, dst, ISO88025_HDR_LEN);
} else if (bcmp(th->iso88025_dhost,
th->iso88025_shost, ETHER_ADDR_LEN) == 0) {
/*printf("iso88025_output: if_simloop to ourselves.\n");*/
(void) if_simloop(ifp, m, dst, ISO88025_HDR_LEN);
return(0); /* XXX */
}
}
s = splimp();
/*
* Queue message on interface, and start output if interface
* not yet active.
*/
if (IF_QFULL(&ifp->if_snd)) {
printf("iso88025_output: packet dropped QFULL.\n");
IF_DROP(&ifp->if_snd);
splx(s);
senderr(ENOBUFS);
}
IF_ENQUEUE(&ifp->if_snd, m);
/*printf("iso88025_output: packet queued.\n");*/
if ((ifp->if_flags & IFF_OACTIVE) == 0)
(*ifp->if_start)(ifp);
splx(s);
ifp->if_obytes += len + ISO88025_HDR_LEN + 8;
if (m->m_flags & M_MCAST)
ifp->if_omcasts++;
return (error);
bad:
if (m)
m_freem(m);
/*printf("iso88025_output: something went wrong, bailing to bad.\n");*/
return (error);
}
/*
* ISO 88025 de-encapsulation
*/
void
iso88025_input(ifp, th, m)
struct ifnet *ifp;
register struct iso88025_header *th;
struct mbuf *m;
{
register struct ifqueue *inq;
u_short ether_type;
int s;
register struct llc *l = mtod(m, struct llc *);
/*printf("iso88025_input: entered.\n");*/
/*m->m_pkthdr.len = m->m_len = m->m_len - 8;*/ /* Length of LLC header in our case */
m->m_pkthdr.len -= 8;
m->m_len -= 8;
m->m_data += 8; /* Length of LLC header in our case */
if ((ifp->if_flags & IFF_UP) == 0) {
m_freem(m);
return;
}
ifp->if_ibytes += m->m_pkthdr.len + sizeof (*th);
if (th->iso88025_dhost[0] & 1) {
if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)th->iso88025_dhost,
sizeof(etherbroadcastaddr)) == 0)
m->m_flags |= M_BCAST;
else
m->m_flags |= M_MCAST;
}
if (m->m_flags & (M_BCAST|M_MCAST))
ifp->if_imcasts++;
ether_type = ntohs(l->llc_un.type_snap.ether_type);
/*printf("iso88025_input: source %6D dest %6D ethertype %x\n", th->iso88025_shost, ":", th->iso88025_dhost, ":", ether_type);*/
switch (ether_type) {
#ifdef INET
case ETHERTYPE_IP:
/*printf("iso88025_input: IP Packet\n");*/
th->iso88025_shost[0] &= ~(0x80); /* Turn off source route bit XXX */
if (ipflow_fastforward(m))
return;
schednetisr(NETISR_IP);
inq = &ipintrq;
break;
case ETHERTYPE_ARP:
/*printf("iso88025_input: ARP Packet\n");*/
schednetisr(NETISR_ARP);
inq = &arpintrq;
break;
#endif
default:
m_freem(m);
return;
}
s = splimp();
if (IF_QFULL(inq)) {
IF_DROP(inq);
m_freem(m);
printf("iso88025_input: Packet dropped (Queue full).\n");
} else
IF_ENQUEUE(inq, m);
/*printf("iso88025_input: Packet queued.\n");*/
splx(s);
}
-112
View File
@@ -1,112 +0,0 @@
/*
* Copyright (c) 1998, Larry Lile
* All rights reserved.
*
* For latest sources and information on this driver, please
* go to http://anarchy.stdio.com.
*
* Questions, comments or suggestions should be directed to
* Larry Lile <lile@stdio.com>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: iso88025.h,v 1.10 1999/01/09 19:01:58 lile Exp $
*
* Information gathered from tokenring@freebsd, /sys/net/ethernet.h and
* the Mach token ring driver.
*/
/*
* Fundamental constants relating to iso 802.5
*/
#ifndef _NET_ISO88025_H_
#define _NET_ISO88025_H_
/*
* The number of bytes in an iso 802.5 (MAC) address.
*/
#define ISO88025_ADDR_LEN 6
/*
*/
#define ISO88025_HDR_LEN (ISO88025_CF_LEN + ISO88025_ADDR_LEN*2)
#define ISO88025_CF_LEN 2
#define RCF_LEN 2
#define RIF_LEN 16
/*
* The minimum packet length.
*/
#define ISO88025_MIN_LEN 0 /* This offends my morality */
/*
* The maximum packet length.
*/
#define ISO88025_MAX_LEN 17960
/*
* A macro to validate a length with
*/
#define ISO88025_IS_VALID_LEN(foo) \
((foo) >= ISO88025_MIN_LEN && (foo) <= ISO88025_MAX_LEN)
/*
* ISO 802.5 physical header
*/
struct iso88025_header {
u_char ac; /* access control field */
u_char fc; /* frame control field */
u_char iso88025_dhost[ISO88025_ADDR_LEN]; /* destination address */
u_char iso88025_shost[ISO88025_ADDR_LEN]; /* source address */
u_short rcf; /* route control field */
u_short rseg[RIF_LEN]; /* routing registers */
};
struct iso88025_sockaddr_data {
u_char ether_dhost[ISO88025_ADDR_LEN];
u_char ether_shost[ISO88025_ADDR_LEN];
u_char ac;
u_char fc;
};
/*
* Structure of a 48-bit iso 802.5 address.
* ( We could also add the 16 bit addresses as a union)
*/
struct iso88025_addr {
u_char octet[ISO88025_ADDR_LEN];
};
#define ISO88025MTU 18000
#define ISO88025_DEFAULT_MTU 1500
#define senderr(e) { error = (e); goto bad;}
void iso88025_ifattach __P((struct ifnet *));
int iso88025_ioctl __P((struct ifnet *, int , caddr_t ));
int iso88025_output __P((struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *));
void iso88025_input __P((struct ifnet *, struct iso88025_header *, struct mbuf *));
#endif
+634 -257
View File
File diff suppressed because it is too large. Load diff
+4 -7
View File
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: bt848_i2c.c,v 1.2.2.1 1999/05/15 12:25:33 roger Exp $
* $Id: bt848_i2c.c,v 1.1 1998/10/31 11:26:38 nsouch Exp $
*
*/
@@ -33,12 +33,6 @@
* From brooktree848.c <fsmp@freefall.org>
*/
#include "pci.h"
#include "bktr.h"
#include "smbus.h"
#if (NBKTR > 0 && NPCI > 0 && NSMBUS > 0)
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@@ -67,7 +61,10 @@
#include "iicbb_if.h"
#include "smbus_if.h"
#include "pci.h"
#include "bktr.h"
#if (NBKTR > 0 && NPCI > 0)
#define I2C_DELAY 40
-320
View File
@@ -1,320 +0,0 @@
Introduction
This package constitutes the alpha distribution of the soft update
code updates for the fast filesystem.
For More information on what Soft Updates is, see:
http://www.ece.cmu.edu/~ganger/papers/CSE-TR-254-95/
Status
My `filesystem torture tests' (described below) run for days without
a hitch (no panic's, hangs, filesystem corruption, or memory leaks).
However, I have had several panic's reported to me by folks that
are field testing the code which I have not yet been able to
reproduce or fix. Although these panic's are rare and do not cause
filesystem corruption, the code should only be put into production
on systems where the system administrator is aware that it is being
run, and knows how to turn it off if problems arise. Thus, you may
hand out this code to others, but please ensure that this status
message is included with any distributions. Please also include
the file ffs_softdep.stub.c in any distributions so that folks that
cannot abide by the need to redistribute source will not be left
with a kernel that will not link. It will resolve all the calls
into the soft update code and simply ignores the request to enable
them. Thus you will be able to ensure that your other hooks have
not broken anything and that your kernel is softdep-ready for those
that wish to use them. Please report problems back to me with
kernel backtraces of panics if possible. This is massively complex
code, and people only have to have their filesystems hosed once or
twice to avoid future changes like the plague. I want to find and
fix as many bugs as soon as possible so as to get the code rock
solid before it gets widely released. Please report any bugs that
you uncover to [email protected].
Performance
Running the Andrew Benchmarks yields the following raw data:
Phase Normal Softdep What it does
1 3s <1s Creating directories
2 8s 4s Copying files
3 6s 6s Recursive directory stats
4 8s 9s Scanning each file
5 25s 25s Compilation
Normal: 19.9u 29.2s 0:52.8 135+630io
Softdep: 20.3u 28.5s 0:47.8 103+363io
Another interesting datapoint are my `filesystem torture tests'.
They consist of 1000 runs of the andrew benchmarks, 1000 copy and
removes of /etc with randomly selected pauses of 0-60 seconds
between each copy and remove, and 500 find from / with randomly
selected pauses of 100 seconds between each run). The run of the
torture test compares as follows:
With soft updates: writes: 6 sync, 1,113,686 async; run time 19hr, 50min
Normal filesystem: writes: 1,459,147 sync, 487,031 async; run time 27hr, 15min
The upshot is 42% less I/O and 28% shorter running time.
Another interesting test point is a full MAKEDEV. Because it runs
as a shell script, it becomes mostly limited by the execution speed
of the machine on which it runs. Here are the numbers:
With soft updates:
labrat# time ./MAKEDEV std
2.2u 32.6s 0:34.82 100.0% 0+0k 11+36io 0pf+0w
labrat# ls | wc
522 522 3317
Without soft updates:
labrat# time ./MAKEDEV std
2.0u 40.5s 0:42.53 100.0% 0+0k 11+1221io 0pf+0w
labrat# ls | wc
522 522 3317
Of course, some of the system time is being pushed
to the syncer process, but that is a different story.
To show a benchmark designed to highlight the soft update code
consider a tar of zero-sized files and an rm -rf of a directory tree
that has at least 50 files or so at each level. Running a test with
a directory tree containing 28 directories holding 202 empty files
produces the following numbers:
With soft updates:
tar: 0.0u 0.5s 0:00.65 76.9% 0+0k 0+44io 0pf+0w (0 sync, 33 async writes)
rm: 0.0u 0.2s 0:00.20 100.0% 0+0k 0+37io 0pf+0w (0 sync, 72 async writes)
Normal filesystem:
tar: 0.0u 1.1s 0:07.27 16.5% 0+0k 60+586io 0pf+0w (523 sync, 0 async writes)
rm: 0.0u 0.5s 0:01.84 29.3% 0+0k 0+318io 0pf+0w (258 sync, 65 async writes)
The large reduction in writes is because inodes are clustered, so
most of a block gets allocated, then the whole block is written
out once rather than having the same block written once for each
inode allocated from it. Similarly each directory block is written
once rather than once for each new directory entry. Effectively
what the update code is doing is allocating a bunch of inodes
and directory entries without writing anything, then ensuring that
the block containing the inodes is written first followed by the
directory block that references them. If there were data in the
files it would further ensure that the data blocks were written
before their inodes claimed them.
Copyright Restrictions
Please familiarize yourself with the copyright restrictions
contained at the top of either the sys/ufs/ffs/softdep.h or
sys/ufs/ffs/ffs_softdep.c file. The key provision is similar
to the one used by the DB 2.0 package and goes as follows:
Redistributions in any form must be accompanied by information
on how to obtain complete source code for any accompanying
software that uses the this software. This source code must
either be included in the distribution or be available for
no more than the cost of distribution plus a nominal fee,
and must be freely redistributable under reasonable
conditions. For an executable file, complete source code
means the source code for all modules it contains. It does
not mean source code for modules or files that typically
accompany the operating system on which the executable file
runs, e.g., standard library modules or system header files.
The idea is to allow those of you freely redistributing your source
to use it while retaining for myself the right to peddle it for
money to the commercial UNIX vendors. Note that I have included a
stub file ffs_softdep.c.stub that is freely redistributable so that
you can put in all the necessary hooks to run the full soft updates
code, but still allow vendors that want to maintain proprietary
source to have a working system. I do plan to release the code with
a `Berkeley style' copyright once I have peddled it around to the
commercial vendors. If you have concerns about this copyright,
feel free to contact me with them and we can try to resolve any
difficulties.
Soft Dependency Operation
The soft update implementation does NOT require ANY changes
to the on-disk format of your filesystems. Furthermore it is
not used by default for any filesystems. It must be enabled on
a filesystem by filesystem basis by running tunefs to set a
bit in the superblock indicating that the filesystem should be
managed using soft updates. If you wish to stop using
soft updates due to performance or reliability reasons,
you can simply run tunefs on it again to turn off the bit and
revert to normal operation. The additional dynamic memory load
placed on the kernel malloc arena is approximately equal to
the amount of memory used by vnodes plus inodes (for a system
with 1000 vnodes, the additional peak memory load is about 300K).
Kernel Changes
There are two new changes to the kernel functionality that are not
contained in in the soft update files. The first is a `trickle
sync' facility running in the kernel as process 3. This trickle
sync process replaces the traditional `update' program (which should
be commented out of the /etc/rc startup script). When a vnode is
first written it is placed 30 seconds down on the trickle sync
queue. If it still exists and has dirty data when it reaches the
top of the queue, it is sync'ed. This approach evens out the load
on the underlying I/O system and avoids writing short-lived files.
The papers on trickle-sync tend to favor aging based on buffers
rather than files. However, I sync on file age rather than buffer
age because the data structures are much smaller as there are
typically far fewer files than buffers. Although this can make the
I/O spikey when a big file times out, it is still much better than
the wholesale sync's that were happening before. It also adapts
much better to the soft update code where I want to control
aging to improve performance (inodes age in 10 seconds, directories
in 15 seconds, files in 30 seconds). This ensures that most
dependencies are gone (e.g., inodes are written when directory
entries want to go to disk) reducing the amount of rollback that
is needed.
The other main kernel change is to split the vnode freelist into
two separate lists. One for vnodes that are still being used to
identify buffers and the other for those vnodes no longer identifying
any buffers. The latter list is used by getnewvnode in preference
to the former.
Packaging of Kernel Changes
The sys subdirectory contains the changes and additions to the
kernel. My goal in writing this code was to minimize the changes
that need to be made to the kernel. Thus, most of the new code
is contained in the two new files softdep.h and ffs_softdep.c.
The rest of the kernel changes are simply inserting hooks to
call into these two new files. Although there has been some
structural reorganization of the filesystem code to accommodate
gathering the information required by the soft update code,
the actual ordering of filesystem operations when soft updates
are disabled is unchanged.
The kernel changes are packaged as a set of diffs. As I am
doing my development in BSD/OS, the diffs are relative to the
BSD/OS versions of the files. Because BSD/OS recently had
4.4BSD-Lite2 merged into it, the Lite2 files are a good starting
point for figuring out the changes. There are 40 files that
require change plus the two new files. Most of these files have
only a few lines of changes in them. However, four files have
fairly extensive changes: kern/vfs_subr.c, ufs/ufs/ufs_lookup.c,
ufs/ufs/ufs_vnops.c, and ufs/ffs/ffs_alloc.c. For these four
files, I have provided the original Lite2 version, the Lite2
version with the diffs merged in, and the diffs between the
BSD/OS and merged version. Even so, I expect that there will
be some difficulty in doing the merge; I am certainly willing
to assist in helping get the code merged into your system.
Packaging of Utility Changes
The utilities subdirectory contains the changes and additions
to the utilities. There are diffs to three utilities enclosed:
tunefs - add a flag to enable and disable soft updates
mount - print out whether soft updates are enabled and
also statistics on number of sync and async writes
fsck - tighter checks on acceptable errors and a slightly
different policy for what to put in lost+found on
filesystems using soft updates
In addition you should recompile vmstat so as to get reports
on the 13 new memory types used by the soft update code.
It is not necessary to use the new version of fsck, however it
would aid in my debugging if you do. Also, because of the time
lag between deleting a directory entry and the inode it
references, you will find a lot more files showing up in your
lost+found if you do not use the new version. Note that the
new version checks for the soft update flag in the superblock
and only uses the new algorithms if it is set. So, it will run
unchanged on the filesystems that are not using soft updates.
Operation
Once you have booted a kernel that incorporates the soft update
code and installed the updated utilities, do the following:
1) Comment out the update program in /etc/rc.
2) Run `tunefs -n enable' on one or more test filesystems.
3) Mount these filesystems and then type `mount' to ensure that
they have been enabled for soft updates.
4) Copy the test directory to a softdep filesystem, chdir into
it and run `./doit'. You may want to check out each of the
three subtests individually first: doit1 - andrew benchmarks,
doit2 - copy and removal of /etc, doit3 - find from /.
====
Additional notes from Feb 13
hen removing huge directories of files, it is possible to get
the incore state arbitrarily far ahead of the disk. Maintaining
all the associated depedency information can exhaust the kernel
malloc arena. To avoid this senario, I have put some limits on
the soft update code so that it will not be allowed to rampage
through all of the kernel memory. I enclose below the relevant
patches to vnode.h and vfs_subr.c (which allow the soft update
code to speed up the filesystem syncer process). I have also
included the diffs for ffs_softdep.c. I hope to make a pass over
ffs_softdep.c to isolate the differences with my standard version
so that these diffs are less painful to incorporate.
Since I know you like to play with tuning, I have put the relevant
knobs on sysctl debug variables. The tuning knobs can be viewed
with `sysctl debug' and set with `sysctl -w debug.<name>=value'.
The knobs are as follows:
debug.max_softdeps - limit on any given resource
debug.tickdelay - ticks to delay before allocating
debug.max_limit_hit - number of times tickdelay imposed
debug.rush_requests - number of rush requests to filesystem syncer
The max_softdeps limit is derived from vnodesdesired which in
turn is sized based on the amount of memory on the machine.
When the limit is hit, a process requesting a resource first
tries to speed up the filesystem syncer process. Such a
request is recorded as a rush_request. After syncdelay / 2
unserviced rush requests (typically 15) are in the filesystem
syncers queue (i.e., it is more than 15 seconds behind in its
work), the process requesting the memory is put to sleep for
tickdelay seconds. Such a delay is recorded in max_limit_hit.
Following this delay it is granted its memory without further
delay. I have tried the following experiments in which I
delete an MH directory containing 16,703 files:
Run # 1 2 3
max_softdeps 4496 4496 4496
tickdelay 100 == 1 sec 20 == 0.2 sec 2 == 0.02 sec
max_limit_hit 16 == 16 sec 27 == 5.4 sec 203 == 4.1 sec
rush_requests 147 102 93
run time 57 sec 46 sec 45 sec
I/O's 781 859 936
When run with no limits, it completes in 40 seconds. So, the
time spent in delay is directly added to the bottom line.
Shortening the tick delay does cut down the total running time,
but at the expense of generating more total I/O operations
due to the rush orders being sent to the filesystem syncer.
Although the number of rush orders decreases with a shorter
tick delay, there are more requests in each order, hence the
increase in I/O count. Also, although the I/O count does rise
with a shorter delay, it is still at least an order of magnitude
less than without soft updates. Anyway, you may want to play
around with these value to see what works best and to see if
you can get an insight into how best to tune them. If you get
out of memory panic's, then you have max_softdeps set too high.
The max_limit_hit and rush_requests show be reset to zero
before each run. The minimum legal value for tickdelay is 2
(if you set it below that, the code will use 2).
-548
View File
@@ -1,548 +0,0 @@
/*
* Copyright 1998 Marshall Kirk McKusick. All Rights Reserved.
*
* The soft updates code is derived from the appendix of a University
* of Michigan technical report (Gregory R. Ganger and Yale N. Patt,
* "Soft Updates: A Solution to the Metadata Update Problem in File
* Systems", CSE-TR-254-95, August 1995).
*
* The following are the copyrights and redistribution conditions that
* apply to this copy of the soft update software. For a license
* to use, redistribute or sell the soft update software under
* conditions other than those described here, please contact the
* author at one of the following addresses:
*
* Marshall Kirk McKusick mckusick@mckusick.com
* 1614 Oxford Street +1-510-843-9542
* Berkeley, CA 94709-1608
* USA
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. None of the names of McKusick, Ganger, Patt, or the University of
* Michigan may be used to endorse or promote products derived from
* this software without specific prior written permission.
* 4. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for any accompanying software
* that uses this software. This source code must either be included
* in the distribution or be available for no more than the cost of
* distribution plus a nominal fee, and must be freely redistributable
* under reasonable conditions. For an executable file, complete
* source code means the source code for all modules it contains.
* It does not mean source code for modules or files that typically
* accompany the operating system on which the executable file runs,
* e.g., standard library modules or system header files.
*
* THIS SOFTWARE IS PROVIDED BY MARSHALL KIRK MCKUSICK ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL MARSHALL KIRK MCKUSICK BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)softdep.h 9.6 (McKusick) 2/25/99
* $Id: softdep.h,v 1.5 1999/03/02 00:19:47 mckusick Exp $
*/
#include <sys/queue.h>
/*
* Allocation dependencies are handled with undo/redo on the in-memory
* copy of the data. A particular data dependency is eliminated when
* it is ALLCOMPLETE: that is ATTACHED, DEPCOMPLETE, and COMPLETE.
*
* ATTACHED means that the data is not currently being written to
* disk. UNDONE means that the data has been rolled back to a safe
* state for writing to the disk. When the I/O completes, the data is
* restored to its current form and the state reverts to ATTACHED.
* The data must be locked throughout the rollback, I/O, and roll
* forward so that the rolled back information is never visible to
* user processes. The COMPLETE flag indicates that the item has been
* written. For example, a dependency that requires that an inode be
* written will be marked COMPLETE after the inode has been written
* to disk. The DEPCOMPLETE flag indicates the completion of any other
* dependencies such as the writing of a cylinder group map has been
* completed. A dependency structure may be freed only when both it
* and its dependencies have completed and any rollbacks that are in
* progress have finished as indicated by the set of ALLCOMPLETE flags
* all being set. The two MKDIR flags indicate additional dependencies
* that must be done when creating a new directory. MKDIR_BODY is
* cleared when the directory data block containing the "." and ".."
* entries has been written. MKDIR_PARENT is cleared when the parent
* inode with the increased link count for ".." has been written. When
* both MKDIR flags have been cleared, the DEPCOMPLETE flag is set to
* indicate that the directory dependencies have been completed. The
* writing of the directory inode itself sets the COMPLETE flag which
* then allows the directory entry for the new directory to be written
* to disk. The RMDIR flag marks a dirrem structure as representing
* the removal of a directory rather than a file. When the removal
* dependencies are completed, additional work needs to be done
* (truncation of the "." and ".." entries, an additional decrement
* of the associated inode, and a decrement of the parent inode). The
* DIRCHG flag marks a diradd structure as representing the changing
* of an existing entry rather than the addition of a new one. When
* the update is complete the dirrem associated with the inode for
* the old name must be added to the worklist to do the necessary
* reference count decrement. The GOINGAWAY flag indicates that the
* data structure is frozen from further change until its dependencies
* have been completed and its resources freed after which it will be
* discarded. The IOSTARTED flag prevents multiple calls to the I/O
* start routine from doing multiple rollbacks. The ONWORKLIST flag
* shows whether the structure is currently linked onto a worklist.
*/
#define ATTACHED 0x0001
#define UNDONE 0x0002
#define COMPLETE 0x0004
#define DEPCOMPLETE 0x0008
#define MKDIR_PARENT 0x0010
#define MKDIR_BODY 0x0020
#define RMDIR 0x0040
#define DIRCHG 0x0080
#define GOINGAWAY 0x0100
#define IOSTARTED 0x0200
#define ONWORKLIST 0x8000
#define ALLCOMPLETE (ATTACHED | COMPLETE | DEPCOMPLETE)
/*
* The workitem queue.
*
* It is sometimes useful and/or necessary to clean up certain dependencies
* in the background rather than during execution of an application process
* or interrupt service routine. To realize this, we append dependency
* structures corresponding to such tasks to a "workitem" queue. In a soft
* updates implementation, most pending workitems should not wait for more
* than a couple of seconds, so the filesystem syncer process awakens once
* per second to process the items on the queue.
*/
/* LIST_HEAD(workhead, worklist); -- declared in buf.h */
/*
* Each request can be linked onto a work queue through its worklist structure.
* To avoid the need for a pointer to the structure itself, this structure
* MUST be declared FIRST in each type in which it appears! If more than one
* worklist is needed in the structure, then a wk_data field must be added
* and the macros below changed to use it.
*/
struct worklist {
LIST_ENTRY(worklist) wk_list; /* list of work requests */
unsigned short wk_type; /* type of request */
unsigned short wk_state; /* state flags */
};
#define WK_DATA(wk) ((void *)(wk))
#define WK_PAGEDEP(wk) ((struct pagedep *)(wk))
#define WK_INODEDEP(wk) ((struct inodedep *)(wk))
#define WK_NEWBLK(wk) ((struct newblk *)(wk))
#define WK_BMSAFEMAP(wk) ((struct bmsafemap *)(wk))
#define WK_ALLOCDIRECT(wk) ((struct allocdirect *)(wk))
#define WK_INDIRDEP(wk) ((struct indirdep *)(wk))
#define WK_ALLOCINDIR(wk) ((struct allocindir *)(wk))
#define WK_FREEFRAG(wk) ((struct freefrag *)(wk))
#define WK_FREEBLKS(wk) ((struct freeblks *)(wk))
#define WK_FREEFILE(wk) ((struct freefile *)(wk))
#define WK_DIRADD(wk) ((struct diradd *)(wk))
#define WK_MKDIR(wk) ((struct mkdir *)(wk))
#define WK_DIRREM(wk) ((struct dirrem *)(wk))
/*
* Various types of lists
*/
LIST_HEAD(dirremhd, dirrem);
LIST_HEAD(diraddhd, diradd);
LIST_HEAD(newblkhd, newblk);
LIST_HEAD(inodedephd, inodedep);
LIST_HEAD(allocindirhd, allocindir);
LIST_HEAD(allocdirecthd, allocdirect);
TAILQ_HEAD(allocdirectlst, allocdirect);
/*
* The "pagedep" structure tracks the various dependencies related to
* a particular directory page. If a directory page has any dependencies,
* it will have a pagedep linked to its associated buffer. The
* pd_dirremhd list holds the list of dirrem requests which decrement
* inode reference counts. These requests are processed after the
* directory page with the corresponding zero'ed entries has been
* written. The pd_diraddhd list maintains the list of diradd requests
* which cannot be committed until their corresponding inode has been
* written to disk. Because a directory may have many new entries
* being created, several lists are maintained hashed on bits of the
* offset of the entry into the directory page to keep the lists from
* getting too long. Once a new directory entry has been cleared to
* be written, it is moved to the pd_pendinghd list. After the new
* entry has been written to disk it is removed from the pd_pendinghd
* list, any removed operations are done, and the dependency structure
* is freed.
*/
#define DAHASHSZ 6
#define DIRADDHASH(offset) (((offset) >> 2) % DAHASHSZ)
struct pagedep {
struct worklist pd_list; /* page buffer */
# define pd_state pd_list.wk_state /* check for multiple I/O starts */
LIST_ENTRY(pagedep) pd_hash; /* hashed lookup */
struct mount *pd_mnt; /* associated mount point */
ino_t pd_ino; /* associated file */
ufs_lbn_t pd_lbn; /* block within file */
struct dirremhd pd_dirremhd; /* dirrem's waiting for page */
struct diraddhd pd_diraddhd[DAHASHSZ]; /* diradd dir entry updates */
struct diraddhd pd_pendinghd; /* directory entries awaiting write */
};
/*
* The "inodedep" structure tracks the set of dependencies associated
* with an inode. One task that it must manage is delayed operations
* (i.e., work requests that must be held until the inodedep's associated
* inode has been written to disk). Getting an inode from its incore
* state to the disk requires two steps to be taken by the filesystem
* in this order: first the inode must be copied to its disk buffer by
* the VOP_UPDATE operation; second the inode's buffer must be written
* to disk. To ensure that both operations have happened in the required
* order, the inodedep maintains two lists. Delayed operations are
* placed on the id_inowait list. When the VOP_UPDATE is done, all
* operations on the id_inowait list are moved to the id_bufwait list.
* When the buffer is written, the items on the id_bufwait list can be
* safely moved to the work queue to be processed. A second task of the
* inodedep structure is to track the status of block allocation within
* the inode. Each block that is allocated is represented by an
* "allocdirect" structure (see below). It is linked onto the id_newinoupdt
* list until both its contents and its allocation in the cylinder
* group map have been written to disk. Once these dependencies have been
* satisfied, it is removed from the id_newinoupdt list and any followup
* actions such as releasing the previous block or fragment are placed
* on the id_inowait list. When an inode is updated (a VOP_UPDATE is
* done), the "inodedep" structure is linked onto the buffer through
* its worklist. Thus, it will be notified when the buffer is about
* to be written and when it is done. At the update time, all the
* elements on the id_newinoupdt list are moved to the id_inoupdt list
* since those changes are now relevant to the copy of the inode in the
* buffer. Also at update time, the tasks on the id_inowait list are
* moved to the id_bufwait list so that they will be executed when
* the updated inode has been written to disk. When the buffer containing
* the inode is written to disk, any updates listed on the id_inoupdt
* list are rolled back as they are not yet safe. Following the write,
* the changes are once again rolled forward and any actions on the
* id_bufwait list are processed (since those actions are now safe).
* The entries on the id_inoupdt and id_newinoupdt lists must be kept
* sorted by logical block number to speed the calculation of the size
* of the rolled back inode (see explanation in initiate_write_inodeblock).
* When a directory entry is created, it is represented by a diradd.
* The diradd is added to the id_inowait list as it cannot be safely
* written to disk until the inode that it represents is on disk. After
* the inode is written, the id_bufwait list is processed and the diradd
* entries are moved to the id_pendinghd list where they remain until
* the directory block containing the name has been written to disk.
* The purpose of keeping the entries on the id_pendinghd list is so that
* the softdep_fsync function can find and push the inode's directory
* name(s) as part of the fsync operation for that file.
*/
struct inodedep {
struct worklist id_list; /* buffer holding inode block */
# define id_state id_list.wk_state /* inode dependency state */
LIST_ENTRY(inodedep) id_hash; /* hashed lookup */
struct fs *id_fs; /* associated filesystem */
ino_t id_ino; /* dependent inode */
nlink_t id_nlinkdelta; /* saved effective link count */
struct dinode *id_savedino; /* saved dinode contents */
LIST_ENTRY(inodedep) id_deps; /* bmsafemap's list of inodedep's */
struct buf *id_buf; /* related bmsafemap (if pending) */
off_t id_savedsize; /* file size saved during rollback */
struct workhead id_pendinghd; /* entries awaiting directory write */
struct workhead id_bufwait; /* operations after inode written */
struct workhead id_inowait; /* operations waiting inode update */
struct allocdirectlst id_inoupdt; /* updates before inode written */
struct allocdirectlst id_newinoupdt; /* updates when inode written */
};
/*
* A "newblk" structure is attached to a bmsafemap structure when a block
* or fragment is allocated from a cylinder group. Its state is set to
* DEPCOMPLETE when its cylinder group map is written. It is consumed by
* an associated allocdirect or allocindir allocation which will attach
* themselves to the bmsafemap structure if the newblk's DEPCOMPLETE flag
* is not set (i.e., its cylinder group map has not been written).
*/
struct newblk {
LIST_ENTRY(newblk) nb_hash; /* hashed lookup */
struct fs *nb_fs; /* associated filesystem */
ufs_daddr_t nb_newblkno; /* allocated block number */
int nb_state; /* state of bitmap dependency */
LIST_ENTRY(newblk) nb_deps; /* bmsafemap's list of newblk's */
struct bmsafemap *nb_bmsafemap; /* associated bmsafemap */
};
/*
* A "bmsafemap" structure maintains a list of dependency structures
* that depend on the update of a particular cylinder group map.
* It has lists for newblks, allocdirects, allocindirs, and inodedeps.
* It is attached to the buffer of a cylinder group block when any of
* these things are allocated from the cylinder group. It is freed
* after the cylinder group map is written and the state of its
* dependencies are updated with DEPCOMPLETE to indicate that it has
* been processed.
*/
struct bmsafemap {
struct worklist sm_list; /* cylgrp buffer */
struct buf *sm_buf; /* associated buffer */
struct allocdirecthd sm_allocdirecthd; /* allocdirect deps */
struct allocindirhd sm_allocindirhd; /* allocindir deps */
struct inodedephd sm_inodedephd; /* inodedep deps */
struct newblkhd sm_newblkhd; /* newblk deps */
};
/*
* An "allocdirect" structure is attached to an "inodedep" when a new block
* or fragment is allocated and pointed to by the inode described by
* "inodedep". The worklist is linked to the buffer that holds the block.
* When the block is first allocated, it is linked to the bmsafemap
* structure associated with the buffer holding the cylinder group map
* from which it was allocated. When the cylinder group map is written
* to disk, ad_state has the DEPCOMPLETE flag set. When the block itself
* is written, the COMPLETE flag is set. Once both the cylinder group map
* and the data itself have been written, it is safe to write the inode
* that claims the block. If there was a previous fragment that had been
* allocated before the file was increased in size, the old fragment may
* be freed once the inode claiming the new block is written to disk.
* This ad_fragfree request is attached to the id_inowait list of the
* associated inodedep (pointed to by ad_inodedep) for processing after
* the inode is written.
*/
struct allocdirect {
struct worklist ad_list; /* buffer holding block */
# define ad_state ad_list.wk_state /* block pointer state */
TAILQ_ENTRY(allocdirect) ad_next; /* inodedep's list of allocdirect's */
ufs_lbn_t ad_lbn; /* block within file */
ufs_daddr_t ad_newblkno; /* new value of block pointer */
ufs_daddr_t ad_oldblkno; /* old value of block pointer */
long ad_newsize; /* size of new block */
long ad_oldsize; /* size of old block */
LIST_ENTRY(allocdirect) ad_deps; /* bmsafemap's list of allocdirect's */
struct buf *ad_buf; /* cylgrp buffer (if pending) */
struct inodedep *ad_inodedep; /* associated inodedep */
struct freefrag *ad_freefrag; /* fragment to be freed (if any) */
};
/*
* A single "indirdep" structure manages all allocation dependencies for
* pointers in an indirect block. The up-to-date state of the indirect
* block is stored in ir_savedata. The set of pointers that may be safely
* written to the disk is stored in ir_safecopy. The state field is used
* only to track whether the buffer is currently being written (in which
* case it is not safe to update ir_safecopy). Ir_deplisthd contains the
* list of allocindir structures, one for each block that needs to be
* written to disk. Once the block and its bitmap allocation have been
* written the safecopy can be updated to reflect the allocation and the
* allocindir structure freed. If ir_state indicates that an I/O on the
* indirect block is in progress when ir_safecopy is to be updated, the
* update is deferred by placing the allocindir on the ir_donehd list.
* When the I/O on the indirect block completes, the entries on the
* ir_donehd list are processed by updating their corresponding ir_safecopy
* pointers and then freeing the allocindir structure.
*/
struct indirdep {
struct worklist ir_list; /* buffer holding indirect block */
# define ir_state ir_list.wk_state /* indirect block pointer state */
caddr_t ir_saveddata; /* buffer cache contents */
struct buf *ir_savebp; /* buffer holding safe copy */
struct allocindirhd ir_donehd; /* done waiting to update safecopy */
struct allocindirhd ir_deplisthd; /* allocindir deps for this block */
};
/*
* An "allocindir" structure is attached to an "indirdep" when a new block
* is allocated and pointed to by the indirect block described by the
* "indirdep". The worklist is linked to the buffer that holds the new block.
* When the block is first allocated, it is linked to the bmsafemap
* structure associated with the buffer holding the cylinder group map
* from which it was allocated. When the cylinder group map is written
* to disk, ai_state has the DEPCOMPLETE flag set. When the block itself
* is written, the COMPLETE flag is set. Once both the cylinder group map
* and the data itself have been written, it is safe to write the entry in
* the indirect block that claims the block; the "allocindir" dependency
* can then be freed as it is no longer applicable.
*/
struct allocindir {
struct worklist ai_list; /* buffer holding indirect block */
# define ai_state ai_list.wk_state /* indirect block pointer state */
LIST_ENTRY(allocindir) ai_next; /* indirdep's list of allocindir's */
int ai_offset; /* pointer offset in indirect block */
ufs_daddr_t ai_newblkno; /* new block pointer value */
ufs_daddr_t ai_oldblkno; /* old block pointer value */
struct freefrag *ai_freefrag; /* block to be freed when complete */
struct indirdep *ai_indirdep; /* address of associated indirdep */
LIST_ENTRY(allocindir) ai_deps; /* bmsafemap's list of allocindir's */
struct buf *ai_buf; /* cylgrp buffer (if pending) */
};
/*
* A "freefrag" structure is attached to an "inodedep" when a previously
* allocated fragment is replaced with a larger fragment, rather than extended.
* The "freefrag" structure is constructed and attached when the replacement
* block is first allocated. It is processed after the inode claiming the
* bigger block that replaces it has been written to disk. Note that the
* ff_state field is is used to store the uid, so may lose data. However,
* the uid is used only in printing an error message, so is not critical.
* Keeping it in a short keeps the data structure down to 32 bytes.
*/
struct freefrag {
struct worklist ff_list; /* id_inowait or delayed worklist */
# define ff_state ff_list.wk_state /* owning user; should be uid_t */
struct vnode *ff_devvp; /* filesystem device vnode */
struct fs *ff_fs; /* addr of superblock */
ufs_daddr_t ff_blkno; /* fragment physical block number */
long ff_fragsize; /* size of fragment being deleted */
ino_t ff_inum; /* owning inode number */
};
/*
* A "freeblks" structure is attached to an "inodedep" when the
* corresponding file's length is reduced to zero. It records all
* the information needed to free the blocks of a file after its
* zero'ed inode has been written to disk.
*/
struct freeblks {
struct worklist fb_list; /* id_inowait or delayed worklist */
ino_t fb_previousinum; /* inode of previous owner of blocks */
struct vnode *fb_devvp; /* filesystem device vnode */
struct fs *fb_fs; /* addr of superblock */
off_t fb_oldsize; /* previous file size */
off_t fb_newsize; /* new file size */
int fb_chkcnt; /* used to check cnt of blks released */
uid_t fb_uid; /* uid of previous owner of blocks */
ufs_daddr_t fb_dblks[NDADDR]; /* direct blk ptrs to deallocate */
ufs_daddr_t fb_iblks[NIADDR]; /* indirect blk ptrs to deallocate */
};
/*
* A "freefile" structure is attached to an inode when its
* link count is reduced to zero. It marks the inode as free in
* the cylinder group map after the zero'ed inode has been written
* to disk and any associated blocks and fragments have been freed.
*/
struct freefile {
struct worklist fx_list; /* id_inowait or delayed worklist */
mode_t fx_mode; /* mode of inode */
ino_t fx_oldinum; /* inum of the unlinked file */
struct vnode *fx_devvp; /* filesystem device vnode */
struct fs *fx_fs; /* addr of superblock */
};
/*
* A "diradd" structure is linked to an "inodedep" id_inowait list when a
* new directory entry is allocated that references the inode described
* by "inodedep". When the inode itself is written (either the initial
* allocation for new inodes or with the increased link count for
* existing inodes), the COMPLETE flag is set in da_state. If the entry
* is for a newly allocated inode, the "inodedep" structure is associated
* with a bmsafemap which prevents the inode from being written to disk
* until the cylinder group has been updated. Thus the da_state COMPLETE
* flag cannot be set until the inode bitmap dependency has been removed.
* When creating a new file, it is safe to write the directory entry that
* claims the inode once the referenced inode has been written. Since
* writing the inode clears the bitmap dependencies, the DEPCOMPLETE flag
* in the diradd can be set unconditionally when creating a file. When
* creating a directory, there are two additional dependencies described by
* mkdir structures (see their description below). When these dependencies
* are resolved the DEPCOMPLETE flag is set in the diradd structure.
* If there are multiple links created to the same inode, there will be
* a separate diradd structure created for each link. The diradd is
* linked onto the pg_diraddhd list of the pagedep for the directory
* page that contains the entry. When a directory page is written,
* the pg_diraddhd list is traversed to rollback any entries that are
* not yet ready to be written to disk. If a directory entry is being
* changed (by rename) rather than added, the DIRCHG flag is set and
* the da_previous entry points to the entry that will be "removed"
* once the new entry has been committed. During rollback, entries
* with da_previous are replaced with the previous inode number rather
* than zero.
*
* The overlaying of da_pagedep and da_previous is done to keep the
* structure down to 32 bytes in size on a 32-bit machine. If a
* da_previous entry is present, the pointer to its pagedep is available
* in the associated dirrem entry. If the DIRCHG flag is set, the
* da_previous entry is valid; if not set the da_pagedep entry is valid.
* The DIRCHG flag never changes; it is set when the structure is created
* if appropriate and is never cleared.
*/
struct diradd {
struct worklist da_list; /* id_inowait or id_pendinghd list */
# define da_state da_list.wk_state /* state of the new directory entry */
LIST_ENTRY(diradd) da_pdlist; /* pagedep holding directory block */
doff_t da_offset; /* offset of new dir entry in dir blk */
ino_t da_newinum; /* inode number for the new dir entry */
union {
struct dirrem *dau_previous; /* entry being replaced in dir change */
struct pagedep *dau_pagedep; /* pagedep dependency for addition */
} da_un;
};
#define da_previous da_un.dau_previous
#define da_pagedep da_un.dau_pagedep
/*
* Two "mkdir" structures are needed to track the additional dependencies
* associated with creating a new directory entry. Normally a directory
* addition can be committed as soon as the newly referenced inode has been
* written to disk with its increased link count. When a directory is
* created there are two additional dependencies: writing the directory
* data block containing the "." and ".." entries (MKDIR_BODY) and writing
* the parent inode with the increased link count for ".." (MKDIR_PARENT).
* These additional dependencies are tracked by two mkdir structures that
* reference the associated "diradd" structure. When they have completed,
* they set the DEPCOMPLETE flag on the diradd so that it knows that its
* extra dependencies have been completed. The md_state field is used only
* to identify which type of dependency the mkdir structure is tracking.
* It is not used in the mainline code for any purpose other than consistency
* checking. All the mkdir structures in the system are linked together on
* a list. This list is needed so that a diradd can find its associated
* mkdir structures and deallocate them if it is prematurely freed (as for
* example if a mkdir is immediately followed by a rmdir of the same directory).
* Here, the free of the diradd must traverse the list to find the associated
* mkdir structures that reference it. The deletion would be faster if the
* diradd structure were simply augmented to have two pointers that referenced
* the associated mkdir's. However, this would increase the size of the diradd
* structure from 32 to 64-bits to speed a very infrequent operation.
*/
struct mkdir {
struct worklist md_list; /* id_inowait or buffer holding dir */
# define md_state md_list.wk_state /* type: MKDIR_PARENT or MKDIR_BODY */
struct diradd *md_diradd; /* associated diradd */
struct buf *md_buf; /* MKDIR_BODY: buffer holding dir */
LIST_ENTRY(mkdir) md_mkdirs; /* list of all mkdirs */
};
LIST_HEAD(mkdirlist, mkdir) mkdirlisthd;
/*
* A "dirrem" structure describes an operation to decrement the link
* count on an inode. The dirrem structure is attached to the pg_dirremhd
* list of the pagedep for the directory page that contains the entry.
* It is processed after the directory page with the deleted entry has
* been written to disk.
*
* The overlaying of dm_pagedep and dm_dirinum is done to keep the
* structure down to 32 bytes in size on a 32-bit machine. It works
* because they are never used concurrently.
*/
struct dirrem {
struct worklist dm_list; /* delayed worklist */
# define dm_state dm_list.wk_state /* state of the old directory entry */
LIST_ENTRY(dirrem) dm_next; /* pagedep's list of dirrem's */
struct mount *dm_mnt; /* associated mount point */
ino_t dm_oldinum; /* inum of the removed dir entry */
union {
struct pagedep *dmu_pagedep; /* pagedep dependency for remove */
ino_t dmu_dirinum; /* parent inode number (for rmdir) */
} dm_un;
};
#define dm_pagedep dm_un.dmu_pagedep
#define dm_dirinum dm_un.dmu_dirinum
-4
View File
@@ -1,4 +0,0 @@
PROG= memcontrol
NOMAN= yes
.include <bsd.prog.mk>
-33
View File
@@ -1,33 +0,0 @@
/*-
* Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id:$
*/
struct lcp;
extern int acf_WrapperOctets(struct lcp *, u_short);
extern struct layer acflayer;
-48
View File
@@ -1,48 +0,0 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the Internet Initiative Japan. The name of the
* IIJ may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id:$
*/
/*
* Definition of protocol numbers
*/
#define PROTO_IP 0x0021 /* IP */
#define PROTO_VJUNCOMP 0x002f /* VJ Uncompressed */
#define PROTO_VJCOMP 0x002d /* VJ Compressed */
#define PROTO_MP 0x003d /* Multilink fragment */
#define PROTO_ICOMPD 0x00fb /* Individual link compressed */
#define PROTO_COMPD 0x00fd /* Compressed datagram */
#define PROTO_COMPRESSIBLE(p) (((p) & 0xffe1) == 0x21)
#define PROTO_IPCP 0x8021
#define PROTO_ICCP 0x80fb
#define PROTO_CCP 0x80fd
#define PROTO_LCP 0xc021
#define PROTO_PAP 0xc023
#define PROTO_CBCP 0xc029
#define PROTO_LQR 0xc025
#define PROTO_CHAP 0xc223
struct lcp;
extern int proto_WrapperOctets(struct lcp *, u_short);
struct mbuf *proto_Prepend(struct mbuf *, u_short, unsigned, int);
extern struct layer protolayer;
-29
View File
@@ -1,29 +0,0 @@
/*-
* Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id:$
*/
extern struct layer synclayer;
-9
View File
@@ -1,9 +0,0 @@
# $Id: Makefile,v 1.2 1997/05/23 04:04:15 msmith Exp $
PROG= wicontrol
SRCS= wicontrol.c
CFLAGS+= -Wall
MAN8= wicontrol.8
.include <bsd.prog.mk>