mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 19:34:43 +01:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c37538200e |
No files matched your search
@@ -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.
|
||||
.\}
|
||||
|
||||
@@ -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
@@ -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');
|
||||
}
|
||||
@@ -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];
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
@@ -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" ; \
|
||||
|
||||
@@ -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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
|
||||
M9NK)90SV?O/7+4C]Z^/P@M0ST-/"JVMB1Q]DVOX5(`-1*W))")GLIL9EI:96U7P>B(0+B;Q.CJDSI9OT9O$9R_<5&
|
||||
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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
|
||||
M!G3\]?Y17G9+F7\"O5<%%R;P&@3\#M_->5E;^X=Y20.965.*$]6FI/A(BZ+!
|
||||
ME\:K?=:3'Q(OZFK=Y'[4TK?I_:A-$%P'9B4S4)\*J`]NX7GANYP@Y%;(WY_G
|
||||
MQ4Z2IWP:)/J#B*"9'OM9,:03XCWVS_UZK]AF1/6JX]-#_-!5&H_].,3&]1N,
|
||||
M>@W@TG*ENGA<AP8RQ##L%^^$_HRW/&)_GOS-^R^O8_SA+/[#5XU?!&,4R*M+
|
||||
M5H(]$^Q2L+U@5X+]!-A\'YEP+JD#^P=@KP-[&]B-8/\*[":P'P2[!>R7P-X(
|
||||
M-HA02[Q@`Y1+-H,-;&')TV##4+3D&;"KP=X*-@AP2[:!_2.PMX-="/8.L(>`
|
||||
MO1/LY6"_V(=`<TM:P889T9*]8$-MEK2![0;[$-AY8!\&^UZPCX+]$-A=8,\&
|
||||
M^P38UX-]$NS[P>X&>SW8:3!.Q4.4!6`#$YV=P^PES%[*[(>8_0BS5S*;[\?K
|
||||
M@+C9=<S=Q-PMS+V9N9]F[FW,O9VY7V3N5N8^Q-R'F?L$<P>8.^U+4I_9D[XD
|
||||
M]9G]D$9#X*\$&^-YP?X!E@OV`U@NV##.S7X&;*CO[*U@PR@X6V'Q>EF\/A:O
|
||||
MG\4+L'@96AIOMI;&FZNE\19H:;P<+8VW3DOA:&+Q#7H-@=?(;#.S+<Q.9G8*
|
||||
MLZW,3F7V:&:/8W8:LR<Q>RJSIS,[@]FSF3V7V0N8G</L)<Q>RNR'F/T(LXN8
|
||||
MO9+9I<RN9#;/[#IFKV-V([.;F-W"[(W,]C)[,[.?9O8SS-[*[&W,WL[L'<S>
|
||||
MR>P7F=W*[+W,;F/V(68?9O919G<Q^P2S3S*[F]D]S#[+;(79O<SN8W8_LP/,
|
||||
M#C*;BZ.VGMD&9AN9;6:VA=G)S$YAMI79J<P>S>QQS$YC]B1F3V7V=&9G,'LV
|
||||
ML[GO?M_]OOO]VS\4P%#+.HNYD]@E7P\S=PJ8>\#<SA%Y@1O-D?&4PRT7?!AQ
|
||||
M!!A\/AJ/;Q82@8/CIJ'B,TL?!P8D*!Q3N!I<G0<S(ZK\A6#JP1B9&V0!#J;S
|
||||
MW"R.C/_<#0R6<<P/EU-P/I2..M)@\$PGR!G<4%8&B.O<]S@R9I)?(HN+,#U(
|
||||
MGT@A/YPAS0.#FCGXX#4*GWC:"@7/"7@LA%VE8F8PXHRR`DPR*R.>Y8%+O;C)
|
||||
M-);A$'&`.L_7@LD$<P<NC$?EAS,@5*8:S!%YB;L&#-YWC1I%('H3V1`7ND:"
|
||||
MF0_F.H[(4]R->-44&)0@\=#YS1R1NXAZ>#Z86SDB%W&X`9<-YC:.[AV"5,BM
|
||||
M8'7*967/9FVRF)7Y""O#P6!:P'!:PMKB(5:6D]$"QVCF"=:6RQAM/,I@6\1H
|
||||
M:#G#014KLX#1RO<9C$M8G<I9G>]C;?(LJ_L>UI9E#+;5+._[6=U6L3H4L;K]
|
||||
MF.6QB>7-,9C7,-QP#%<_8CBO9'G]@-$&S^KZ,H-18C`_R7#D9G456-VJ6=E/
|
||||
M,1JJ96U=RG#.,5IXAN%R+8/Y/QFN.!:78W7T,%QPC-9:69V;&0Y_S\I\CL'*
|
||||
M,5A:6-]J8C"(C"9_RNJ^@97]0U97CO6AQUF=.-8''V-];BOK6[]A?7TS"WN:
|
||||
MY<VQLF0&&\=HX0\,%H[A[C]8V1R+NX7UL5^PNGH9;CF&0X[Y;6.P<BP/CK7I
|
||||
M'QDLNUA>/V=M^1-F?J;.>MCW;H;[[2SN+UG9'&N#7[.Z_I:%_1?C:<^S;X[!
|
||||
M\@*C28ZEX1AN.)8WQ_+X'3,OL;;:P0S'<,.QMN-8&3N9X5C=.%;6BZR.'/OF
|
||||
M6%TXEC?'^@;':.051K/AS4+V0U[,]47X>APPN9Y*ZA[*W&FL`48R]]3)U'TC
|
||||
M<^OO9GJFS)W#"IK*W&W[(Q=#XG&U[5HBEQ&>B>&629%^2/)C"'N8N<_>1=TN
|
||||
MYLYX@;JKF+MI8H1>2?D,42+C[:GDTDU*1QC>,I:&/\W<J7^,M#>ZE?^,M"/)
|
||||
MCY6WD^'K$8:O3C5\'W4?9V[K'=3]/G,OJ:+NOZKX983B9^X76?W^J>;W#'7_
|
||||
MB[FW3Z5N?#*&X(?!<PUSMTUCXS!S6QM8>S!W'\/_!.;.8.V3P=Q+F?L^YE["
|
||||
MX'F(N6>W,3ZENEE[53%W(VO_-<Q]\E?4O9ZY<]B`L$&%]W;67YE;81WI9\R]
|
||||
MF;7_L\S=PL+_P-R&="[\W`VZG][&VH.Y)S%X3Z#[E@@]GF'A12S_?S!W-^NP
|
||||
M%YF[=QR3"[2,OA@^AFFIK"*P^"-9^$[&,&[64GH;S>@MC;G',3>^1(GTS^;O
|
||||
MW'TL/(V%/\+"%1:^FN6_D=6GGKF3F5MF[AYVD\PFYO8R?/^,Y3^)Y?\;EC_.
|
||||
MQ['M7U33LSML_L3<C2R_-YA[`>M?[V@I/E5Z^2L+;V/]YY\JO$QX^TI-S_K;
|
||||
M$!UU][/^<9..PC>5P3>6A6]C]#J9N1L9`YS)W%-9_YG#W*69U+V8N5,9?K[/
|
||||
MW(\P>EG-W`KKKV[F-K+X&YC[F78VKC!W<"9U_T3-_[>,K^LH/N8R?+RBPO=+
|
||||
MZGX-W5"URIVT/=]@X6D5-/PD<R]@^,=G5+%]'M%0_O@E"S<PP3NDH_2WD/'N
|
||||
MP7J*O^D,?R/T-/U#+#T^Q4;JQ_C9W7H*;[C_L_!M!ZE[+G/WL/!<YO:R_OT0
|
||||
M<P?9C4;%S)W#Z*6"N4^P@:^>N=/8>"(Q=Q'+SZOFS^K_2^;&?36"7^:>RO#_
|
||||
M"G,O9>WU)^;N8P-A%W.7,OKJ4?,?1=V*FI[QISZUO@R>2\Q]F+5??!R#]T[J
|
||||
M'A['^L^7P"-A,G('"W^$#:B3F7OK`>K.9.YQK'X+F3O(X,]7XS-\/<K<R6Q\
|
||||
M7</<)[<R?LK*YW%]#^PG6'@/&P]^R,+GQI'U/^[G:OZ,WGX=1^DE@]'+3A9N
|
||||
M9OWG9>9N9>Z#S&VU4?=;S*T*$N\Q]R%&CSW,O8V-#W]G[B8V?OV#E3^;E1]D
|
||||
MX8V,?QCB&3P,7R.8V\KX\2W,/971QQCF7L#Z]SW,S3-ZSHJG_:7T+#M7P,*]
|
||||
MK#ZY\12>N0R>!UEX$</W,N8>Q_+GF7OK:NIN4..S]FIF[L,,/CF>M@>NA^+<
|
||||
M=7,\E9G4WYOQ=&ZM_MYCZ5]D_>OOS#V)T6<O<W>U4O=YYFYE^$I(H&Z5']W(
|
||||
MW-V,?Z<RMY7QYSN9NY'5[V[F3F;TFY%`\;.`X6<."U=O,,MAX3DLO$#-G_'/
|
||||
ME<QM8?@H9^Z@G;KKF+N?C<<-S/T(ZP_-S)W#\"TS-\_H:Y.:?RIU/\/<@9%,
|
||||
M+E?KQ^2-WZGPL?S_R-PG6'ZMS-W%ZO^:"@_#YY\3*/]4^^L)%CZ)P?]>`I4/
|
||||
M5\91?'R40-L?]P=PKN1G\0^Q^%\P]].,OK]B^%S*\*DU4/<2%;\%L^]?F.F8
|
||||
M-XLKH&<5"@H*BOB*0J[`557%%:".-W@5\U5K4`L:=8H+JGEA&5=04EW(\VLP
|
||||
M>DDUOQ)5YUU%7$%I-5\(>:QP\94E1<06T(9?E5#N0DU^KJ`.(J.Z->914EZ,
|
||||
MH<M+787E0B5)4.2J=:W!L/)"*)H<KR5`E=04E=P%7W,6+,K*7%"P*#O[/ON2
|
||||
M@B6960OL!1BANJSP4=<R`?);SK*'S%SE-1P`7%7MHIFO0&C`S5>4<@4UM855
|
||||
MY760MKRB'*I5*?`()%>`E2DJJ6(1(0&_'))"=:L0%0/P4%`LE`_PPG))0<N+
|
||||
MJUU\=:4+,5.&9RQ<RQ'!KKH2GF2^''&%VONDM#!:Z+%14J<UU<OY4NJS$J*4
|
||||
M%15@+0M606ZN<%Q$$"FJA)45W5QJ-J@J7A!U8`]BE907%926+"N@T1!J;"QZ
|
||||
M2)#D7(1-4@X0%D+QT`)5U=P`!U]87E18513K6Y!3R*]<4`%%NL*U*JB&\%(D
|
||||
M)GXYGMA9!OZ/(M@K(F!75I64\]!^:JT+"O"X!1XO(GY(D:@[3]"P#($'-%27
|
||||
M5B!*BVL+2R&[NC*&PJA&";<OE$3;-X+R:CX,.CE-50`-'^L!D8M*BO!J1H*]
|
||||
M0G)JAWR6%]*&*5?;JK:JA'>QEJA06QVSXPM(;2LKH'HTYLI"GE(J5E^-RR\'
|
||||
MVJHE$8I95RBI<I7S526NZAC"*P(R7P%YN\K**FH8;LI)=ZVI+E>1J)(*HY."
|
||||
M@K)E!<N%*O"L(T4L+ZVHAK2(1U=5`1:#W0SJ!<F1SF<)55AX+F!,;4JH+*.-
|
||||
MX@ARJUVEE*H!ZE*A&E!&<B;HC?3K8A4LK!6/!V2J2]92VJP%!&$4AKXH$J=M
|
||||
M2WHIQ*QR+2\M+"DKX%VEI23WY<48L:J0H&PU\(<J5UE,"Y)8*D70L_&$K9$F
|
||||
MH=#CC078?5@*[`T4\MFNXD*A-*;Z6,,:!B42,5^YHJJ2`$QP7$C]BZKP+`]$
|
||||
M)J@J$,HCS%$MFO9_>ED"R3:;M$]%$65P!27J7:`$/810"@H@>Y(,O#`_\D$.
|
||||
M_A!F6[@BC%!!S:B*+R7,#ID,XW1X?`8P4EFPDF9!.@8E;J@&9(3H@]X)R"VK
|
||||
M+&><N`;@KHLT#."+T10Y+@35`LAX.E00W`'/+:G"3D*NGX@D7%'!AXD1>0_A
|
||||
MS36$;ED30Q\M%5P<NDK*5TRS\BM+JM63E7B.K=I:#"R!,I318\99:U>6+%^)
|
||||
M1^.`[\)X,Q[H+!P>^ZVB3%"'$0"JN*0NFH/$=B_&RJN750&&(R1744YX-FE^
|
||||
M.B``_.45!':*QS"*>3SD23HUZ144B37ACE!,&Z8,HG(J10CEQ%6GQJ&=$^)6
|
||||
MN5PXMI+F9AV7C$F4`HM9$8SFN()'2Y#9NXH*>1C'@?67`S!0F>+EY=A>B/OJ
|
||||
ME4#JV%1%2"<%](0FI8KO?M_]OOM]]_ON]]WON]]WO^]^W_V^^_U__<.U=W,?
|
||||
MQXWN^_9I<$^Y!TS;08[K>IWCMG=1?]0?6MK-<18#W:>?JZ/V(;:OAVO7N)Z.
|
||||
M:X2X+X!KL;A>BWM$N.Z(>XFX_XA[DKCOB'L7N-^&:]*XSX-[X[B?@WORN"^`
|
||||
M>T>X?X![5KA/B'M+N+^'>\ZX+X5[`U[?1:*IY/4EC:'VIUG4?IS9SS$[F]D?
|
||||
MV*@]?AJU[VBD]O!9U-;:J7U+!K6?9/[QZZD]OY[:CRVB]M]9O*P_,#@F4_LV
|
||||
MENYQYE_#W+]@]L'=U'Z3P37Q16H?^R.U.[)9_.>H_<E,EO^]+#YS9S/[(BOG
|
||||
MIW<Q^*=2>PBK3]X]#&Y6[V4LGT\SJ;U?]7^!VL,64GL:@_?,.I8?<[_'XKW"
|
||||
MX'R`E?.+=&JO8O6XQ,HY^%L&)XM_RUQ6+U;_.W:R^MU-[3V[J+V!Q5OU/8;7
|
||||
M^ZC]`O,?\A*UWV'XO&,^B\?\'V?NQUGX+0R?6H;OYYB=ZV#I.UF\#H9/-ROO
|
||||
M3]1>R^S'#C#X][-V8_ZO,#R]Q]RO[Z/VC_;%TLDK#(X-/Z5V^0)6WA%JW\CJ
|
||||
M/Y/!5\SLW^UEY;)\'F#EO\#BE[-XOWZ=Q6-POL#<[S$[[TUJUQ.;W"2#^@+0
|
||||
M+R<(U5438)[OJG,MGU!:-+ZZ@NH#XN/!"ZP<=Q9,\!;HK[=RW,9;V/Y[*M4]
|
||||
MQ-V!C=!GWTVENH/D$F9P[TVENH'H;@'W?Z52W43\;0;WCU(C.I5-X&Y,I3J)
|
||||
M1#<&W"6I5->0[*W$:2[C6?J!/.R.6#<NR#D*5Y3@RM77\3Z5OWR%VH_:;V&R
|
||||
MM%21,MIH_Y=,1CPTB/[?-\8X3@-&"T8'1@\F#DP\F`0P!C")8+XNCR0ICAL$
|
||||
MQ@AF,)@A8$Q@R`;Z_Z:Y6ODCH7PP1C"#P0P!8P+#C=3_[YJ!96N_DQV^^U%^
|
||||
MA:2@8SP&]_!1ESJ!R5:X)XJZBLCKD'^AGC3JA*,^.?)#U%M$77/4FT:=:>1I
|
||||
MR,=0#QWY'VX/(U]$_6_474?]<=R71SUQ8+-$;QI9+.I+X]8RJH^@KC1N(Z-N
|
||||
M.^JG(ZM#M2;<NKV3R6FH/XU;\;B=CEONJ#:&6\NX?8\J`K@-CJH0J'Z`*GNH
|
||||
MIH4ZTK@=CRHNN.V/6^NH'XXZQ*@_C&N\R#Q19QCUA5%7&/6$44<8]8-1-QCU
|
||||
M@G$@034/5+7![7)4.40]8-0!1OU?U/U%O5_4^45]7]3U17UFU&5&/4O4948]
|
||||
MYD?^#Y:/>L:HLXGZQ:A;C&J+N$^.^L2H2XSZFZA#C/K#J(>,^L.H.XQZPZ@S
|
||||
MC/K"J"N,>L*HVXGZP:@;C'K!J!.,^L"H"XQZP*@#C+K?J/.)>L"H`XSZOZAJ
|
||||
MB7J_J,*':E*H^H'J/Z@BA&J'J%J(ZF:H\H?;_KAUK^KQJOJ[J+>+.KNJOBZJ
|
||||
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
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 // */
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 *
|
||||
@@ -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
|
||||
|
||||
@@ -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 *
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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).
|
||||
|
||||
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+84
-53
@@ -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 *);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,4 +0,0 @@
|
||||
source .gdbinit.kernel
|
||||
source .gdbinit.vinum.paths
|
||||
source .gdbinit.vinum
|
||||
asf
|
||||
@@ -1,5 +0,0 @@
|
||||
source .gdbinit.kernel
|
||||
source .gdbinit.vinum.paths
|
||||
source .gdbinit.vinum
|
||||
tr
|
||||
asf
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+4
-7
@@ -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
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -1,4 +0,0 @@
|
||||
PROG= memcontrol
|
||||
NOMAN= yes
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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>
|
||||
Reference in new issue
Block a user