diff options
31 files changed, 11235 insertions, 0 deletions
diff --git a/gnu/usr.bin/man/Makefile.shprog b/gnu/usr.bin/man/Makefile.shprog new file mode 100644 index 000000000000..665a194917ff --- /dev/null +++ b/gnu/usr.bin/man/Makefile.shprog @@ -0,0 +1,30 @@ +# $Id$ + +# This may become bsd.shprog.mk. The general version would have to handle: +# - arbitrary sed substitutions. +# - programs without man pages. +# - programs with man pages in sections other than section 1. + +MAN1= ${SHPROG:S/$/.1/g} + +CLEANFILES+= ${SHPROG} ${MAN1} + +all: ${SHPROG} + +.sh: + sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \ + -e 's,%pager%,${pager},' \ + ${.ALLSRC} > ${.TARGET} + +.SUFFIXES: .man .1 +.man.1: + sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \ + -e 's,%pager%,${pager},' -e 's,%troff%,${troff},' \ + -e 's,%manpath_config_file%,${manpath_config_file},' \ + ${.ALLSRC} > ${.TARGET} + +beforeinstall: + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${SHPROG} ${DESTDIR}${BINDIR} + +.include <bsd.prog.mk> diff --git a/lib/libc/sys/semctl.2 b/lib/libc/sys/semctl.2 new file mode 100644 index 000000000000..fe60ce048443 --- /dev/null +++ b/lib/libc/sys/semctl.2 @@ -0,0 +1,173 @@ +.\" +.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.com> +.\" +.\" 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 DEVELOPERS ``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 DEVELOPERS 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$ +.\" +.Dd September 12, 1995 +.Dt SEMCTL 2 +.Os FreeBSD +.Sh NAME +.Nm semctl +.Nd control operations on a semaphore set +.Sh SYNOPSIS +.Fd #include <sys/types.h> +.Fd #include <sys/ipc.h> +.Fd #include <sys/sem.h> +.Ft int +.Fn "semctl" "int semid" "int semnum" "int cmd" "union semun arg" +.Sh DESCRIPTION +.Fn Semctl +performs the operation indicated by +.Fa cmd +on the semaphore set indicated by +.Fa semid . +For the commands that use the +.Fa arg +parameter, +.Fa "union semun" +is defined as follows: +.Bd -literal +.\" +.\" From <sys/sem.h>: +.\" +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + u_short *array; /* array for GETALL & SETALL */ +}; +.Ed +.Pp +Commands are performed as follows: +.\" +.\" This section based on Stevens, _Advanced Programming in the UNIX +.\" Environment_. +.\" +.Bl -tag -width IPC_RMIDXXX +.It Dv IPC_STAT +Fetch the semaphore set's +.Fa "struct semid_ds" , +storing it in the memory pointed to by +.Fa arg.buf . +.It Dv IPC_SET +Changes the +.Fa sem_perm.uid , +.Fa sem_perm.gid , +and +.Fa sem_perm.mode +members of the semaphore set's +.Fa "struct semid_ds" +to match those of the struct pointed to by +.Fa arg.buf . +The calling process's effective uid must +match either +.Fa sem_perm.uid +or +.Fa sem_perm.cuid , +or it must have superuser privileges. +.It IPC_RMID +Immediately removes the semaphore set from the system. The calling +process's effictive uid must equal the semaphore set's +.Fa sem_perm.uid +or +.Fa sem_perm.cuid , +or the process must have superuser priviliges. +.It Dv GETVAL +Return the value of semaphore number +.Fa semnum . +.It Dv SETVAL +Set the value of semaphore number +.Fa semnum +to +.Fa arg.val . +.It Dv GETPID +Return the pid of the last process to perform an operation on +semaphore number +.Fa semnum . +.It Dv GETNCNT +Return the number of processes waiting for semaphore number +.Fa semnum Ns 's +value to become greater than its current value. +.It Dv GETZCNT +Return the number of processes waiting for semaphore number +.Fa semnum Ns 's +value to become 0. +.It Dv GETALL +Fetch the value of all of the semaphores in the set into the +array pointed to by +.Fa arg.array . +.It Dv SETALL +Set the values of all of the semaphores in the set to the values +in the array pointed to by +.Fa arg.array . +.El +.Pp +The +.Fa "struct semid_ds" +is defined as follows: +.Bd -literal +.\" +.\" Taken straight from <sys/sem.h>. +.\" +struct semid_ds { + struct ipc_perm sem_perm; /* operation permission struct */ + struct sem *sem_base; /* pointer to first semaphore in set */ + u_short sem_nsems; /* number of sems in set */ + time_t sem_otime; /* last operation time */ + long sem_pad1; /* SVABI/386 says I need this here */ + time_t sem_ctime; /* last change time */ + /* Times measured in secs since */ + /* 00:00:00 GMT, Jan. 1, 1970 */ + long sem_pad2; /* SVABI/386 says I need this here */ + long sem_pad3[4]; /* SVABI/386 says I need this here */ +}; +.Ed +.Sh RETURN VALUES +On success, when +.Fa cmd +is one of GETVAL, GETNCNT, or GETZCNT, +.Fn semctl +returns the corresponding value; otherwise, 0 is returned. +On failure, -1 is returned, and +.Va errno +is set to indicate the error. +.Sh ERRORS +.Fn Semctl +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +No semaphore set corresponds to +.Fa semid . +.It Bq Er EINVAL +.Fa semnum +is not in the range of valid semaphores for given semaphore set. +.It Bq Er EPERM +The calling process's effective uid does not match the uid of +the semaphore set's owner or creator. +.It Bq Er EACCES +Permission denied due to mismatch between operation and mode of +semaphore set. +.Sh SEE ALSO +.Xr semget 2 , +.Xr semop 2 diff --git a/lib/libc/sys/semget.2 b/lib/libc/sys/semget.2 new file mode 100644 index 000000000000..323aef47043d --- /dev/null +++ b/lib/libc/sys/semget.2 @@ -0,0 +1,137 @@ +.\" +.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.com> +.\" +.\" 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 DEVELOPERS ``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 DEVELOPERS 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$ +.\" +.Dd September 12, 1995 +.Dt SEMGET 2 +.Os FreeBSD +.Sh NAME +.Nm semget +.Nd obtain a semaphore id +.Sh SYNOPSIS +.Fd #include <sys/types.h> +.Fd #include <sys/ipc.h> +.Fd #include <sys/sem.h> +.Ft int +.Fn "semget" "key_t key" "int nsems" "int flag" +.Sh DESCRIPTION +Based on the values of +.Fa key +and +.Fa flag , +.Fn semget +returns the identifier of a newly created or previously existing +set of semaphores. +.\" +.\" This is copied verbatim from the shmget manpage. Perhaps +.\" it should go in a common manpage, such as .Xr ipc 2 +.\" +The key +is analogous to a filename: it provides a handle that names an +IPC object. There are three ways to specify a key: +.Bl -bullet +.It +IPC_PRIVATE may be specified, in which case a new IPC object +will be created. +.It +An integer constant may be specified. If no IPC object corresponding +to +.Fa key +is specified and the IPC_CREAT bit is set in +.Fa flag , +a new one will be created. +.It +.Fn ftok +may be used to generate a key from a pathname. See +.Xr ftok 3 . +.El +.\" +.\" Likewise for this section, except SHM_* becomes SEM_*. +.\" +.Pp +The mode of a newly created IPC object is determined by +.Em OR Ns 'ing +the following constants into the +.Fa flag +parameter: +.Bl -tag -width XSEM_WXX6XXX +.It Dv SEM_R +Read access for user. +.It Dv SEM_W +Write access for user. +.It Dv (SEM_R>>3) +Read access for group. +.It Dv (SEM_W>>3) +Write access for group. +.It Dv (SEM_R>>6) +Read access for other. +.It Dv (SEM_W>>6) +Write access for other. +.El +.Pp +If a new set of semaphores is being created, +.Fa nsems +is used to indicate the number of semaphores the set should contain. +Otherwise, +.Fa nsems +may be specified as 0. +.Sh RETURN VALUES +.Fn Semget +returns the id of a semaphore set if successful; otherwise, -1 +is returned and +.Va errno +is set to indicate the error. +.Sh ERRORS +.Fn Semget +will fail if: +.Bl -tag -width Er +.\" ipcperm could fail (we're opening to read and write, as it were) +.It Bq Er EACCES +Access permission failure. +.\" +.\" sysv_sem.c is quite explicit about these, so I'm pretty sure +.\" this is accurate +.\" +.It Bq Er EEXIST +IPC_CREAT and IPC_EXCL were specified, and a semaphore set +corresponding to +.Fa key +already exists. +.It Bq Er EINVAL +The number of semaphores requested exceeds the system imposed maximum +per set. +.It Bq Er ENOSPC +Insufficiently many semaphores are available. +.It Bq Er ENOSPC +The kernel could not allocate a +.Fa "struct semid_ds" . +.It Bq Er ENOENT +No semaphore set was found corresponding to +.Fa key , +and IPC_CREAT was not specified. +.Sh SEE ALSO +.Xr semctl 2 , +.Xr semop 2 diff --git a/lib/libc/sys/semop.2 b/lib/libc/sys/semop.2 new file mode 100644 index 000000000000..74fa01bc7f03 --- /dev/null +++ b/lib/libc/sys/semop.2 @@ -0,0 +1,192 @@ +.\" +.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.com> +.\" +.\" 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 DEVELOPERS ``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 DEVELOPERS 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$ +.\" +.Dd September 22, 1995 +.Dt SEMOP 2 +.Os FreeBSD +.Sh NAME +.Nm semop +.Nd atomic array of operations on a semaphore set +.Sh SYNOPSIS +.Fd #include <sys/types.h> +.Fd #include <sys/ipc.h> +.Fd #include <sys/sem.h> +.Ft int +.Fn "semop" "int semid" "struct sembuf array[]" "unsigned nops" +.Sh DESCRIPTION +.Fn Semop +atomically performs the array of operations indicated by +.Fa array +on the semaphore set indicated by +.Fa semid . +The length of +.Fa array +is indicated by +.Fa nops . +Each operation is encoded in a +.Fa "struct sembuf" , +which is defined as follows: +.Bd -literal +.\" +.\" From <sys/sem.h> +.\" +struct sembuf { + u_short sem_num; /* semaphore # */ + short sem_op; /* semaphore operation */ + short sem_flg; /* operation flags */ +}; +.Ed +.Pp +For each element in +.Fa array , +.Fa sem_op +and +.Fa sem_flg +determine an operation to be performed on semaphore number +.Fa sem_num +in the set. The values SEM_UNDO and IPC_NOWAIT may be +.Em OR Ns 'ed +into the +.Fa sem_flg +member in order to modify the behavior of the given operation. +.Pp +The operation performed depends as follows on the value of +.Fa sem_op : +.\" +.\" This section is based on the description of semop() in +.\" Stevens, _Advanced Programming in the UNIX Environment_. +.\" +.Bl -bullet +.It +When +.Fa sem_op +is positive, the semaphore's value is incremented by +.Fa sem_op Ns 's +value. If SEM_UNDO is specified, the semaphore's adjust on exit +value is decremented by +.Fa sem_op Ns 's +value. A positive value for +.Fa sem_op +generally corresponds to a process releasing a resource +associated with the semaphore. +.It +The behavior when +.Fa sem_op +is negative depends on the current value of the semaphore: +.Bl -bullet +.It +If the current value of the semaphore is greater than or equal to +the absolute value of +.Fa sem_op , +then the value is decremented by the absolute value of +.Fa sem_op . +If SEM_UNDO is specified, the semaphore's adjust on exit +value is incremented by the absolute value of +.Fa sem_op . +.It +If the current value of the semaphore is less than +.Fa sem_op Ns 's +value, one of the following happens: +.\" XXX a *second* sublist? +.Bl -bullet +.It +If IPC_NOWAIT was specifed, then +.Fn semop +returns immediately with a return value of EAGAIN. +.It +If some other process has removed the semaphore with the IPC_RMID +option of +.Fn semctl , +then +.Fn semop +returns immediately with a return value of EINVAL. +.It +Otherwise, the calling process is put to sleep until the semaphore's +value is greater than or equal to the absolute value of +.Fa sem_op . +When this condition becomes true, the semaphore's value is decremented +by the absolute value of +.Fa sem_op , +and the semaphore's adjust on exit value is incremented by the +absolute value of +.Fa sem_op . +.El +.Pp +A negative value for +.Fa sem_op +generally means that a process is waiting for a resource to become +available. +.El +.Pp +.It +When +.Fa sem_op +is zero, the process waits for the semaphore's value to become zero. +If it is already zero, the call to +.Fn semop +can return immediately. Otherwise, the calling process is put to +sleep until the semaphore's value becomes zero. +.El +.Pp +For each semaphore a process has in use, the kernel maintains an +`adjust on exit' value, as alluded to earlier. When a process +exits, either voluntarily or involuntarily, the adjust on exit value +for each semaphore is added to the semaphore's value. This can +be used to insure that a resource is released if a process terminates +unexpectedly. +.Sh RETURN VALUES +On success, +.Fn semop +returns 0; otherwise, -1 is returned and +.Va errno +is set to indicate the error. +.Sh ERRORS +.Fn Semop +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +No semaphore set corresponds to +.Fa semid . +.It Bq Er EACCES +Permission denied due to mismatch between operation and mode of +semaphore set. +.It Bq Er EAGAIN +The semaphore's value was less than +.Fa sem_op , +and IPC_NOWAIT was specified. +.It Bq Er E2BIG +Too many operations were specified. +.It Bq Er EFBIG +.\" +.\" I'd have thought this would be EINVAL, but the source says +.\" EFBIG. +.\" +.Fa sem_num +was not in the range of valid semaphores for the set. +.Sh SEE ALSO +.Xr semget 2 , +.Xr semctl 2 diff --git a/lib/libc/sys/shmat.2 b/lib/libc/sys/shmat.2 new file mode 100644 index 000000000000..587eebc6cb1d --- /dev/null +++ b/lib/libc/sys/shmat.2 @@ -0,0 +1,110 @@ +.\" +.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.com> +.\" +.\" 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 DEVELOPERS ``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 DEVELOPERS 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$ +.\" +.Dd August 2, 1995 +.Dt SHMAT 2 +.Os FreeBSD +.Sh NAME +.Nm shmat , +.Nm shmdt +.Nd attach or detach shared memory +.Sh SYNOPSIS +.Fd #include <sys/types.h> +.Fd #include <sys/ipc.h> +.Fd #include <sys/shm.h> +.Ft void * +.Fn "shmat" "int shmid" "void *addr" "int flag" +.Ft int +.Fn "shmdt" "void *addr" +.Sh DESCRIPTION +.Fn Shmat +attaches the shared memory segment identifed by +.Fa shmid +to the calling process's address space. The address where the segment +is attached is determined as follows: +.\" +.\" These are cribbed almost exactly from Stevens, _Advanced Programming in +.\" the UNIX Environment_. +.\" +.Bl -bullet +.It +If +.Fa addr +is 0, the segment is attached at an address selected by the +kernel. +.It +If +.Fa addr +is nonzero and SHM_RND is not specifed in +.Fa flag , +the segment is attached the specified address. +.It +If +.Fa addr +is specified and SHM_RND is specified, +.Fa addr +is rounded down to the nearest multiple of SHMLBA. +.El +.Pp +.Fn Shmdt +detaches the shared memory segment at the address specified by +.Fa addr +from the calling process's address space. +.Sh RETURN VALUES +Upon success, +.Fn shmat +returns the address where the segment is attached; otherwise, -1 +is returned and +.Va errno +is set to indicate the error. +.Pp +Upon success, +.Fn shmdt +returns 0; otherwise, -1 is returned and +.Va errno +is set to indicate the error. +.Sh ERRORS +.Fn Shmat +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +No shared memory segment was found corresponding to +.Fa shmid . +.It Bq Er EINVAL +.Fa addr +was not an acceptable address. +.El +.Pp +.Fn Shmdt +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa addr +does not point to a shared memory segment. +.Sh "SEE ALSO" +.Xr shmget 2 , +.Xr shmctl 2 diff --git a/lib/libc/sys/shmctl.2 b/lib/libc/sys/shmctl.2 new file mode 100644 index 000000000000..b1c5a4bdf6b2 --- /dev/null +++ b/lib/libc/sys/shmctl.2 @@ -0,0 +1,136 @@ +.\" +.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.com> +.\" +.\" 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 DEVELOPERS ``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 DEVELOPERS 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$ +.\" +.Dd July 17, 1995 +.Dt SHMCTL 2 +.Os FreeBSD +.Sh NAME +.Nm shmctl +.Nd shared memory control +.Sh SYNOPSIS +.Fd #include <sys/types.h> +.Fd #include <sys/ipc.h> +.Fd #include <sys/shm.h> +.Ft int +.Fn "shmctl" "int shmid" "int cmd" "struct shmid_ds *buf" +.Sh DESCRIPTION +Performs the action specified by +.Fa cmd +on the shared memory segment identified by +.Fa shmid : +.Bl -tag -width SHM_UNLOCKX +.It Dv IPC_STAT +Fetch the segment's +.Fa "struct shmid_ds" , +storing it in the memory pointed to by +.Fa buf . +.\" +.\" XXX need to make sure that this is correct for FreeBSD +.\" +.It Dv IPC_SET +Changes the +.Fa shm_perm.uid , +.Fa shm_perm.gid , +and +.Fa shm_perm.mode +members of the segment's +.Fa "struct shmid_ds" +to match those of the struct pointed to by +.Fa buf . +The calling process's effective uid must +match either +.Fa shm_perm.uid +or +.Fa shm_perm.cuid , +or it must have superuser privileges. +.It Dv IPC_RMID +Removes the segment from the system. The removal will not take +effect until all processes having attached the segment have exited; +however, once the IPC_RMID operation has taken place, no further +processes will be allowed to attach the segment. For the operation +to succeed, the calling process's effective uid must match +.Fa shm_perm.uid +or +.Fa shm_perm.cuid , +or the process must have superuser privilges. +.\" .It Dv SHM_LOCK +.\" Locks the segment in memory. The calling process must have +.\" superuser privileges. Not implemented in FreeBSD. +.\" .It Dv SHM_UNLOCK +.\" Unlocks the segment from memory. The calling process must +.\" have superuser priviliges. Not implemented in FreeBSD. +.El +.Pp +The +.Fa "shmid_ds" +struct is defined as follows: +.\" +.\" I fiddled with the spaces a bit to make it fit well when viewed +.\" with nroff, but otherwise it's straight from sys/shm.h +.\" +.Bd -literal +struct shmid_ds { + struct ipc_perm shm_perm; /* operation permission structure */ + int shm_segsz; /* size of segment in bytes */ + pid_t shm_lpid; /* process ID of last shared memory op */ + pid_t shm_cpid; /* process ID of creator */ + short shm_nattch; /* number of current attaches */ + time_t shm_atime; /* time of last shmat() */ + time_t shm_dtime; /* time of last shmdt() */ + time_t shm_ctime; /* time of last change by shmctl() */ + void *shm_internal; /* sysv stupidity */ +}; +.Ed +.Sh RETURN VALUES +Upon successful completion, +.Fn shmctl +returns 0. Otherwise, it returns -1 and +.Va errno +is set to indicate the error. +.Sh ERRORS +.Fn Shmctl +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +Invalid operation, or +no shared memory segment was found corresponding to +.Fa shmid . +.\" +.\" XXX I think the following is right: ipcperm() only returns EPERM +.\" when an attempt is made to modify (IPC_M) by a non-creator +.\" non-owner +.It Bq Er EPERM +The calling process's effective uid does not match the uid of +the shared memory segment's owner or creator. +.It Bq Er EACCES +Permission denied due to mismatch between operation and mode of +shared memory segment. +.Sh "SEE ALSO" +.Xr shmget 2 , +.Xr shmat 2 , +.Xr shmdt 2 , +.Xr ftok 3 diff --git a/lib/libc/sys/shmget.2 b/lib/libc/sys/shmget.2 new file mode 100644 index 000000000000..3df3272131cd --- /dev/null +++ b/lib/libc/sys/shmget.2 @@ -0,0 +1,138 @@ +.\" +.\" Copyright (c) 1995 David Hovemeyer <daveho@infocom.com> +.\" +.\" 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 DEVELOPERS ``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 DEVELOPERS 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$ +.\" +.Dd July 3, 1995 +.Dt SHMGET 2 +.Os FreeBSD +.Sh NAME +.Nm shmget +.Nd obtain a shared memory identifier +.Sh SYNOPSIS +.Fd #include <sys/types.h> +.Fd #include <sys/ipc.h> +.Fd #include <sys/shm.h> +.Ft int +.Fn "shmget" "key_t key" "int size" "int flag" +.Sh DESCRIPTION +Based on the values of +.Fa key +and +.Fa flag , +.Fn shmget +returns the identifier of a newly created or previously existing shared +memory segment. +.\" +.\" The following bit about keys and modes also applies to semaphores +.\" and message queues. +.\" +The key +is analogous to a filename: it provides a handle that names an +IPC object. There are three ways to specify a key: +.Bl -bullet +.It +IPC_PRIVATE may be specified, in which case a new IPC object +will be created. +.It +An integer constant may be specified. If no IPC object corresponding +to +.Fa key +is specified and the IPC_CREAT bit is set in +.Fa flag , +a new one will be created. +.It +.Fn ftok +may be used to generate a key from a pathname. See +.Xr ftok 3 . +.El +.Pp +The mode of a newly created IPC object is determined by +.Em OR Ns 'ing +the following constants into the +.Fa flag +parameter: +.Bl -tag -width XSHM_WXX6XXX +.It Dv SHM_R +Read access for user. +.It Dv SHM_W +Write access for user. +.It Dv (SHM_R>>3) +Read access for group. +.It Dv (SHM_W>>3) +Write access for group. +.It Dv (SHM_R>>6) +Read access for other. +.It Dv (SHM_W>>6) +Write access for other. +.El +.\" +.\" XXX - we should also mention how uid, euid, and gid affect ownership +.\" and use +.\" +.\" end section about keys and modes +.\" +.Pp +When creating a new shared memory segment, +.Fa size +indicates the desired size of the new segment in bytes. The size +of the segment may be rounded up to a multiple convenient to the +kernel (i.e., the page size). +.Sh RETURN VALUES +Upon successful completion, +.Fn shmget +returns the positive integer identifier of a shared memory segment. +Otherwise, -1 is returned and +.Va errno +set to indicate the error. +.Sh ERRORS +.Fn Shmget +will fail if: +.Bl -tag -width Er +.\" +.\" XXX What about ipcperm failing? +.\" +.It Bq Er EINVAL +Size specified is greater than the size of the previously existing segment. +Size specified is less than the system imposed minumum, or greater than +the system imposed maximum. +.It Bq Er ENOENT +No shared memory segment was found matching +.Fa key , +and IPC_CREAT was not specified. +.It Bq Er ENOSPC +The kernel was unable to allocate enough memory to +satisfy the request. +.It Bq Er EEXIST +IPC_CREAT and IPC_EXCL were specified, and a shared memory segment +corresponding to +.Fa key +already exists. +.Pp +.Sh "SEE ALSO" +.Xr shmctl 2 , +.Xr shmat 2 , +.Xr shmdt 2 , +.Xr ftok 3 diff --git a/release/MIRROR.SITES b/release/MIRROR.SITES new file mode 100644 index 000000000000..cc817e45b88b --- /dev/null +++ b/release/MIRROR.SITES @@ -0,0 +1,198 @@ +$Id$ + +Obtaining FreeBSD + + The official sources for FreeBSD available via anonymous FTP from: + + ftp://ftp.FreeBSD.org/pub/FreeBSD + + and on CD-ROM from Walnut Creek CDROM: + + Walnut Creek CDROM + 1547 Palos Verdes Mall, Suite 260 + Walnut Creek CA 94596 USA + Phone: +1 510 674-0783 + Fax: +1 510 674-0821 + Email: info@cdrom.com + WWW: http://www.cdrom.com/ + + + Additionally, FreeBSD is available via anonymous FTP from the + following mirror sites. If you choose to obtain FreeBSD via anonymous + FTP, please try to use a site near you. + + Australia + + + ftp://ftp.physics.usyd.edu.au/FreeBSD + Contact: dawes@xfree86.org. + + + ftp://minnie.cs.adfa.oz.au/FreeBSD + Contact: wkt@dolphin.cs.adfa.oz.au. + + Canada + + + ftp://ftp.synapse.net/contrib/FreeBSD + Contact: evanc@synapse.net. + + Finland + + + ftp://nic.funet.fi/pub/unix/FreeBSD + Contact: count@nic.funet.fi. + + France + + + ftp://ftp.ibp.fr/pub/FreeBSD + Contact: Remy.Card@ibp.fr. + + Germany + + + ftp://ftp.fb9dv.uni-duisburg.de/pub/unix/FreeBSD + Contact: ftp@ftp.fb9dv.uni-duisburg.de. + + + ftp://gil.physik.rwth-aachen.de/pub/FreeBSD + Contact: kuku@gil.physik.rwth-aachen.de. + + + ftp://ftp.uni-paderborn.de/freebsd + Contact: ftp@uni-paderborn.de. + + + ftp://ftp.leo.org/pub/comp/os/bsd/FreeBSD + Contact: bsd@leo.org. + + + ftp://ftp.tu-dresden.de/pub/soft/unix/bsd/FreeBSD + Contact: pdsowner@rcs1.urz.tu-dresden.de. + + Ireland + + + ftp://ftp.internet-eireann.ie/pub/FreeBSD + Contact: ftpadmin@internet-eireann.ie. + + Israel + + + + ftp://orgchem.weizmann.ac.il/pub/FreeBSD + Contact: serg@klara.weizmann.ac.il. + + Hong Kong + + + ftp://ftp.hk.super.net/pub/FreeBSD + Contact: ftp-admin@HK.Super.NET. + + Korea + + + ftp://ftp.cau.ac.kr/pub/FreeBSD + Contact: ftpadm@ftp.cau.ac.kr. + + Netherlands + + + ftp://ftp.nl.net/pub/os/FreeBSD + Contact: archive@nl.net. + + Russia + + + ftp://ftp.kiae.su/FreeBSD + Contact: ftp@ftp.kiae.su. + + Sweden + + + ftp://ftp.luth.se/pub/FreeBSD + Contact: ragge@ludd.luth.se. + + Taiwan + + + ftp://NCTUCCCA.edu.tw/Operating-Systems/FreeBSD + Contact: freebsd@NCTUCCCA.edu.tw. + + + ftp://netbsd.csie.nctu.edu.tw/pub/FreeBSD + Contact: ftp@netbsd.csie.nctu.edu.tw. + + Thailand + + + ftp://ftp.nectec.or.th/pub/FreeBSD + Contact: ftpadmin@ftp.nectec.or.th. + + USA + + + ftp://gatekeeper.dec.com/pub/BSD/FreeBSD + Contact: hubbard@gatekeeper.dec.com. + + + ftp://ftp.cybernetics.net/pub/FreeBSD + Contact: michael@Cybernetics.NET. + + + ftp://ftp.neosoft.com/systems/FreeBSD + Contact: smace@NeoSoft.COM. + + + ftp://kryten.atinc.com/pub/FreeBSD + Contact: jmb@kryten.atinc.com. + + + ftp://ftp.dataplex.net/pub/FreeBSD + Contact: rkw@dataplex.net. + + + ftp://ftp.cps.cmich.edu/pub/ftp.freebsd.org + Contact: ftpadmin@cps.cmich.edu. + + + ftp://ftp.cslab.vt.edu/pub/FreeBSD + Contact: ftp@ftp.cslab.vt.edu. + + Japan + + + ftp://ftp.tokyonet.ad.jp/pub/FreeBSD + Contact: ftpadmin@TokyoNet.AD.JP. + + + ftp://ftp.tut.ac.jp/FreeBSD + Contact: ashida@ftp.tut.ac.jp. + + + ftp://ftp.sra.co.jp/pub/os/FreeBSD + Contact: ftp-admin@sra.co.jp. + + + ftp://ftp.ee.uec.ac.jp/pub/os/mirror/ftp.freebsd.org + Contact: ftp-admin@ftp.ee.uec.ac.jp. + + + ftp://ftp.mei.co.jp/free/PC-UNIX/FreeBSD + Contact: tanig@isl.mei.co.jp. + + + ftp://ftp.waseda.ac.jp/pub/FreeBSD + Contact: ftp-admin@waseda.ac.jp. + + + ftp://ftp.pu-toyama.ac.jp/pub/FreeBSD + Contact: Yoshihiko USUI usui@pu-toyama.ac.jp. + + + ftp://ftpsv1.u-aizu.ac.jp/pub/os/FreeBSD + Contact: ftp-admin@u-aizu.ac.jp. + + UK + + + ftp://src.doc.ic.ac.uk/packages/unix/FreeBSD + Contact: wizards@doc.ic.ac.uk. + + + ftp://unix.hensa.ac.uk/pub/walnut.creek/FreeBSD + Contact: archive-admin@unix.hensa.ac.uk. + + + ftp://ftp.demon.co.uk/pub/BSD/FreeBSD + Contact: uploads@demon.net. + + + + The latest versions of export-restricted code for FreeBSD (2.0C or + later) (eBones and secure) are being made available at the following + locations. If you are outside the U.S. or Canada, please get secure + (DES) and eBones (Kerberos) from one of the following foreign + distribution sites: + + SouthAfrica + + + ftp://ftp.internat.freebsd.org/pub/FreeBSD + Contact: Mark Murray mark@grondar.za. + + + ftp://storm.sea.uct.ac.za/pub/FreeBSD + Contact: Shaun Courtney ftp@storm.sea.uct.ac.za. + + Brazil + + + ftp://ftp.iqm.unicamp.br/pub/FreeBSD + Contact: Pedro A M Vazquez vazquez@iqm.unicamp.br. + + Finland + + + ftp://nic.funet.fi/pub/unix/FreeBSD/eurocrypt + Contact: count@nic.funet.fi. + diff --git a/sbin/startslip/uucplock.c b/sbin/startslip/uucplock.c new file mode 100644 index 000000000000..20a823915da9 --- /dev/null +++ b/sbin/startslip/uucplock.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1988, 1993 + * 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 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 the University of + * California, Berkeley and its contributors. + * 4. 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 BY THE REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/dir.h> +#include <errno.h> +#include <syslog.h> +#include <unistd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <paths.h> + +#define LOCKFMT "LCK..%s" + +/* Forward declarations */ +static int put_pid (int fd, pid_t pid); +static pid_t get_pid (int fd); + +/* + * uucp style locking routines + * return: 0 - success + * -1 - failure + */ + +int uu_lock (char *ttyname) +{ + int fd; + pid_t pid; + char tbuf[MAXNAMLEN]; + + (void)sprintf(tbuf, _PATH_UUCPLOCK LOCKFMT, ttyname); + fd = open(tbuf, O_RDWR|O_CREAT|O_EXCL, 0660); + if (fd < 0) { + /* + * file is already locked + * check to see if the process holding the lock still exists + */ + fd = open(tbuf, O_RDWR, 0); + if (fd < 0) { + syslog(LOG_ERR, "lock open: %m"); + return(-1); + } + if ((pid = get_pid (fd)) == -1) { + syslog(LOG_ERR, "lock read: %m"); + (void)close(fd); + return(-1); + } + + if (kill(pid, 0) == 0 || errno != ESRCH) { + (void)close(fd); /* process is still running */ + return(-1); + } + /* + * The process that locked the file isn't running, so + * we'll lock it ourselves + */ + if (lseek(fd, 0L, L_SET) < 0) { + syslog(LOG_ERR, "lock lseek: %m"); + (void)close(fd); + return(-1); + } + /* fall out and finish the locking process */ + } + pid = getpid(); + if (!put_pid (fd, pid)) { + syslog(LOG_ERR, "lock write: %m"); + (void)close(fd); + (void)unlink(tbuf); + return(-1); + } + (void)close(fd); + return(0); +} + +int uu_unlock (char *ttyname) +{ + char tbuf[MAXNAMLEN]; + + (void)sprintf(tbuf, _PATH_UUCPLOCK LOCKFMT, ttyname); + return(unlink(tbuf)); +} + +static int put_pid (int fd, pid_t pid) +{ + char buf [32]; + int len; + + len = sprintf (buf, "%10ld\n", pid); + return write (fd, buf, len) == len; +} + +static pid_t get_pid (int fd) +{ + int bytes_read; + char buf [32]; + pid_t pid; + + bytes_read = read (fd, buf, sizeof (buf) - 1); + if (bytes_read > 0) { + buf [bytes_read] = '\0'; + pid = strtol (buf, (char **) NULL, 10); + } + else + pid = -1; + return pid; +} + +/* end of uucplock.c */ diff --git a/share/doc/handbook/crypt.sgml b/share/doc/handbook/crypt.sgml new file mode 100644 index 000000000000..2efe3504cdaa --- /dev/null +++ b/share/doc/handbook/crypt.sgml @@ -0,0 +1,80 @@ +<!-- $Id$ --> +<!-- The FreeBSD Documentation Project --> + +<sect><heading>DES, MD5, and Crypt<label id="crypt"></heading> + +<p><em>Contributed by &a.wollman;<newline>24 September 1995.</em> + +<p><bf>History</bf> + +<p>In order to protect the security of passwords on UN*X systems from +being easily exposed, passwords have traditionally been scrambled in +some way. Starting with Bell Labs' Seventh Edition Unix, passwords +were encrypted using what the security people call a ``one-way hash +function''. That is to say, the password is transformed in such a way +that the original password cannot be regained except by brute-force +searching the space of possible passwords. Unfortunately, the only +secure method that was available to the AT&T researchers at the +time was based on DES, the Data Encryption Standard. This causes only +minimal difficulty for commercial vendors, but is a serious problem +for an operating system like FreeBSD where all the source code is +freely available, because national governments in many places like to +place restrictions on cross-border transport of DES and other +encryption software. + +<p>So, the FreeBSD team was faced with a dilemma: how could we provide +compatibility with all those UNIX systems out there while still not +running afoul of the law? We decided to take a dual-track approach: +we would make distributions which contained only a non-regulated +password scrambler, and then provide as a separate add-on library the +DES-based password hash. The password-scrambling function was moved +out of the C library to a separate library, called `<tt>libcrypt</tt>' +because the name of the C function to implement it is +`<tt>crypt</tt>'. In FreeBSD 1.x and some pre-release 2.0 snapshots, +the non-regulated scrambler uses an insecure function written by Nate +Williams; in subsequent releases this was replaced by a mechanism +using the RSA Data Security, Inc., MD5 one-way hash function. Because +neither of these functions involve encryption, they are believed to be +exportable from the US and importable into many other countries. + +<p>Meanwhile, work was also underway on the DES-based password hash +function. First, a version of the `<tt>crypt</tt>' function which was +written outside the US was imported, thus synchronizing the US and +non-US code. Then, the library was modified and split into two; the +DES `<tt>libcrypt</tt>' contains only the code involved in performing +the one-way password hash, and a separate `<tt>libcipher</tt>' was +created with the entry points to actually perform encryption. The +code was partitioned in this way to make it easier to get an export +license for the compiled library. + +<p><bf>Recognizing your `<tt>crypt</tt>' mechanism</bf> + +<p>It is fairly easy to recognize whether a particular password +string was created using the DES- or MD5-based hash function. +MD5 password strings always begin with the characters +`<tt>$1$</tt>'. DES password strings do not have +any particular identifying characteristics, but they are shorter +than MD5 passwords, and are coded in a 64-character alphabet +which does not include the `<tt>$</tt>' character, so a +relatively short string which doesn't begin with a dollar sign is +very likely a DES password. + +<p>Determining which library is being used on your system is fairly +easy for most programs, except for those like `<tt>init</tt>' which +are statically linked. (For those programs, the only way is to try +them on a known password and see if it works.) Programs which use +`<tt>crypt</tt>' are linked against `<tt>libcrypt</tt>', which for +each type of library is a symbolic link to the appropriate +implementation. For example, on a system using the DES versions: + +<tscreen><verb> +$ cd /usr/lib +$ ls -l /usr/lib/libcrypt* +lrwxr-xr-x 1 bin bin 13 Sep 5 12:50 libcrypt.a -> libdescrypt.a +lrwxr-xr-x 1 bin bin 18 Sep 5 12:50 libcrypt.so.2.0 -> libdescrypt.so.2.0 +lrwxr-xr-x 1 bin bin 15 Sep 5 12:50 libcrypt_p.a -> libdescrypt_p.a +</verb></tscreen> + +On a system using the MD5-based libraries, the same links will be +present, but the target will be `<tt>libscrypt</tt>' rather than +`<tt>libdescrypt</tt>'. diff --git a/share/doc/handbook/dma.sgml b/share/doc/handbook/dma.sgml new file mode 100644 index 000000000000..a6628f42e9c1 --- /dev/null +++ b/share/doc/handbook/dma.sgml @@ -0,0 +1,105 @@ +<!-- $Id$ --> +<!-- The FreeBSD Documentation Project --> + +<sect><heading>PC DMA<label id="dma"></heading> + +<p><em>Contributed by &a.uhclem;.<newline> + 31 August 1995.</em> + +Posted to <htmlurl url="mailto:hackers@freebsd.org" + name="freebsd-hackers@freebsd.org">: +<quote> +<p><em>Yes, as long as `single mode' is appropriate for you, there's no need +to worry about TC. TC is intented for continuous mode. Well, i've +just noticed that the PC DMAC cannot even generate an interrupt when +ready... hmm, go figure, the Z80 DMAC did it.</em> +<p><em>And yes, for `single mode', the masking trick will do it. The +peripheral device will issue a DRQ signal for each transfered +byte/word, and masking would prevent the DMAC from accepting new DRQs +for this channel. Aborting a continuous mode transfer would not be so +easy (or even impossible at all).</em> +</quote> + +Actually, masking is the correct procedure for all transfer modes on the +8237, even autoinit mode, which is frequently used for audio operations +since it allows seamless DMA transfers with no under/overruns. + +You are generally correct about TC. All the TC signal does is +when the counter on any channel in the DMA controller goes from +one to zero, TC is asserted. What the peripherals are supposed +to if they want to generate an interrupt when the transfer is +through, is that peripheral device is supposed to look at +<tt>(-DACK%d && TC && DEVICE_DMA_ACTIVE)</tt> and then +latch an <tt>IRQ%d</tt> for the 8259 interrupt controller. Since there is +only one TC signal, it is important that only the peripheral who +is transferring data at that moment honor the TC signal. + +The host CPU will eventually investigate the interrupt by having some driver +poll the hardware associated with the peripheral, NOT the DMA controller. +If a peripheral doesn't want an interrupt associated with the DMA counter +reaching zero, it doesn't implement the circuitry to monitor TC. + +Some sound cards realize that when the TC hits zero it means the DMA +is now idle and that is really too late, so they don't use TC and +instead allow the driver to program in a local counter value, which +is usually set lower than the value programmed into the DMA. This means +the peripheral can interrupt the CPU in advance of the DMA "running dry", +allowing the CPU to be ready to reprogram the DMA the instant it finishes +what it is doing, rather than incurring the latency later. + +This also means that two or more different devices could share a +DMA channel, by tristating <tt>DRQ%d</tt> when idle and only +honoring <tt>-DACK%d</tt> when the device knows it is expecting +the DMA to go active. (Iomega PC2B boards forgot this minor +point and will transfer data even if they are not supposed to.) + + +So, if you want to abort a 8237 DMA transfer of any kind, simply mask the +bit for that DMA channel in the 8237. Note: You can't interrupt an individual +transfer (byte or burst) in progress. Think about it... if the DMA is +running, how is your OUT instruction going to be performed? +The CPU has to be bus master for the OUT to be performed. + +Since the 8237 DMA re-evaluates DMA channel priorities constantly, even if +the DMA had already asserted HOLD (to request the bus from the CPU) when +the OUT actually took place, the processor would still grant the bus to the +DMA controller. The DMA controller would look for the highest-priority +DMA source remaining (your interrupt is masked now) at that instant, +and if none remained, the DMA will release HOLD and the processor will +get the bus back after a few clocks. + +There is a deadly race condition in this area, but if I remember right, +you can't get into it via mis-programming the DMA, UNLESS you cause the DMA +controller to be RESET. You should not do this. Effectively the CPU +can give up the bus and the DMA doesn't do anything, including giving the +bus back. Very annoying and after 16msec or so, all is over since +refresh on main memory has started failing. + +So, mask the DMA controller, then go do what you have to do to get the +transfer aborted in the peripheral hardware. In some extremely stupid +hardware (I could mention a few), you may have to program the DMA to +transfer one more byte to a garbage target to get the peripheral hardware +to go back to an idle state. Most hardware these days isn't that +stupid. + +Technically, you are supposed to mask the DMA channel, program the other +settings (direction, address, length, etc), issue commands to the +peripheral and then unmask the DMA channel once the peripheral commands have +been accepted. The last two steps can be done out of order without +harm, but you must always program the DMA channel while it is masked to +avoid spraying data all over the place in the event the peripheral +unexpected asserts <tt>DRQ%d</tt>. + +If you need to pad-out an aborted buffer, once you have masked the +DMA, you can ask it how many bytes it still had to go and what +address it was to write to next. Your driver can then fill in the +remaining area or do what needs to be done. + + +Don't forget that the 8237 was designed for use with the 8085 and +really isn't suited to the job that IBM gave it in the original PC. +That's why the upper eight bits of DMA addressing appear to be lashed-on. +They are. Look at the schematics of the original PC and you will +the upper bits are kept in external latches that are enabled whenever +the DMA is too. Very kludgy. + diff --git a/share/doc/handbook/esdi.sgml b/share/doc/handbook/esdi.sgml new file mode 100644 index 000000000000..6d2c3dee5df4 --- /dev/null +++ b/share/doc/handbook/esdi.sgml @@ -0,0 +1,421 @@ +<!-- $Id: esdi.sgml,v 1.1 1995/09/25 04:53:30 jfieber Exp $ --> +<!-- The FreeBSD Documentation Project --> + +<!-- + <title>An introduction to ESDI hard disks and their use with FreeBSD</title> + <author>(c) 1995, Wilko Bulte, <tt/wilko@yedi.iaf.nl/ + <date>Tue Sep 12 20:48:44 MET DST 1995</date> + + Copyright 1995, Wilko C. Bulte, Arnhem, The Netherlands + + <abstract> + This document describes the use of ESDI disks in combination + with the FreeBSD operating system. Contrary to popular + belief, this is possible and people are using ESDI based + systems succesfully! This document tries to explain you + how to do this. + + If you find something missing, plain wrong or have useful + comments on how to improve + the document please send mail to <tt/wilko@yedi.iaf.nl/ + </abstract> +--> + + <sect><heading>ESDI hard disks and FreeBSD<label id="esdi"></heading> + + <p><em>Copyright © 1995, &a.wilko;.<newline>24 September 1995.</em> + + ESDI is an acronym that means Enhanced Small Device Interface. + It is loosely based on the good old ST506/412 interface originally + devised by Seagate Technology, the makers of the first affordable + 5.25" winchester disk. + + The acronym says Enhanced, and rightly so. In the first place + the speed of the interface is higher, 10 or 15 Mbits/second + instead of the 5 Mbits/second of ST412 interfaced drives. + Secondly some higher level commands are added, making the ESDI + interface somewhat 'smarter' to the operating system driver + writers. It is by no means as smart as SCSI by the way. ESDI + is standardised by ANSI. + + Capacities of the drives are boosted by putting more sectors + on each track. Typical is 35 sectors per track, high capacity + drives I've seen were up to 54 sectors/track. + + Although ESDI has been largely obsoleted by IDE and SCSI interfaces, + the availability of free or cheap surplus drives makes them + ideal for low (or now) budget systems. + + <sect1><heading>Concepts of ESDI</heading> + <p> + <sect2><heading>Physical connections</heading> + <p> + The ESDI interface uses two cables connected to each drive. + One cable is a 34 pin flatcable edge connector that carries + the command and status signals from the controller to the + drive and viceversa. The command cable is daisy chained + between all the drives. So, it forms a bus onto which all + drives are connected. + + The second cable is a a 20 pin flatcable edge connector that + carries the data to and from the drive. This cable is radially + connected, so each drive has it's own direct connection to the + controller. + + To the best of my knowledge PC ESDI controllers are limited + to using a maximum of 2 drives per controller. This is + compatibility feature(?) left over from the WD1003 standard + that reserves only a single bit for device addressing. + + <sect2><heading>Device addressing</heading> + <p> + On each command cable a maximum of 7 devices and 1 controller + can be present. To enable the controller to uniquely + identify which drive it addresses, each ESDI device is equipped + with jumpers or switches to select the devices address. + + On PC type controllers the first drive is set to address 0, + the second disk to address 1. <it>Always make sure</it> you + set each disk to an unique address! So, on a PC with it's + two drives/controller maximum the first drive is drive 0, the + second is drive 1. + + <sect2><heading>Termination</heading> + <p> + The daisy chained command cable (the 34 pin cable remember?) + needs to be terminated at the last drive on the chain. + For this purpose ESDI drives come with a termination resistor + network that can be removed or disabled by a jumper when it + is not used. + + So, one and <it>only</it> one drive, the one at + the fartest end of the command + cable has it's terminator installed/enabled. The controller + automatically terminates the other end of the cable. + Please note that this implies that the controller must be + at one end of the cable and <it>not</it> in the middle. + + <sect1><heading>Using ESDI disks with FreeBSD</heading> + <p> + Why is ESDI such a pain to get working in the first place? + + People who tried ESDI disks with FreeBSD are known to have + developed a profound sense of frustration. A combination of + factors works against you to produce effects that are + hard to understand when you have never seen them before. + + This has also led to the popular legend ESDI and FreeBSD + is a plain NO-GO. + The following sections try to list all the pitfalls and + solutions. + + <sect2><heading>ESDI speed variants</heading> + <p> + As briefly mentioned before, ESDI comes in two speed flavours. + The older drives and controllers use a 10 Mbits/second + data transfer rate. Newer stuff uses 15 Mbits/second. + + It is not hard to imagine that 15 Mbits/second drive cause + problems on controllers laid out for 10 Mbits/second. + As always, consult your controller <it>and</it> drive + documentation to see if things match. + + <sect2><heading>Stay on track</heading> + <p> + Mainstream ESDI drives use 34 to 36 sectors per track. + Most (older) controllers cannot handle more than this + number of sectors. + Newer, higher capacity, drives use higher numbers of sectors + per track. For instance, I own a 670 Mb drive that has + 54 sectors per track. + + In my case, the controller could not handle this number + of sectors. It proved to work well except that it only + used 35 sectors on each track. This meant losing a + lot of diskspace. + + Once again, check the documentation of your hardware for + more info. Going out-of-spec like in the example might + or might not work. Give it a try or get another more + capable controller. + + <sect2><heading>Hard or soft sectoring</heading> + <p> + Most ESDI drives allow hard or soft sectoring to be + selected using a jumper. Hard sectoring means that the + drive will produce a sector pulse on the start of each + new sector. The controller uses this pulse to tell when + it should start to write or read. + + Hard sectoring allows a selection of sector size (normally + 256, 512 or 1024 bytes per formatted sector). FreeBSD uses + 512 byte sectors. The number of sectors per track also varies + while still using the same number of bytes per formatted sector. + The number of <em>unformatted</em> bytes per sector varies, + dependent on your controller it needs more or less overhead + bytes to work correctly. Pushing more sectors on a track + of course gives you more usable space, but might give + problems if your controller needs more bytes than the + drive offers. + + In case of soft sectoring, the controller itself determines + where to start/stop reading or writing. For ESDI + hard sectoring is the default (at least on everything + I came across). I never felt the urge to try soft sectoring. + + In general, experiment with sector settings before you install + FreeBSD because you need to re-run the low-level format + after each change. + + <sect2><heading>Low level formatting</heading> + <p> + ESDI drives need to be low level formatted before they + are usable. A reformat is needed whenever you figgle + with the number of sectors/track jumpers or the + physical orientation of the drive (horizontal, vertical). + So, first think, then format. + The format time must not be underestimated, for big + disks it can take hours. + + After a low level format, a surface scan is done to + find and flag bad sectors. Most disks have a + manufacturer bad block list listed on a piece of paper + or adhesive sticker. In addition, on most disks the + list is also written onto the disk. + Please use the manufacturer's list. It is much easier + to remap a defect now than after FreeBSD is installed. + + Stay away from low-level formatters that mark all + sectors of a track as bad as soon as they find one + bad sector. Not only does this waste space, it also + and more importantly causes you grief with bad144 + (see the section on bad144). + + <sect2><heading>Translations</heading> + <p> + Translations, although not exclusively a ESDI-only problem, + might give you real trouble. + Translations come in multiple flavours. Most of them + have in common that they attempt to work around the + limitations posed upon disk geometries by the original + IBM PC/AT design (thanks IBM!). + + First of all there is the (in)famous 1024 cylinder limit. + For a system to be able to boot, the stuff (whatever + operating system) must be in the first 1024 cylinders + of a disk. Only 10 bits are available to encode the + cylinder number. For the number of sectors the limit + is 64 (0-63). + When you combine the 1024 cylinder limit with the 16 head + limit (also a design feature) you max out at fairly limited + disk sizes. + + To work around this problem, the manufacturers of ESDI + PC controllers added a BIOS prom extension on their boards. + This BIOS extension handles disk I/O for booting (and for + some operating systems <it>all</it> disk I/O) by using + translation. For instance, a big drive might be presented + to the system as having 32 heads and 64 sectors/track. + The result is that the number of cylinders is reduced to + something below 1024 and is therefore usable by the system + without problems. + It is noteworthy to know that FreeBSD after it's kernel has + started no longer uses the BIOS. More on this later. + + A second reason for translations is the fact that most + older system BIOSes could only handle drives with 17 sectors + per track (the old ST412 standard). Newer system BIOSes + usually have a user-defined drive type (in most cases this is + drive type 47). + + <em>Whatever you do to translations after reading this document, + keep in mind that if you have multiple operating systems on the + same disk, all must use the same translation</em> + + While on the subject of translations, I've seen one controller + type (but there are probably more like this) offer the option + to logically split a drive in multiple partitions as a BIOS + option. I had select 1 drive == 1 partition because this + controller wrote this info onto the disk. On powerup it + read the info and presented itself to the system based on + the info from the disk. + + <sect2><heading>Spare sectoring</heading> + <p> + Most ESDI controllers offer the possibility to remap bad sectors. + During/after the low-level format of the disk bad sectors are + marked as such, and a replacement sector is put in place + (logically of course) of the bad one. + + In most cases the remapping is done by using N-1 sectors on + each track for actual datastorage, and sector N itself is + the spare sector. N is the total number of sectors physically + available on the track. + The idea behind this is that the operating system sees + a 'perfect' disk without bad sectors. In the case of + FreeBSD this concept is not usable. + + The problem is that the translation from <it>bad</it> to <it>good</it> + is performed by the BIOS of the ESDI controller. FreeBSD, + being a true 32 bit operating system, does not use the BIOS + after it has been booted. Instead, it has device drivers that + talk directly to the hardware. + + <em>So: don't use spare sectoring, bad block remapping or + whatever it may be called by the controller manufacturer when you + want to use the disk for FreeBSD.</em> + + <sect2><heading>Bad block handling</heading> + <p> + The preceding section leaves us with a problem. The controller's + bad block handling is not usable and still FreeBSD's filesystems + assume perfect media without any flaws. + To solve this problem, FreeBSD use the <it>bad144</it> tool. + Bad144 (named after a Digital Equipment standard for bad block + handling) scans a FreeBSD slice for bad blocks. Having found + these bad blocks, it writes a table with the offending block + numbers to the end of the FreeBSD slice. + + When the disk is in operation, the diskaccesses are checked + against the table read from the disk. Whenever a blocknumber + is requested that is in the bad144 list, a replacement block + (also from the end of the FreeBSD slice) is used. + In this way, the bad144 replacement scheme presents 'perfect' + media to the FreeBSD filesystems. + + There are a number of potential pitfalls associated with + the use of bad144. + First of all, the slice cannot have more than 126 bad sectors. + If your drive has a high number of bad sectors, you might need + to divide it into multiple FreeBSD slices each containing less + than 126 bad sectors. Stay away from low-level format programs + that mark <em>every</em> sector of a track as bad when + they find a flaw on the track. As you can imagine, the + 126 limit is quickly reached when the low-level format is done + this way. + + Second, if the slice contains the root filesystem, the slice + should be within the 1024 cylinder BIOS limit. During the + boot process the bad144 list is read using the BIOS and this + only succeeds when the list is within the 1024 cylinder limit. + <em>Note</em> that the restriction is not that only the root + <em>filesystem</em> must be within the 1024 cylinder limit, but + rather the entire <em>slice</em> that contains the root filesystem. + + + <sect2><heading>Kernel configuration</heading> + <p> + ESDI disks are handled by the same <it>wd</it>driver as + IDE and ST412 MFM disks. The <it>wd</it> driver should work + for all WD1003 compatible interfaces. + + Most hardware is jumperable for one of two different I/O + address ranges and IRQ lines. This allows you to have + two wd type controllers in one system. + + When your hardware allows non-standard strappings, you + can use these with FreeBSD as long as you enter the + correct info into the kernel config file. + An example from the kernel config file (they live in + <tt>/sys/i386/conf</tt> BTW). + +<tscreen><verb> +# First WD compatible controller +controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr +disk wd0 at wdc0 drive 0 +disk wd1 at wdc0 drive 1 + +# Second WD compatible controller +controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr +disk wd2 at wdc1 drive 0 +disk wd3 at wdc1 drive 1 +</verb></tscreen> + +<!-- + <sect2><heading>Tuning your ESDI kernel setup</heading> + <p> +--> + + <sect1><heading>Particulars on ESDI hardware</heading> + <p> + <sect2><heading>Adaptec 2320 controllers</heading> + <p> + I succesfully installed FreeBSD onto a ESDI disk controlled by a + ACB-2320. No other operating system was present on the disk. + + To do so I low level formatted the disk using NEFMT.EXE + (<it>ftp</it>able from <it>www.adaptec.com</it>) and answered NO + to the question whether the disk should be formatted with a + spare sector on each track. The BIOS on the ACD-2320 was + disabled. I used the 'free configurable' option in the system + BIOS to allow the BIOS to boot it. + + Before using NEFMT.EXE I tried to format the disk using the + ACB-2320 BIOS builtin formatter. This proved to be a showstopper, + because it didn't give me an option to disable spare sectoring. + With spare sectoring enabled the FreeBSD installation + process broke down on the bad144 run. + + Please check carefully which ACB-232xy variant you have. The + x is either 0 or 2, indicating a controller without or with + a floppy controller on board. + + The y is more interesting. It can either be a blank, + a "A-8" or a "D". A blank indicates a plain 10 Mbits/second + controller. An "A-8" indicates a 15 Mbits/second controller + capable of handling 52 sectors/track. + A "D" means a 15 Mbits/second controller that can also + handle drives with > 36 sectors/track (also 52 ?). + + All variations should be capable of using 1:1 interleaving. Use 1:1, + FreeBSD is fast enough to handle it. + + <sect2><heading>Western Digital WD1007 controllers</heading> + <p> + I succesfully installed FreeBSD onto a ESDI disk controlled by a + WD1007 controller. To be precise, it was a WD1007-WA2. Other + variations of the WD1007 do exist. + + To get it to work, I had to disable the sector translation and + the WD1007's onboard BIOS. This implied I could not use + the low-level formatter built into this BIOS. Instead, I grabbed + WDFMT.EXE from www.wdc.com Running this formatted my drive + just fine. + + <sect2><heading>Ultrastor U14F controllers</heading> + <p> + According to multiple reports from the net, Ultrastor ESDI + boards work OK with FreeBSD. I lack any further info on + particular settings. + +<!-- + + <sect1><heading>Tracking down problems</heading> + <p> +--> + + <sect1><heading>Further reading<label id="esdi:further-reading"></> + <p> + If you intend to do some serious ESDI hacking, you might want to + have the official standard at hand: + + The latest ANSI X3T10 committee document is: + <itemize> +<item>Enhanced Small Device Interface (ESDI) [X3.170-1990/X3.170a-1991] + [X3T10/792D Rev 11] + </itemize> + On Usenet the newsgroup <htmlurl url="news:comp.periphs" + name="comp.periphs"> is a noteworthy place to look + for more info. + + The World Wide Web (WWW) also proves to be a very handy info source: + For info on Adaptec ESDI controllers see <htmlurl + url="http://www.adaptec.com/">. + For info on Western Digital controllers see <htmlurl + url="http://www.wdc.com/">. + + <sect1>Thanks to... + <p> + Andrew Gordon for sending me an Adaptec 2320 controller and ESDI disk + for testing. + diff --git a/share/doc/handbook/firewalls.sgml b/share/doc/handbook/firewalls.sgml new file mode 100644 index 000000000000..6a63a53bf853 --- /dev/null +++ b/share/doc/handbook/firewalls.sgml @@ -0,0 +1,525 @@ +<!-- $Id$ --> +<!-- The FreeBSD Documentation Project --> + +<sect><heading>Firewalls<label id="firewalls"></heading> + +<p><em>Contributed by &a.gpalmer;.<newline>4th of October 1995</em> + +Firewalls are an area of increasing interest for people who are +connected to the Internet, and are even finding applications on +private networks to provide enhanced security. This section will +hopefully explain what firewalls are, how to use them, and how to use +the facilities provided in the FreeBSD kernel to impliment them. + +<quote><bf>Note</bf>: People often think that having a firewall between +your companies internal network and the ``Big Bad Internet'' will +solve all your security problems. It may help, but a poorly setup +firewall system is more of a security risk than not having one at all. +A firewall can only add another layer of security to your systems, but +they will not be able to stop a really determined hacker from +penetrating your internal network. If you let internal security lapse +because you believe your firewall to be impenetrable, you have just +made the hackers job that bit easier.</quote> + +<sect1><heading>What is a firewall?</heading> + +<p>There are currently two distinct types of firewalls in common +use on the Internet today. The first type is more properly called +a <bf>packet filtering router</bf>, where the kernel on a +multi-homed machine chooses whether to forward or block packets +based on a set of rules. The second type, known as <bf>proxy +servers</bf>, rely on daemons to provide authentication and to +forward packets, possibly on a multi-homed machine which has +kernel packet forwarding disabled. + +<p>Sometimes sites combine the two types of firewalls, so that only a +certain machine (known as a <bf>bastion host</bf>) is allowed to send +packets through a packet filtering router onto an internal +network. Proxy services are run on the bastion host, which are +generally more secure than normal authentication mechanisms. + +<p>FreeBSD comes with a kernel packet filter (known as <tt>IPFW</tt>), +which is what the rest of this section will concentrate on. Proxy +servers can be built on FreeBSD from third party software, but there +is such a vareity of proxy servers available that it would be +impossible to cover them in this document. + +<sect2><heading>Packet filtering routers<label id="firewalls:packet_filters"></heading> + +<p>A router is a machine which forwards packets between two or more +networks. A packet filtering router has an extra piece of code in it's +kernel, which compares each packet to a list of rules before deciding +if it should be forwarded or not. Most modern IP routing software has +packet filtering code in it, which defaults to forwarding all +packets. To enable the filters, you need to define a set of rules for +the filtering code, so that it can decide if the packet should be +allowed to pass or not. + +<p>To decide if a packet should be passed on or not, the code looks +through it's set of rules for a rule which matches the contents of +this packets headers. Once a match is found, the rule action is +obeyed. The rule action could be to drop the packet, to forward the +packet, or even to send an ICMP message back to the originator. Only +the first match counts, as the rules are searched in order. Hence, the +list of rules can be referred to as a ``rule chain''. + +<p>The packet matching criteria varies depending on the software used, +but typically you can specify rules which depend on the source IP +address of the packet, the destination IP address, the source port +number, the destination port number (for protocols which support +ports), or even the packet type (UDP, TCP, ICMP, etc). + +<sect2><heading>Proxy servers<label id="firewalls:proxy_servers"></heading> + +<p>Proxy servers are machines which have had the normal system daemons +(telnetd, ftpd, etc) replaced with special servers. These servers are +called <bf>proxy servers</bf> as they normally only allow onward +connections to be made. This enables you to run (for example) a proxy +telnet server on your firewall host, and people can telnet in to your +firewall from the outside, go through some authentication mechanism, +and then gain access to the internal network (alternatively, proxy +servers can be used for signals coming from the internal network and +heading out). + +<p>Proxy servers are normally more secure than normal servers, and +often have a wider variety of authentication mechanisms available, +including ``one-shot'' password systems so that even if someone +manages to discover what password you used, they will not be able to use +it to gain access to your systems as the password instantly +expires. As they do not actually give users access to the host machine, +it becomes a lot more difficult for someone to install backdoors +around your security system. + +<p>Proxy servers often have ways of restricting access further, so +that only certain hosts can gain access to the servers, and often they +can be set up so that you can limit which users can talk to which +destination machine. Again, what facilities are available depends +largely on what proxy software you choose. + +<sect1><heading>What does <tt>IPFW</tt> allow me to do?</heading> + +<p><tt>IPFW</tt>, the software supplied with FreeBSD, is a packet +filtering and accounting system which resides in the kernel, and has a +user-land control utility, <tt>ipfw(8)</tt>. Together, they +allow you to define and query the rules currently used by the kernel +in its routing decisions. + +<p>There are two related parts to <tt>IPFW</tt>. The firewall section +allows you to perform packet filtering. There is also an IP accounting +section which allows you to track usage of your router, based on +similar rules to the firewall section. This allows you to see (for +example) how much traffic your router is getting from a certain +machine, or how much WWW (World Wide Web) traffic it is forwarding. + +<p>As a result of the way that <tt>IPFW</tt> is designed, you can use +<tt>IPFW</tt> on non-router machines to perform packet filtering on +incoming and outgoing connections. This is a special case of the more +general use of <tt>IPFW</tt>, and the same commands and techniques +should be used in this situation. + +<sect1><heading>Enabling <tt>IPFW</tt> on FreeBSD</heading> + +<p>As the main part of the <tt>IPFW</tt> system lives in the kernel, you will +need to add one or more options to your kernel configuration +file, depending on what facilities you want, and recompile your kernel. See +<ref id="kernelconfig" name="reconfiguring the kernel"> for more +details on how to recompile your kernel. + +<p>There are currently three kernel configuration options +relevant to IPFW: + +<descrip> +<tag/options IPFIREWALL/ Compiles into the kernel the code for packet +filtering. + +<tag/options IPFIREWALL_VERBOSE/ Enables code to allow logging of +packets through <tt>syslogd</tt>. Without this option, even if you +specify that packets should be logged in the filter rules, nothing +will happen. + +<tag/options IPACCT/ Turns on the IP accounting facilities. + +</descrip> + +<sect1><heading>Configuring <tt>IPFW</tt></heading> + +<p>The configuration of the <tt>IPFW</tt> software is done through the +<tt>ipfw(8)</tt> utility. The syntax for this command looks +quite complicated, but it is relatively simple once you understand +it's structure. + +<p>There are currently two different command line formats for the +utility, depending on what you are doing. The first form is used when +adding/deleting entries from the firewall or accounting chains, or +when clearing the counters for an entry on the accounting chain. The +second form is used for more general actions, such as flushing the +rule chains, listing the rule chains or setting the default policy. + +<sect2><heading>Altering the <tt>IPFW</tt> rules</heading> + +<p>The syntax for this form of the command is: +<tscreen> +ipfw [-n] <em>command</em> <em>action</em> <em>protocol</em> <em>addresses</em> +</tscreen> + +<p>There is one valid flag when using this form of the command: + +<descrip> +<tag/-n/Do not attempt to resolve given addresses. +</descrip> + +The <em>command</em> given can be shortened to the shortest unique +form. The valid <em>commands</em> are: + +<descrip> + +<tag/addfirewall/Add an entry to the firewall rule list + +<tag/delfirewall/Delete an entry from the firewall rule list + +<tag/addaccounting/Add an entry to the accounting rule list + +<tag/delaccounting/Delete an entry from the accounting rule list + +<tag/clraccounting/Clear the counters for an accounting rule entry. + +</descrip> + +If no command is given, it will default <bf>addfirewall</bf> or +<bf>addaccounting</bf> depending on the arguments given. + +<p>Currently, the firewall support in the kernel applies a set of +weights to the rule being added. This means that the rules will +<em>not</em> be evaluated in the order that they are given to the +system. The weighting system is designed so that rules which are very +specific are evaluated first, and rules which cover very large ranges +are evaluated last. In other words, a rule which applies to a specific +port on a specific host will have a higher priority than a rule which +applies to that same port, but on a range of hosts, or that host on a +range of ports. + +<p>The weighting system is not perfect, however, and can lead to +problems. The best way to see what order it has put your rules in is +to use the <bf>list</bf> command, as that command lists the rules in +the order that they are evaluated, not the order that they were fed to +the system. + +<p>The <em>actions</em> available depend on which rule chain the +entry is destined for. For the firewall chain, valid +<em>actions</em> are: + +<descrip> + +<tag/reject/Drop the packet, and send an ICMP HOST_UNREACHABLE packet +to the source. + +<tag/lreject/As <bf>reject</bf>, but also log the packet details. + +<tag/deny/Drop the packet. + +<tag/ldeny/As <bf>deny</bf>, but also log the packet details. + +<tag/log/Log the packets details and pass it on as normal. + +<tag/accept/Pass the packet on as normal. + +<tag/pass/Synonym for <bf>accept</bf>. + +</descrip> + +For the accounting chain, valid <em>actions</em> are: + +<descrip> + +<tag/single/Count packets matching the address specifier. + +<tag/bidirectional/Count packets matching the address specifier, and +also packets travelling in the opposite direction (i.e. those going +from ``destination'' to ``source''). + +</descrip> + +<p>Each <em>action</em> will be recognized by the shortest unambigious +prefix. + +The <em>protocols</em> which can be specified are: + +<descrip> + +<tag/all/Matches any IP packet + +<tag/icmp/Matches ICMP packets + +<tag/tcp/Matches TCP packets + +<tag/udp/Matches UDP packets + +<tag/syn/Matches the TCP SYN (synchronization) packet used during TCP +connection negotiation. You can use this to block ``incoming'' TCP +connections, but allow ``outgoing'' TCP connections. +</descrip> + +<p>The <em>address</em> specification is: +<tscreen> +[<bf>from</bf> <<em>address/mask</em>>[<em>port</em>]] [<bf>to</bf> + <<em>address/mask</em>>[<em>port</em>]] [<bf>via</bf> <<em>interface</em>>] +</tscreen> + +<p>You can only specify <em>port</em> in conjunction with +<em>protocols</em> which support ports (UDP, TCP and SYN). + +<p>The order of the <bf>from</bf>, <bf>to</bf>, and +<bf>via</bf> keywords is unimportant. Any of them can be omitted, +in which case a default entry for that keyword will be supplied which +matches everything. + +<p>The <bf>via</bf> is optional and may specify the IP address or +domain name of a local IP interface, or an interface name (e.g. +<tt>ed0</tt>) to match only packets coming through this interface. The +keyword <bf>via</bf> can be substituted by <bf>on</bf>, for +readability reasons. + +<p>The syntax used to specify an <tt><address/mask></tt> is: +<tscreen> +<address> +</tscreen> +or +<tscreen> +<address>/mask-bits +</tscreen> +or +<tscreen> +<address>:mask-pattern +</tscreen> + +<p>A valid hostname may be specified in place of the IP +address. <tt>mask-bits</tt> is a decimal number representing how many +bits in the address mask should be set. e.g. specifying +<tscreen> +192.216.222.1/24 +</tscreen> +will create a mask which will allow any address in a class C subnet +(in this case, 192.216.222) to be matched. <tt>mask-pattern</tt> is an IP +address which will be logically AND'ed with the address given. The +keyword <tt>any</tt> may be used to specify ``any IP address''. +<p>The port numbers to be blocked are specified as: +<tscreen> +port[,port[,port[...]]] +</tscreen> +to specify either a single port or a list of ports, or +<tscreen><verb> +port:port +</verb></tscreen> +to specify a range of ports. The name of a service (from +<em>/etc/services</em>) can be used instead of a numeric port value. + +<sect2><heading>Listing/flushing the <tt>IPFW</tt> rules</heading> + +<p>The syntax for this form of the command is: +<tscreen> +ipfw [-ans] <em>command</em> [<em>argument</em>] +</tscreen> + +<p>There are three valid flags when using this form of the command: + +<descrip> + +<tag/-a/While listing, show counter values. This option is the only +way to see accounting counters. Works only with <bf>-s</bf>. + +<tag/-n/Do not attempt to resolve given addresses. + +<tag/-s/Use short listing form. This should be used with <bf>-a</bf> +to see accounting counters. The short form listing is incompatible +with the input syntax used by the <tt>ipfw(8)</tt> utility. + +</descrip> + +The <em>command</em> given can be shortened to the shortest unique +form. The valid <em>commands</em> are: + +<descrip> + +<tag/list/List the chain rule entries. Unless the <bf>-s</bf> flag is +given, the format is compatable with the command line syntax. + +<tag/flush/Flush the chain rule entries. + +<tag/zero/Clear counters for the entire accounting chain. + +<tag/policy/Set or display the default policy for the firewall +code. Without an argument, the current policy will be displayed. + +</descrip> + +The <bf>list</bf> and <bf>flush</bf> commands may optionally be passed +an <em>argument</em> to specify which chain to flush. Valid arguments are: + +<descrip> + +<tag/firewall/The packet filter chain. + +<tag/accounting/The accounting chain. + +</descrip> + +<p>The <bf>policy</bf> command can be given one of two arguments: + +<descrip> + +<tag/accept/If a packet is not matched by any rule, pass it on. + +<tag/deny/If a packet is not matched by any rule, do not pass it on. + +</descrip> + +As usual, the arguments can be shortened to the shortest unique form +(in this case, the first letter). + +<sect1><heading>Example commands for ipfw</heading> + +<p>This command will deny all packets from the host +<bf>evil.hacker.org</bf> to the telnet port of the host +<bf>nice.people.org</bf> by being forwarded by the router: + +<tscreen><verb> +ipfw addf deny tcp from evil.hacker.org to nice.people.org telnet +</verb></tscreen> + +<p>The next example denies and logs any TCP traffic from the entire +<bf>hacker.org</bf> network (a class C) to the <bf>nice.people.org</bf> +machine (any port). + +<tscreen><verb> +ipfw addf ldeny tcp from evil.hacker.org/24 to nice.people.org +</verb></tscreen> + +If you do not want people sending X sessions to your internal network +(a subnet of a class C), the following command will do the necessary +filtering: + +<tscreen><verb> +ipfw addf deny syn to my.org/28 6000 +</verb></tscreen> + +To allow access to the SUP server on <bf>sup.FreeBSD.ORG</bf>, use the +following command: + +<tscreen><verb> +ipfw addf accept syn to sup.FreeBSD.ORG supfilesrv +</verb></tscreen> + +To see the accounting records: +<tscreen><verb> +ipfw -sa list accounting +</verb></tscreen> +or in the short form +<tscreen><verb> +ipfw -sa l a +</verb></tscreen> + +<sect1><heading>Building a packet filtering firewall</heading> + +<p><quote><bf>Note:</bf> The following suggestions are just that: +suggestions. The requirements of each firewall are different and I +cannot tell you how to build a firewall to meet your particular +requirements.</quote> + +<p>When initially setting up your firewall, unless you have a test +bench setup where you can configure your firewall host in a controlled +environment, I strongly recommend you use the logging version of the +commands and enable logging in the kernel. This will allow you to +quickly identify problem areas and cure them without too much +disruption. Even after the initial setup phase is complete, I +recommend using the logging for of `deny' as it allows tracing of +possible attacks and also modification of the firewall rules if your +requirements alter. + +<quote><bf>Note:</BF> If you use the logging versions of the +<bf>accept</bf> command, it can generate <em>large</em> ammounts +of log data as one log line will be generated for every packet +that passes through the firewall, so large ftp/http transfers, +etc, will really slow the system down. It also increases the +latencies on those packets as it requires more work to be done by +the kernel before the packet can be passed on. syslogd with also +start using up a lot more processor time as it logs all the extra +data to disk, and it could quite easily fill the partition +<tt>/var/log</tt> is located on.</quote> + +<p>As currently supplied, FreeBSD does not have the ability to +load firewall rules at boot time. My suggestion is to put a call +to a shell script in the <tt>/etc/netstart</tt> script. Put the +call early enough in the netstart file so that the firewall is +configured before any of the IP interfaces are configured. This +means that there is no window during which time your network is +open. + +<p>The actual script used to load the rules is entirely up to +you. There is currently no support in the <tt>ipfw</tt> utility for +loading multiple rules in the one command. The system I use is to use +the command: + +<tscreen><verb> +# ipfw list +</verb></tscreen> + +to write a list of the current rules out to a file, and then use a +text editor to prepend ``<tt>ipfw </tt>'' before all the lines. This +will allow the script to be fed into /bin/sh and reload the rules into +the kernel. Perhaps not the most efficient way, but it works. + +<p>The next problem is what your firewall should actually <bf>DO</bf>! +This is largely dependant on what access to your network you want to +allow from the outside, and how much access to the outside world you +want to allow from the inside. Some general rules are: + +<itemize> + + <item>Block all incoming access to ports below 1000 for TCP. This is +where most of the security sensitive services are, like finger, smtp +(mail) and telnet. + + <item>Block incoming SYN connections to ports between 1001 and 1024 +(this will allow internal users to rsh/rlogin to the outside). If you +do not want to allow rsh/rlogin connections from the inside to the +outside, then extend the above suggestion to cover ports 1-1024. + + <item>Block <bf>all</bf> incoming UDP traffic. There are very few +useful services that travel over UDP, and what useful traffic there is +is normally a security threat (e.g. Suns RPC and NFS protocols). This +has its disadvantages also, since UDP is a connectionless protocol, +denying incoming UDP traffic also blocks the replies to outoing UDP +traffic. This can cause a problem for people (on the inside) +using external archie (prospero) servers. If you want to allow access +to archie, you'll have to allow packets coming from ports 191 and 1525 +to any internal UDP port through the firewall. ntp is another service +you may consider allowing through, which comes from port 123. + + <item>Block traffic to port 6000 from the outside. Port 6000 is the +port used for access to X11 servers, and can be a security threat +(especially if people are in the habbit of doing <tt>xhost +</tt> on +their workstations). X11 can actually use a range of ports starting at +6000, the upper limit being how many X displays you can run on the +machine. The upper limit as defined by RFC 1700 (Assigned Numbers) is +6063. + + <item>Check what ports any internal servers use (e.g. SQL servers, +etc). It's probably a good idea to block those as well, as they +normally fall outside the 1-1024 range specified above. + +</itemize> + +<p>Of course, if you want to make sure that no un-authorised traffic +gets through the firewall, change the default policy to ``deny''. This +will mean that any traffic which is allowed through has to be +specified explicitly in an ``accept'' or ``allow'' filter rule. Which +ports you allow through is again something that you will have to +decide for yourself. If you do set the default policy to be deny, you +will probably want to install proxy servers, as no traffic will be +able to get OUT either unless you allow TCP SYN connections going form +the inside out. + +<p>As I said above, these are only <em>guidelines</em>. You will have +to decide what filter rules you want to use on your firewall +yourself. I cannot accept ANY responsibility if someone breaks into +your network, even if you follow the advice given above. diff --git a/share/doc/handbook/kernelconfig.sgml b/share/doc/handbook/kernelconfig.sgml new file mode 100644 index 000000000000..bb8cc08f13de --- /dev/null +++ b/share/doc/handbook/kernelconfig.sgml @@ -0,0 +1,1206 @@ +<!-- $Id: kernelconfig.sgml,v 0.99 1995/10/05 20:14:15 jehamby Exp $ --> +<!-- The FreeBSD Documentation Project --> +<!-- <!DOCTYPE linuxdoc PUBLIC '-//FreeBSD//DTD linuxdoc//EN'> --> + <chapt><heading>Configuring the FreeBSD Kernel<label id="kernelconfig"></heading> + + <p><em>Contributed by &a.jehamby;.<newline>6 October 1995.</em> + + This large section of the handbook discusses the basics of + building your own custom kernel for FreeBSD. This section + is appropriate for both novice system administrators and + those with advanced Unix experience. + + <sect><heading>Why build a custom kernel?</heading> + + <p>Building a custom kernel is one of the most important + rites of passage every Unix system administrator must + learn. This process, while time-consuming, will provide + many benefits to your FreeBSD system. Unlike the GENERIC + kernel, which must support every possible SCSI and + network card, along with tons of other rarely used + hardware support, a custom kernel only contains support + for <em>your</em> PC's hardware. This has a number of + benefits: + + <itemize> + + <item>It will take less time to boot because it does not + have to spend time probing for hardware which you + do not have. + + <item>A custom kernel often uses less memory, which is + important because the kernel is the one process which + must always be present in memory, and so all of that + unused code ties up pages of RAM that your programs + would otherwise be able to use. Therefore, on a + system with limited RAM, building a custom kernel is + of critical importance. + + <item>Finally, there are several kernel options which + you can tune to fit your needs, and device driver + support for things like sound cards which you can + include in your kernel but are <em>not</em> present + in the GENERIC kernel. + + </itemize></p> + + <sect><heading>Building and Installing a Custom Kernel</heading> + + <p>First, let us take a quick tour of the kernel build + directory. All directories mentioned will be relative to + the main <tt>/usr/src/sys</tt> directory, which is also + accessible through <tt>/sys</tt>. There are a number of + subdirectories here representing different parts of the + kernel, but the most important, for our purposes, are + <tt>i386/conf</tt>, where you will edit your custom + kernel configuration, and <tt>compile</tt>, which is the + staging area where your kernel will be built. Notice the + logical organization of the directory tree, with each + supported device, filesystem, and option in its own + subdirectory. Also, anything inside the <tt>i386</tt> + directory deals with PC hardware only, while everything + outside the <tt>i386</tt> directory is common to all + platforms which FreeBSD could potentially be ported to. + + <quote><em/Note:/ If there is <em>not</em> a + <tt>/usr/src/sys</tt> directory on your system, then the + kernel source has not been been installed. Follow the + instructions for installing packages to add this package + to your system.</quote> + + Next, move to the <tt>i386/conf</tt> directory and copy + the GENERIC configuration file to the name you want to + give your kernel. For example: +<tscreen><verb> +# cd /usr/src/sys/i386/conf +# cp GENERIC MYKERNEL +</verb></tscreen> + Traditionally, this name is in all capital letters and, + if you are maintaining multiple FreeBSD machines with + different hardware, it's a good idea to name it after + your machine's hostname. We will call it MYKERNEL for + the purpose of this example. + + <quote><em/Note:/ You must execute these and all of the + following commands under the root account or you will get + ``permission denied'' errors.</quote> + + Now, edit MYKERNEL with your favorite text editor. If + you're just starting out, the only editor available will + probably be <tt>vi</tt>, which is too complex to explain + here, but is covered well in many books in the <ref + id="bibliography" name="bibliography">. Feel free to change the comment + lines at the top to reflect your configuration or the + changes you've made to differentiate it from GENERIC. + + If you've build a kernel under SunOS or some other BSD + operating system, much of this file will be very familiar + to you. If you're coming from some other operating + system such as DOS, on the other hand, the GENERIC + configuration file might seem overwhelming to you, so + follow the descriptions in the <ref + id="kernelconfig:config" name="Configuration File"> + section slowly and carefully. + + When you're finished, type the following to compile and + install your kernel: +<tscreen><verb> +# /usr/sbin/config MYKERNEL +# cd ../../compile/MYKERNEL +# make +# make install +</verb></tscreen> + The new kernel will be copied to the root directory as + <tt>/kernel</tt> and the old kernel will be moved to + <tt>/kernel.old</tt>. Now, shutdown the system and + reboot to use your kernel. In case something goes wrong, + there are some <ref id="kernelconfig:trouble" name= + "troubleshooting"> instructions at the end of this + document. Be sure to read the section which explains how + to recover in case your new kernel <ref + id="kernelconfig:noboot" name="does not boot">. + + <quote><em/Note:/ If you've added any new devices (such + as sound cards) you may have to add some <ref + id="kernelconfig:nodes" name="device nodes"> to your + <tt>/dev</tt> directory before you can use them.</quote> + + <sect><heading>The Configuration File<label id="kernelconfig:config"></heading> + + <p>The general format of a configuration file is quite + simple. Each line contains a keyword and one or more + arguments. For simplicity, most lines only contain one + argument. Anything following a <tt>#</tt> is considered + a comment and ignored. The following sections describe + each keyword, generally in the order they are listed in + GENERIC, although some related keywords have been grouped + together in a single section (such as Networking) even + though they are actually scattered throughout the GENERIC + file. An exhaustive list of options is present in the + LINT configuration file, located in the same directory as + GENERIC. + + <sect1><heading>Mandatory Keywords</heading> + + <p>These keywords are required in every kernel you build. + + <descrip> + + <tag>machine ``i386''</tag> + + <p>The first keyword is <tt>machine</tt>, which, + since FreeBSD only runs on Intel 386 and compatible + chips, is i386. + + <quote><em>Note:</em> that any keyword which + contains numbers used as text must be enclosed in + quotation marks, otherwise <tt>config</tt> gets + confused and thinks you mean the actual number + 386.</quote> + + <tag>cpu ``<em>cpu_type</em>''</tag> + + <p>The next keyword is <tt>cpu</tt>, which includes + support for each CPU supported by FreeBSD. The + possible values of <tt><em>cpu_type</em></tt> + include: + <itemize> + <item>I386_CPU + <item>I486_CPU + <item>I586_CPU + </itemize> + and multiple instances of the <tt>cpu</tt> line may + be present with different values of + <tt><em>cpu_type</em></tt> as are present in the + GENERIC kernel. For a custom kernel, it is best to + specify only the cpu you have. If, for example, + you have an Intel Pentium, use <tt>I586_CPU</tt> + for <tt><em>cpu_type</em></tt>. + + <tag>ident <em>machine_name</em></tag> + + <p>Next, we have <tt>ident</tt>, which is the + identification of the kernel. You should change + this from GENERIC to whatever you named your + kernel, in this example, MYKERNEL. The value you + put in <tt>ident</tt> will print when you boot up + the kernel, so it's useful to give a kernel a + different name if you want to keep it separate from + your usual kernel (if you want to build an + experimental kernel, for example). Note that, as + with <tt>machine</tt> and <tt> cpu</tt>, enclose + your kernel's name in quotation marks if it + contains any numbers. + + <tag>maxusers <em>number</em></tag> + + <p>This file sets the size of a number of important + system tables. This number is supposed to be + roughly equal to the number of simultaneous users + you expect to have on your machine. However, under + normal circumstances, you will want to set + <tt>maxusers</tt> to at least four, especially if + you're using X Windows or compiling software. The + reason is that the most important table set by + <tt>maxusers</tt> is the maximum number of + processes, which is set to <bf><tt>20 + 16 * + maxusers</tt></bf>, so if you set <tt>maxusers</tt> + to one, then you can only have 36 simultaneous + processes, including the 18 or so that the system + starts up at boot time, and the 15 or so you will + probably create when you start X Windows. Even a + simple task like reading a <tt>man</tt> page will + start up nine processes to filter, decompress, and + view it. Setting <tt>maxusers</tt> to 4 will allow + you to have up to 84 simultaneous processes, which + should be enough for anyone. If, however, you see + the dreaded ``proc table full'' error when trying + to start another program, or are running a server + with a large number of simultaneous users (like + Walnut Creek CDROM's FTP site!), you can always + increase this number and rebuild. + + <quote><em/Note:/ <tt>maxuser</tt> does + <em>not</em> limit the number of users which can + log into your machine. It simply sets various + table sizes to reasonable values considering the + maximum number of users you will likely have on + your system and how many processes each of them + will be running. One keyword which + <em>does</em> limit the number of simultaneous + <em>remote logins</em> is <ref + id="kernelconfig:ptys" name="pseudo-device pty + 16">.</quote> + + <tag>config <em>kernel_name</em> root on <em>root_device</em></tag> + + <p>This line specifies the location and name of the + kernel. Traditionally the kernel is called + <tt>vmunix</tt> but in FreeBSD, it is aptly named + <tt>kernel</tt>. You should always use + <tt>kernel</tt> for <em>kernel_name</em> because + changing it will render numerous system utilities + inoperative. The second part of the line specifies + the disk and partition where the root filesystem + and kernel can be found. Typically this will be + <tt>wd0</tt> for systems with non-SCSI drives, or + <tt>sd0</tt> for systems with SCSI drives. + + </descrip> + + <sect1><heading>General Options</heading> + + <p>These lines provide kernel support for various + filesystems and other options. + + <descrip> + + <label id="kernelconfig:mathemu"> + + <tag>options MATH_EMULATE</tag> + + <p>This line allows the kernel to simulate a math + coprocessor if your computer does not have one (386 + or 486SX). If you have a Pentium, a 486DX, or a + 386 or 486SX with a separate 387 or 487 chip, you + can comment this line out. + + <quote><em>Note:</em> The normal math coprocessor + emulation routines that come with FreeBSD are + <em>not</em> very accurate. If you do not have a + math coprocessor, and you need the best accuracy, + I recommend that you change this option to + <tt>GPL_MATH_EMULATE</tt> to use the superior GNU + math support, which is not included by default + for licensing reasons.</quote> + + <tag>options ``COMPAT_43''</tag> + + <p>Compatibility with BSD 4.3. Leave this in; some + programs will act strangely if you comment this + out. + + <tag>options BOUNCE_BUFFERS</tag> + + <p>ISA devices and EISA devices operating in an ISA + compatibilty mode can only perform DMA (Direct + Memory Access) to memory below 16 megabytes. This + option enables such devices to work in systems with + more than 16 megabytes of memory. + + <tag>options UCONSOLE</tag> + + <p>Allow users to grab the console, useful for X + Windows. For example, you can create a console + xterm by typing <tt>xterm -C</tt>, which will + display any `write', `talk', and other messages you + receive. + + <tag>options SYSVSHM</tag> + + <p>This option + provides for System V shared memory. The most + common use of this is the XSHM extension in X + Windows, which many graphics-intensive programs + (such as the movie player XAnim, and Linux DOOM) + will automatically take advantage of for extra + speed. If you use X Windows, you'll definitely + want to include this. + + <tag>options SYSVSEM</tag> + + <p>Support for System V + semaphores. Less commonly used but only adds a few + hundred bytes to the kernel. + + <tag>options SYSVMSG</tag> + + <p>Support for System V + messages. Again, only adds a few hundred bytes to + the kernel. + + <quote><em/Note:/ The <tt>ipcs(1)</tt> command will + tell will list any processes using using each of + these System V facilities.</quote> + + </descrip> + + <sect1><heading>Filesystem Options</heading> + + <p>These options add support for various filesystems. + You must include at least one of these to support the + device you boot from; typically this will be + <tt>FFS</tt> if you boot from a hard drive, or + <tt>NFS</tt> if you are booting a diskless workstation + from Ethernet. You can include other commonly-used + filesystems in the kernel, but feel free to comment out + support for filesystems you use less often (perhaps the + MS-DOS filesystem?), since they will be dynamically + loaded from the Loadable Kernel Module directory + <tt>/lkm</tt> the first time you mount a partition of + that type. + + <descrip> + + <tag>options FFS</tag> + + <p>The basic hard drive + filesystem; leave it in if you boot from the hard + disk. + + <tag>options NFS</tag> + + <p>Network Filesystem. Unless + you plan to mount partitions from a Unix file + server over Ethernet, you can comment this out. + + <tag>options MSDOSFS</tag> + + <p>MS-DOS Filesystem. Unless + you plan to mount a DOS formatted hard drive + partition at boot time, you can safely comment this + out. It will be automatically loaded the first + time you mount a DOS partition, as described above. + Also, the excellent <tt>mtools</tt> software (in + the ports collection) allows you to access DOS + floppies without having to mount and unmount them + (and does not require MSDOSFS at all). + + <tag>options ``CD9660''</tag> + + <p>ISO 9660 filesystem for + CD-ROMs. Comment it out if you do not have a + CD-ROM drive or only mount data CD's occasionally + (since it will be dynamically loaded the first time + you mount a data CD). Audio CD's do not need this + filesystem. + + <tag>options PROCFS</tag> + + <p>Process filesystem. This + is a pretend filesystem mounted on /proc which + allows programs like <tt>ps(1)</tt> to give you + more information on what processes are running. + Leave it in. + + <tag>options MFS</tag> + + <p>Memory-mapped file system. + This is basically a RAM disk for fast storage of + temporary files, useful if you have a lot of swap + space that you want to take advantage of. A + perfect place to mount an MFS partition is on the + <tt>/tmp</tt> directory, since many programs store + temporary data here. To mount an MFS RAM disk on + <tt>/tmp</tt>, add the following line to + <tt>/etc/fstab</tt> and then reboot or type + <tt>mount /tmp</tt>: +<tscreen><verb> +/dev/wd1s2b /tmp mfs rw 0 0 +</verb></tscreen> + + <quote><em/Note:/ Replace the <tt>/dev/wd1s2b</tt> + with the name of your swap partition, which will + be listed in your <tt>/etc/fstab</tt> as follows: +<tscreen><verb> +/dev/wd1s2b none swap sw 0 0 +</verb></tscreen> + </quote> + + <quote><em/Note:/ <!-- MFS is currently a bit + limited (for example, I noticed that two programs + ca not access the <tt>/tmp</tt> device + simultaneously). As such, you may want to avoid + it for now. --> Also, the <tt>MFS</tt> filesystem + can <em>not</em> be dynamically loaded, so you + <em>must</em> compile it into your kernel if you + want to experiment with it.</quote> + + <tag>options QUOTA</tag> + + <p>Enable disk quotas. If you + have a public access system, and do not want users + to be able to overflow the <tt>/home</tt> + partition, you can establish disk quotas for each + user. This code is a little buggy, so do not + enable it unless you have to. View the manual page + for <tt>quota(1)</tt> to learn more about disk + quotas. + + </descrip> + + <sect1><heading>Basic Controllers and Devices</heading> + + <p>These sections describe the basic disk, tape, and + CD-ROM controllers supported by FreeBSD. There are + separate sections for <ref id="kernelconfig:scsi" + name="SCSI"> controllers and <ref + id="kernelconfig:network" name="network"> cards. + + <descrip> + + <tag>controller isa0</tag> + + <p>All PC's supported by + FreeBSD have one of these. If you have an IBM PS/2 + (Micro Channel Architecture), then you cannot run + FreeBSD at this time. + + <tag>controller pci0</tag> + + <p>Include this if you have a + PCI motherboard. This enables auto-detection of + PCI cards and gatewaying from the PCI to the ISA + bus. + + <tag>controller fdc0</tag> + + <p>Floppy drive controller: + <tt>fd0</tt> is the ``A:'' floppy drive, and + <tt>fd1</tt> is the ``B:'' drive. <tt>ft0</tt> is + a QIC-80 tape drive attached to the floppy + controller. Comment out any lines corresponding to + devices you do not have. + + <quote><em/Note:/ QIC-80 tape support requires a + separate filter program called <tt>ft(8)</tt>, see + the manual page for details.</quote> + + <tag>controller wdc0</tag> + + <p>This is the primary IDE + controller. <tt>wd0</tt> and <tt>wd1</tt> are the + master and slave hard drive, respectively. + <tt>wdc1</tt> is a secondary IDE controller where + you might have a third or fourth hard drive, or an + IDE CD-ROM. Comment out the lines which do not + apply (if you have a SCSI hard drive, you'll + probably want to comment out all six lines, for + example). + + <tag>controller wcd0<label id="kernelconfig:atapi"></tag> + + <p>This device + provides IDE CD-ROM support. Be sure to leave + <tt>wdc1</tt> uncommented if your CD-ROM is on + its own controller card. To use this, you must + also include the line <tt>options ATAPI</tt>. + + <tag>device npx0 at isa? port ``IO_NPX'' irq 13 vector npxintr</tag> + + <p><tt>npx0</tt> is the interface to the + math coprocessor. If you have one then make sure + you've commented out <ref id="kernelconfig:mathemu" + name="MATH_EMULATE"> above. If you do not have a + math coprocessor, you can comment this out. + + <tag>device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr</tag> + + <p>Wangtek and Archive + QIC-02/QIC-36 tape drive support + + <tag>Proprietary CD-ROM support</tag> + + <p>The following + drivers are for the so-called <em>proprietary</em> + CD-ROM drives. These drives have their own + controller card or might plug into a sound card + such as the Soundblaster 16. They are <em>not</em> + IDE or SCSI. Most older single-speed and + double-speed CD-ROMs use these interfaces, while + newer quad-speeds are likely to be <ref + id="kernelconfig:atapi" name="IDE"> or <ref + id="kernelconfig:scsi" name="SCSI">. + + <descrip> + + <tag>device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr</tag> + + <p>Mitsumi CD-ROM (LU002, + LU005, FX001D). + + <tag>device scd0 at isa? port 0x230 bio</tag> + + <p>Sony CD-ROM (CDU31, CDU33A). + + <tag>controller matcd0 at isa? port ? bio</tag> + + <p>Matsushita/Panasonic CD-ROM (sold by Creative + Labs for Soundblaster). + + </descrip> + + </descrip> + + <sect1><heading>SCSI Device Support<label id="kernelconfig:scsi"></heading> + + <p>This section describes the various SCSI controllers + and devices supported by FreeBSD. + + <descrip> + + <tag>SCSI Controllers</tag> + + <p>The next ten or so lines include support for + different kinds of SCSI controllers. Comment out + all except for the one(s) you have: + + <descrip> + + <tag>controller bt0 at isa? port ``IO_BT0'' bio irq ? vector btintr</tag> + + <p>Most Buslogic controllers + + <tag>controller uha0 at isa? port ``IO_UHA0'' bio irq ? drq 5 vector uhaintr</tag> + + <p>UltraStor 14F and 34F + + <tag>controller ahc0</tag> + + <p>Adaptec 274x/284x/294x + + <tag>controller ahb0 at isa? bio irq ? vector ahbintr</tag> + + <p>Adaptec 174x + + <tag>controller aha0 at isa? port ``IO_AHA0'' bio irq ? drq 5 vector ahaintr</tag> + + <p>Adaptec 154x + + <tag>controller aic0 at isa? port 0x340 bio irq 11 vector aicintr +</tag> + + <p>Adaptec 152x and sound cards using Adaptec AIC-6360 (slow!) + + <tag>controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr +</tag> + + <p>ProAudioSpectrum cards using NCR 5380 or Trantor T130 + + <tag>controller sea0 at isa? bio irq 5 iomem 0xc8000 iosiz 0x2000 vector seaintr</tag> + + <p>Seagate ST01/02 8 bit controller (slow!) + + <tag>controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr</tag> + + <p>Western Digital WD7000 controller + + <tag>controller ncr0</tag> + + <p>NCR 53C810 and 53C825 PCI SCSI controller + + </descrip> + + <tag>options ``SCSI_DELAY=15''</tag> + + <p>This causes the + kernel to pause 15 seconds before probing each SCSI + device in your system. If you only have IDE hard + drives, you can ignore this, otherwise you'll + probably want to lower this number, perhaps to 5 + seconds, to speed up booting. Of course if you do + this, and FreeBSD has trouble recognizing your SCSI + devices, you'll have to raise it back up. + + <tag>controller scbus0</tag> + + <p>If you have any SCSI + controllers, this line provides generic SCSI + support. If you do not have SCSI, you can comment + this, and the following three lines, out. + + <tag>device sd0</tag> + + <p>Support for SCSI hard + drives. + + <tag>device st0</tag> + + <p>Support for SCSI tape + drives. + + <tag>device cd0</tag> + + <p>Support for SCSI CD-ROM + drives. + + </descrip> + + <sect1><heading>Console, Bus Mouse, and X Server Support</heading> + + <p>You must choose one of these two console types, and, if you plan + to use X Windows, enable the XSERVER option and optionally, a bus + mouse or PS/2 mouse device. + + <descrip> + + <tag>device sc0 at isa? port ``IO_KBD' tty irq 1 vector scintr</tag> + + <p><tt>sc0</tt> is the default + console driver, which resembles an SCO console. + Since most full-screen programs access the console + through a terminal database library like + <em>termcap</em>, it should not matter much whether + you use this or <tt>vt0</tt>, the VT220 compatible + console driver. When you log in, set your TERM + variable to ``scoansi'' if full-screen programs + have trouble running under this console. + + <tag>device vt0 at isa? port ``IO_KBD'' tty irq 1 vector pcrint</tag> + + <p>This is a VT220-compatible + console driver, backwards compatible to VT100/102. + It works well on some laptops which have hardware + incompatibilities with <tt>sc0</tt>. Also, set + your TERM variable to ``vt220'' when you log in if + full-screen programs do not run correctly on this + console. + + <descrip> + + <tag>options ``PCVT_FREEBSD=210''</tag> + + <p>Required + with the <tt>vt0</tt> console driver. + + <tag>options XSERVER</tag> + + <p>This includes code + required to run the <tt>XFree86</tt> X Window + Server. + + </descrip> + + <tag>device mse0 at isa? port 0x23c tty irq 5 vector ms</tag> + + <p>Use this device if you have a Logitech or + ATI InPort bus mouse card. + + <quote><em/Note:/ If you have a serial mouse, + ignore these two lines, and instead, make sure + the appropriate <ref id="kernelconfig:serial" + name="serial"> port is enabled (probably + COM1).</quote> + + <tag>device psm0 at isa? port ``IO_KBD'' conflicts tty irq 12 vector psmintr</tag> + + <p>Use this device if your + mouse plugs into the PS/2 mouse port. + + </descrip> + + <sect1><heading>Serial and Parallel Ports</heading> + + <p>Nearly all systems have these. If you are attaching a + printer to one of these ports, the <ref id="printing" + name="Printing"> section of the handbook is very + useful. If you are using modem, <ref id="dialup" + name="Dialup access"> provides extensive detail on + serial port configuration for use with such devices. + + <descrip> + + <tag>device sio0 at isa? port ``IO_COM1'' tty irq 4 vector siointr<label id="kernelconfig:serial"></tag> + + <p><tt>sio0</tt> + through <tt>sio3</tt> are the four serial ports + referred to as COM1 through COM4 in the MS-DOS + world. Note that if you have an internal modem on + COM4 and a serial port at COM2 you will have to + change the IRQ of the modem to 2 (for obscure + technical reasons IRQ 2 = IRQ 9) in order to access + it from FreeBSD. If you have a multiport serial + card, check the manual page for <tt>sio(4)</tt> for + more information on the proper values for these + lines. + + <tag>device lpt0 at isa? port? tty irq 7 vector lptintr</tag> + + <p><tt>lpt0</tt> through <tt>lpt2</tt> + are the three printer ports you could conceivably + have. Most people just have one, though, so feel + free to comment out the other two lines if you do + not have them. + + </descrip> + + <sect1><heading>Networking<label id="kernelconfig:network"></heading> + + <p>FreeBSD, as with Unix in general, places a + <em>big</em> emphasis on networking. Therefore, even + if you do not have an Ethernet card, pay attention to + the mandatory options and the dial-up networking + support. + + <descrip> + + <tag>options INET</tag> + Networking support. Leave it in even if you do not plan + to be connected to a network. Most programs require at least + loopback networking (i.e. making network connections within your + PC) so this is essentially mandatory. + + <tag>Ethernet cards</tag> + + <p>The next lines enable support for various Ethernet + cards. If you do not have a network card, you can + comment out all of these lines. Otherwise, you'll + want to leave in support for your particular + Ethernet card(s): + + <descrip> + + <tag>device de0</tag> + + <p>Digital Equipment DC21040 PCI Ethernet adapter + + <tag>device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr</tag> + + <p>Cronyx/Sigma multiport + sync/async (with Cisco or PPP framing) + + <tag>device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr</tag> + + <p>Western Digital and SMC 80xx; Novell NE1000 + and NE2000; 3Com 3C503 + + <tag>device el0 at isa? port 0x300 net irq 9 vector elintr</tag> + + <p>3Com 3C501 (slow!) + + <tag>device eg0 at isa? port 0x310 net irq 5 vector egintr</tag> + + <p>3Com 3C505 + + <tag>device ep0 at isa? port 0x300 net irq 10 vector epintr</tag> + + <p>3Com 3C509 (buggy) + + <tag>device fe0 at isa? port 0x240 net irq ? vector feintr</tag> + + <p>Fujitsu MB86960A/MB86965A Ethernet + + <tag>device fea0 at isa? net irq ? vector feaintr</tag> + + <p>DEC DEFEA EISA FDDI adapter + + <tag>device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr</tag> + + <p>AT&T StarLAN 10 and EN100; 3Com 3C507; + unknown NI5210 + + <tag>device ix0 at isa? port 0x300 net irq 10 iomem 0xd0000 iosiz 32768 vector ixintr</tag> + + <p>Intel EtherExpress 16 + + <tag>device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr</tag> + + <p>Digital Equipment EtherWorks 2 and EtherWorks + 3 (DEPCA, DE100, DE101, DE200, DE201, DE202, + DE203, DE204, DE205, DE422) + + <tag>device lnc0 at isa? port 0x300 net irq 10 drq 0 vector lncintr</tag> + + <p>Lance/PCnet cards (Isolan, Novell NE2100, + NE32-VL) + + <tag>device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr</tag> + + <p>IBM/National Semiconductor PCMCIA ethernet + controller. + + <tag>device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr</tag> + + <p>3Com PCMCIA Etherlink III + + </descrip> + + <quote><em/Note:/ With certain cards (notably the + NE2000) you'll have to change the port and/or IRQ + since there is no ``standard'' location for these + cards.</quote> + + <tag>pseudo-device loop</tag> + + <p><tt>loop</tt> is the + generic loopback device for TCP/IP. If you telnet + or FTP to <em>localhost</em> + (a.k.a. <tt>127.0.0.1</tt>) it will come back at + you through this pseudo-device. Mandatory. + + <tag>pseudo-device ether</tag> + + <p><tt>ether</tt> is only + needed if you have an Ethernet card and includes + generic Ethernet protocol code. + + <tag>pseudo-device sl <em>number</em></tag> + + <p><tt>sl</tt> is for SLIP (Serial Line Internet + Protocol) support. This has been almost entirely + supplanted by PPP, which is easier to set up, + better suited for modem-to-modem connections, as + well as more powerful. The <em>number</em> after + <tt>sl</tt> specifies how many simultaneous SLIP + sessions to support. This handbook has more + information on setting up a SLIP <ref id="slipc" + name="client"> or <ref id="slips" name="server">. + + <tag>pseudo-device ppp <em>number</em></tag> + + <p><tt>ppp</tt> is for kernel-mode PPP (Point-to-Point + Protocol) support for dial-up Internet connections. + There is also version of PPP implemented as a user + application that uses the <tt>tun</tt> and offers + more flexibility and features such as demand + dialing. If you still want to use this PPP driver, + read the <ref id="ppp" name="kernel-mode PPP"> + section of the handbook. As with the <tt>sl</tt> + device, <em>number</em> specifies how many + simultaneous PPP connections to support. + + <tag>pseudo-device tun <em>number</em></tag> + + <p><tt>tun</tt> is used by the user-mode PPP software. + This program is easy to set up and very fast. It + also has special features such as automatic + dial-on-demand. The number after <tt>tun</tt> + specifies the number of simultaneous PPP sessions + to support. See the <ref id="userppp" + name="user-mode PPP"> section of the handbook for + more information. + + <tag>pseudo-device bpfilter <em>number</em></tag> + + <p>Berkeley packet filter. This pseudo-device allows + network interfaces to be placed in promiscuous + mode, capturing every packet on a broadcast network + (e.g. an ethernet). These packets can be captured + to disk and/or examined with the + <tt>tcpdump(1)</tt> program. Note that + implementation of this capability can seriously + compromise your overall network security. + The <em>number</em> after bpfilter is the number of + interfaces that can be examined + simultaneously. Optional, not recommended except + for those who are fully aware of the potential + pitfalls. Not all network cards support this + capability. + + </descrip> + + <sect1><heading>Sound cards</heading> + + <p>This is the first section containing lines that are + not in the GENERIC kernel. To include sound card + support, you'll have to copy the appropriate lines from + the LINT kernel (which contains support for + <em>every</em> device) as follows: + + <descrip> + + <tag>controller snd0</tag> + + <p>Generic sound driver code. + Required for all of the following sound cards + except <tt>pca</tt>. + + <tag>device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr</tag> + + <p>ProAudioSpectrum digital audio and MIDI. + + <tag>device sb0 at isa? port 0x220 irq 7 conflicts drq 1 vector sbintr</tag> + + <p>SoundBlaster digital audio. + + <quote><em/Note:/ If your Soundblaster is on a + different IRQ (such as 5), change <tt>irq 7</tt> + to, for example, <tt>irq 5</tt> and remove the + <tt>conflicts</tt> keyword. Also, you must add + the line: <tt>options ``SBC_IRQ=5''</tt></quote> + + <tag>device sbxvi0 at isa? drq 5</tag> + + <p>SoundBlaster 16 digital 16-bit audio. + + <quote><em/Note:/ If your SB16 is on a different + 16-bit DMA channel (such as 6 or 7), change the + <tt>drq 5</tt> keyword appropriately, and then + add the line: <tt>options + "SB16_DMA=6"</tt></quote> + + <tag>device sbmidi0 at isa? port 0x330</tag> + + <p>SoundBlaster 16 MIDI interface. If you have a + SoundBlaster 16, you must include this line, or the + kernel will not compile. + + <tag>device gus0 at isa? port 0x220 irq 10 drq 1 vector gusintr</tag> + + <p>Gravis Ultrasound. + + <tag>device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr</tag> + + <p>Microsoft Sound System. + + <tag>device opl0 at isa? port 0x388 conflicts</tag> + + <p>AdLib FM-synthesis audio. Include this line for + AdLib, SoundBlaster, and ProAudioSpectrum users, if + you want to play MIDI songs with a program such as + <tt>playmidi</tt> (in the ports collection). + + <tag>device mpu0 at isa? port 0x330 irq 6 drq 0</tag> + + <p>Roland MPU-401 stand-alone card. + + <tag>device uart0 at isa? port 0x330 irq 5 vector ``m6850intr''</tag> + + <p>Stand-alone 6850 UART for MIDI. + + <tag>device pca0 at isa? port ``IO_TIMER1'' tty</tag> + + <p>Digital audio through PC speaker. This is going to + be very poor sound quality and quite CPU-intensive, + so you have been warned (but it does not require a + sound card)! + + </descrip> + + <quote><em/Note:/ There is some additional + documentation in + <tt>/usr/src/sys/i386/isa/sound/sound.doc</tt>. + Also, if you add any of these devices, be sure to + create the sound <ref id="kernelconfig:nodes" + name="device nodes">.</quote> + + <sect1><heading>Pseudo-devices</heading> + + <p>Pseudo-device drivers are parts of the kernel that act + like device drivers but do not correspond to any actual + hardware in the machine. The <ref + id="kernelconfig:network" name="network-related"> + pseudo-devices are in that section, while the remainder + are here. + + <descrip> + + <tag>pseudo-device gzip</tag> + + <p><tt>gzip</tt> allows you to run FreeBSD programs + that have been compressed with <tt>gzip</tt>. This + is really only useful when you need to compress + FreeBSD programs to fit on a boot floppy. You will + probably never need to compress programs on your + hard drive in this fashion, so you'll probably want + to comment out this line. + <tag>pseudo-device log</tag> + + <p><tt>log</tt> is used for logging of kernel error + messages. Mandatory. + + + <tag>pseudo-device pty <em>number</em><label id="kernelconfig:ptys"></tag> + + <p><tt>pty</tt> is a ``pseudo-terminal'' or simulated + login port. It's used by incoming <bf>telnet</bf> + and <bf>rlogin</bf> sessions, xterm, and some other + applications such as emacs. The <em>number</em> + indicates the number of <tt>pty</tt>s to create. + If you need more than GENERIC default of 16 + simultaneous xterm windows and/or remote logins, be + sure to increase this number accordingly, up to a + maximum of 64. + + <tag>pseudo-device snp <em>number</em></tag> + + <p>Snoop device. This pseudo-device allows one + terminal session to watch another using the + <tt>watch(8)</tt> command. Note that + implementation of this capability has important + security and privacy implications. The + <em>number</em> after snp is the total number of + simultaneous snoop sessions. Optional. + + <tag>pseudo-device vn</tag> + + <p>Vnode driver. Allows a file to be treated as a + device after being set up with the + <tt>vnconfig(8)</tt> command. This driver can be + useful for manipulating floppy disk images and + using a file as a swap device (e.g. an MS Windows + swap file). Optional. + + </descrip> + + <sect1><heading>Joystick, PC Speaker, Miscellaneous</heading> + + <p>This section describes some miscellaneous hardware + devices supported by FreeBSD. Note that none of these + lines are included in the GENERIC kernel, you'll have + to copy them from this handbook or the LINT kernel + (which contains support for <em>every</em> device): + + <descrip> + + <tag>device joy0 at isa? port ``IO_GAME''</tag> + + <p>PC joystick device. + + <tag>pseudo-device speaker</tag> + + <p>Supports IBM BASIC-style noises through the PC + speaker. Some fun programs which use this are + <tt>/usr/sbin/spkrtest</tt>, which is a shell + script that plays some simple songs, and + <tt>/usr/games/piano</tt> which lets you play songs + using the keyboard as a simple piano (this file + only exists if you've installed the <em>games</em> + package). Also, the excellent text role-playing + game NetHack (in the ports collection) can be + configured to use this device to play songs when + you play musical instruments in the game. + + </descrip> + + <sect><heading>Making Device Nodes<label id="kernelconfig:nodes"></heading> + + <p>Almost every device in the kernel has a corresponding + ``node'' entry in the <tt>/dev</tt> directory. These + nodes look like regular files, but are actually special + entries into the kernel which programs use to access the + device. The shell script <tt>/dev/MAKEDEV</tt>, which is + executed when you first install the operating system, + creates nearly all of the device nodes supported. + However, it does not create <em>all</em> of them, so when + you add support for a new device, it pays to make sure + that the appropriate entries are in this directory, and + if not, add them. Here is a simple example: + + Suppose you add the IDE CD-ROM support to the kernel. + The line to add is: +<tscreen><verb> +controller wcd0 +</verb></tscreen> + This means that you should look for some entries that + start with <tt>wcd0</tt> in the <tt>/dev</tt> directory, + possibly followed by a letter, such as `c', or preceded + by the letter 'r', which means a `raw' device. It turns + out that those files are not there, so I must change to + the <tt>/dev</tt> directory and type: +<tscreen><verb> +# sh MAKEDEV wcd0 +</verb></tscreen> + When this script finishes, you will find that there are + now <tt>wcd0c</tt> and <tt>rwcd0c</tt> entries in + <tt>/dev</tt> so you know that it executed correctly. + + For sound cards, the command: +<tscreen><verb> +# sh MAKEDEV snd0 +</verb></tscreen> + creates the appropriate entries. Follow this simple + procedure for any other non-GENERIC devices which do not + have entries. + + <quote><em/Note:/ All SCSI controllers use the same set + of <tt>/dev</tt> entries, so you do not need to create + these. Also, network cards and SLIP/PPP pseudo-devices + do not have entries in <tt>/dev</tt> at all, so you do + not have to worry about these either.</quote> + +<sect><heading>If Something Goes Wrong<label id="kernelconfig:trouble"></heading> + + <p>There are four categories of trouble that can occur when + building a custom kernel. They are: + + <descrip> + + <tag>Config command fails</tag> + + <p>If the <tt>config</tt> + command fails when you give it your kernel + description, you've probably made a simple error + somewhere. Fortunately, <tt>config</tt> will print + the line number that it had trouble with, so you can + quickly skip to it with <tt>vi</tt>. For example, if + you see: +<tscreen><verb> +config: line 17: syntax error +</verb></tscreen> + you can skip to the problem in <tt>vi</tt> by typing + ``17G'' in command mode. Make sure the keyword is + typed correctly, by comparing it to the GENERIC + kernel or another reference. + + <tag>Make command fails</tag> + + <p>If the <tt>make</tt> + command fails, it usually signals an error in your + kernel description, but not severe enough for + <tt>config</tt> to catch it. Again, look over your + configuration, and if you still cannot resolve the + problem, send mail to <tt><htmlurl + url="mailto:questions@freebsd.org" + name="questions@FreeBSD.ORG"></tt> with your kernel + configuration, and it should be diagnosed very + quickly. + + <tag>Kernel will not boot<label id="kernelconfig:noboot"></tag> + + <p>If your new kernel + does not boot, or fails to recognize your devices, + do not panic! Fortunately, BSD has an excellent + mechanism for recovering from incompatible kernels. + Simply type the name of the kernel you want to boot + from (i.e. ``kernel.old'') at the FreeBSD boot + prompt instead of pressing return. When + reconfiguring a kernel, it is always a good idea to + keep a kernel that is known to work on hand. + + After booting with a good kernel you can check over + your configuration file and try to build it again. + One helpful resource is the + <tt>/var/log/messages</tt> file which records, among + other things, all of the kernel messages from every + successful boot. Also, the <tt>dmesg(8)</tt> command + will print the kernel messages from the current boot. + + <quote><em/Note:/ If you are having trouble building + a kernel, make sure to keep a GENERIC, or some + other kernel that is known to work on hand as a + different name that will not get erased on the next + build. You cannot rely on <tt>kernel.old</tt> + because when installing a new kernel, + <tt>kernel.old</tt> is overwritten with the last + installed kernel which may be non-functional. + Also, as soon as possible, move the working kernel + to the proper ``kernel'' location or commands such + as <tt>ps(1)</tt> will not work properly. The + proper command to ``unlock'' the kernel file that + <tt>make</tt> installs (in order to move another + kernel back permanently) is: +<tscreen><verb> +# chflags noschg /kernel +</verb></tscreen> + And, if you want to ``lock'' your new kernel into place, or any file + for that matter, so that it cannot be moved or tampered with: +<tscreen><verb> +# chflags schg /kernel +</verb></tscreen> + </quote> + + <tag>Kernel works, but <tt>ps</tt> does not work any more!</tag> + + <p>If you've installed a different version + of the kernel from the one that the system utilities + have been built with, for example, an experimental + ``2.2.0'' kernel on a 2.1.0-RELEASE system, many + system-status commands like <tt>ps(1)</tt> and + <tt>vmstat(8)</tt> will not work any more. You must + recompile the <tt>libkvm</tt> library as well as + these utilities. This is one reason it is not + normally a good idea to use a different version of + the kernel from the rest of the operating system. + + </descrip> diff --git a/share/doc/handbook/printing.sgml b/share/doc/handbook/printing.sgml new file mode 100644 index 000000000000..fd6d75bd0b7f --- /dev/null +++ b/share/doc/handbook/printing.sgml @@ -0,0 +1,3877 @@ +<!-- This is an SGML document in the linuxdoc DTD describing + Printing with FreeBSD. By Sean Kelly, 1995. + + $Id: printing.sgml,v 1.1 1995/10/01 04:43:13 jfieber Exp $ + + The FreeBSD Documentation Project + +<!DOCTYPE linuxdoc PUBLIC "-//FreeBSD//DTD linuxdoc//EN"> + + <article> + <title> Printing with FreeBSD + <author> Sean Kelly <tt/kelly@fsl.noaa.gov/ + <date> 30 September 1995, (c) 1995 + + <abstract> This document describes printing with FreeBSD. It + tells how to set up printer hardware, how to configure FreeBSD + to use printers, and how to control the print queue and print + a variety of file formats. </abstract> + + <toc> +--> + + <chapt><heading>Printing<label id="printing"></heading> + + <p><em>Contributed by &a.kelly;<newline>30 September 1995</em> + + In order to use printers with FreeBSD, you'll need to set + them up to work with the Berkeley line printer spooling + system, also known as the LPD spooling system. It's the + standard printer control system in FreeBSD. This section + introduces the LPD spooling system, often simply called LPD. + + If you're already familiar with LPD or another printer + spooling system, you may wish to skip to section <ref + id="printing:intro:setup" name="Setting up the spooling + system">. + + <sect><heading>What the Spooler Does<label + id="printing:intro:spooler"></heading> + + <p> LPD controls everything about a host's printers. It's + responsible for a number of things: + + <itemize> + <item>It controls access to attached printers and + printers attached to other hosts on the network. + + <item>It enables users to submit files to be printed; + these submissions are known as <em/jobs/. + + <item>It prevents multiple users from accessing a printer + at the same time by maintaining a <em/queue/ for each + printer. + + <item>It can print <em/header pages/ (also known as + <em/banner/ or <em/burst/ pages) so users can easily + find jobs they've printed in a stack of printouts. + + <item>It takes care of communications parameters for + printers connected on serial ports. + + <item>It can send jobs over the network to another LPD + spooler on another host. + + <item>It can run special filters to format jobs to be + printed for various printer languages or printer + capabilities. + + <item>It can account for printer usage. + </itemize> + + Through a configuration file, and by providing the special + filter programs, you can enable the LPD system to do all or + some subset of the above for a great variety of printer + hardware. + + <sect><heading>Why You Should Use the Spooler<label + id="printing:intro:why"></heading> + + <p> If you're the sole user of your system, you may be + wondering why you should bother with the spooler when you + don't need access control, header pages, or printer + accounting. While it's possible to enable direct access to + a printer, you should use the spooler anyway since + + <itemize> + <item>LPD prints jobs in the background; you don't have + to wait for data to be copied to the printer. + + <item>LPD can conveniently run a job to be printed + through filters to add date/time headers or convert a + special file format (such as a TeX DVI file) into a + format the printer will understand. You won't have to do + these steps manually. + + <item>Many free and commercial programs that provide a + print feature usually expect to talk to the spooler on + your system. By setting up the spooling system, you'll + more easily support other software you may later add or + already have. + </itemize> + + <sect><heading>Setting Up the Spooling System<label + id="printing:intro:setup"></heading> + + <p> To use printers with the LPD spooling system, you'll need + to set up both your printer hardware and the LPD software. + This document describes two levels of setup: + + <itemize> + <item>See section <ref name="Simple Printer Setup" + id="printing:simple"> to learn how to connect a + printer, tell LPD how to communicate with it, and + print plain text files to the printer. + + <item>See section <ref name="Advanced Printer Setup" + id="printing:advanced"> to find out how to print a + variety of special file formats, to print header + pages, to print across a network, to control access to + printers, and to do printer accounting. + </itemize> + + + <sect><heading>Simple Printer Setup<label + id="printing:simple"></heading> + + <p> This section tells how to configure printer hardware and the + LPD software to use the printer. It teaches the basics: + + <itemize> + <item>Section <ref id="printing:hardware" name="Hardware + Setup"> gives some hints on connecting the printer to a + port on your computer. + + <item>Section <ref id="printing:software" name="Software + Setup"> shows how to setup the LPD spooler configuration + file <tt>/etc/printcap</tt>. + </itemize> + + If you're setting up a printer that uses a network protocol + to accept data to print instead of a serial or parallel interface, + see <ref id="printing:advanced:network:net-if" name="Printers + With Networked Data Stream Interaces">. + + Although this section is called ``Simple Printer Setup,'' it's + actually fairly complex. Getting the printer to work with + your computer and the LPD spooler is the hardest part. The + advanced options like header pages and accounting are fairly + easy once you get the printer working. + + <sect1><heading>Hardware Setup<label id="printing:hardware"></heading> + + <p> This section tells about the various ways you can connect a + printer to your PC. It talks about the kinds of ports and + cables, and also the kernel configuration you may need to + enable FreeBSD to speak to the printer. + + If you've already connected your printer and have + successfully printed with it under another operating system, + you can probably skip to section <ref id="printing:software" + name="Software Setup">. + + <sect2><heading>Ports and Cables<label + id="printing:ports"></heading> + + <p> Nearly all printers you can get for a PC today support + one or both of the following interfaces: + + <itemize> + <item><em/Serial/ interfaces use a serial port on your + computer to send data to the printer. Serial + interfaces are common in the computer industry and + cables are readily available and also easy to + construct. Serial interfaces sometimes need special + cables and might require you to configure somewhat + complex communications options. + + <item><em/Parallel/ interfaces use a parallel port on + your computer to send data to the printer. Parallel + interfaces are common in the PC market. Cables are + readily available but more difficult to construct by + hand. There are usually no communications options + with parallel interfaces, making their configuration + exceedingly simple. + + <p> Parallel interfaces are sometimes known as + ``Centronics'' interfaces, named after the connector + type on the printer. + </itemize> + + In general, serial interfaces are slower than parallel + interfaces. Parallel interfaces usually offer just + one-way communication (computer to printer) while serial + gives you two-way. Many newer parallel ports can also + receive data from the printer, but only few printers need + to send data back to the computer. And FreeBSD doesn't + support two-way parallel communication yet. + + Usually, the only time you need two-way communication with + the printer is if the printer speaks PostScript. + PostScript printers can be very verbose. In fact, + PostScript jobs are actually programs sent to the printer; + they needn't produce paper at all and may return results + directly to the computer. PostScript also uses + two-way communication to tell the computer about problems, + such as errors in the PostScript program or paper jams. + Your users may be appreciative of such information. + Furthermore, the best way to do effective accounting with + a PostScript printer requires two-way communication: you + ask the printer for its page count (how many pages it's + printed in its lifetime), then send the user's job, then + ask again for its page count. Subtract the two values and + you know how much paper to charge the user. + + So, which interface should you use? + + <itemize> + <item>If you need two-way communication, use a serial + port. FreeBSD does not yet support two-way + communication over a parallel port. + + <item>If you don't need two-way communication and can + pick parallel or serial, prefer the parallel + interface. It keeps a serial port free for other + peripherals---such as a terminal or a modem---and is + faster most of the time. It's also easier to + configure. + + <item>Finally, use whatever works. + </itemize> + + + <sect2><heading>Parallel Ports<label id="printing:parallel"></heading> + + <p> To hook up a printer using a parallel interface, connect + the Centronics cable between the printer and the + computer. The instructions that came with the printer, the + computer, or both should give you complete guidance. + + Remember which parallel port you used on the computer. The + first parallel port is /dev/lpt0 to FreeBSD; the second is + /dev/lpt1, and so on. + + <sect2><heading>Serial Ports<label id="printing:serial"></heading> + + <p> To hook up a printer using a serial interface, connect + the proper serial cable between the printer and the + computer. The instructions that came with the printer, + the computer, or both should give you complete guidance. + + If you're unsure what the ``proper serial cable'' is, you + may wish to try one of the following alternatives: + <itemize> + <item>A <em/modem/ cable connects each pin of the + connector on one end of the cable straight through to + its corresponding pin of the connector on the other + end. This type of cable is also known as a DTE-to-DCE + cable. + + <item>A <em/null-modem/ cable connects some pins + straight through, swaps others (send data to receive + data, for example), and shorts some internally in each + connector hood. This type of cable is also known as a + DTE-to-DTE cable. + + <item>A <em/serial printer/ cable, required for some + unusual printers, is like the null modem cable, but + sends some signals to their counterparts instead of + being internally shorted. + </itemize> + + You should also set up the communications parameters for + the printer, usually through front-panel controls or DIP + switches on the printer. Choose the highest bps (bits per + second, sometimes <em/baud rate/) rate that both your + computer and the printer can support. Choose 7 or 8 data + bits; none, even, or odd parity; and 1 or 2 stop bits. + Also choose a flow control protocol: either none, or + XON/XOFF (also known as <em/in-band/ or <em/software/) + flow control. Remember these settings for the software + configuration that follows. + + <sect1><heading>Software Setup<label id="printing:software"></heading> + + <p> This section describes the software setup necessary to + print with the LPD spooling system in FreeBSD. + + Here's an outline of the steps involved: + <enum> + <item>Configure your kernel, if necessary, for the port + you're using for the printer; section <ref + id="printing:kernel" name="Kernel Configuration"> tells + you what you need to do. + + <item>Set the communications mode for the parallel port, + if you're using a parallel port; section <ref + id="printing:parallel-port-mode" name = "Setting the + Communication Mode for the Parallel Port"> gives + details. + + <item>Test if the operating system can send data to the + printer. Section <ref id="printing:testing" + name="Checking Printer Communications"> gives some + suggestions on how to do this. + + <item>Set up LPD for the printer by modifying the file + <tt>/etc/printcap</tt>. Section <ref + id="printing:printcap" name="The /etc/printcap File"> + shows you how. + </enum> + + <sect2><heading>Kernel Configuration<label + id="printing:kernel"></heading> + + <p> The operating system kernel is compiled to work with a + specific set of devices. The serial or parallel interface + for your printer is a part of that set. Therefore, it + might be necessary to add support for an additional serial + or parallel port if your kernel isn't already configured + for one. + + To find out if the kernel you're currently using supports a serial + interface, type +<tscreen> +<tt>dmesg | grep sio</tt><it/N/ +</tscreen> + where <it/N/ is the number of the serial port, starting + from zero. If you see output similar to the following +<tscreen><verb> +sio2 at 0x3e8-0x3ef irq 5 on isa +sio2: type 16550A +</verb></tscreen> + then the kernel supports the port. + + To find out if the kernel supports a parallel interface, + type +<tscreen> +<tt>dmesg | grep lpt</tt><it/N/ +</tscreen> + where <it/N/ is the number of the parallel port, starting + from zero. If you see output similar to the following +<tscreen><verb> +lpt0 at 0x378-0x37f on isa +</verb></tscreen> + then the kernel supports the port. + + You might have to reconfigure your kernel in order for the + operating system to recognize and use the parallel or + serial port you're using for the printer. + + To add support for a serial port, see the section on + kernel configuration. To add support for a parallel port, + see that section <em/and/ the section that follows. + + <sect3><heading>Adding <tt>/dev</tt> Entries for the Ports + <label id="printing:dev-ports"></heading> + + <p> Even though the kernel may support communication along + a serial or parallel port, you'll still need a software + interface through which programs running on the system + can send and receive data. That's what entries in the + <tt>/dev</tt> directory are for. + + <bf>To add a <tt>/dev</tt> entry for a port:</bf> + <enum> + <item>Become root with the <tt/su/ command. Enter + the root password when prompted. + + <item>Change to the <tt>/dev</tt> directory: +<tscreen><verb> +cd /dev +</verb></tscreen> + + <item>Type +<tscreen> +<tt> ./MAKEDEV</tt> <it/port/ +</tscreen> + where <it/port/ is the device entry for the port you + want to make. Use <tt/lpt0/ for the first parallel + port, <tt/lpt1/ for the second, and so on; use + <tt/ttyd0/ for the first serial port, <tt/ttyd1/ for + the second, and so on. + + <item>Type +<tscreen> +<tt>ls -l</tt> <it/port/ +</tscreen> + to make sure the device entry got created. + </enum> + + <sect3><heading>Setting the Communication Mode for the Parallel Port + <label id="printing:parallel-port-mode"></heading> + + <p> When you're using the parallel interface, you can + choose whether FreeBSD should use interrupt-driven or + polled communication with the printer. + + <itemize> + <item>The <em/interrupt-driven/ method is the default + with the GENERIC kernel. With this method, the + operating system uses an IRQ line to determine when + the printer's ready for data. + + <item>The <em/polled/ method directs the operating + system to repeatedly ask the printer if it's ready + for more data. When it responds ready, the kernel + sends more data. + </itemize> + + The interrupt-driven method is somewhat faster but uses + up a precious IRQ line. You should use whichever one + works. + + You can set the communications mode in two ways: by + configuring the kernel or by using the <tt/lptcontrol/ + program. + + <bf>To set the communications mode by configuring the + kernel:</bf> + <enum> + <item>Edit your kernel configuration file. Look for + or add an <tt/lpt0/ entry. If you're setting up the + second parallel port, use <tt/lpt1/ instead. Use + <tt/lpt2/ for the third port, and so on. + <itemize> + <item>If you want interrupt-driven mode, add the <tt/irq/ + specifer: +<tscreen> +<tt>device lpt0 at isa? port? tty irq <it/N/ vector lptintr</tt> +</tscreen> + where <it/N/ is the IRQ number for your + computer's parallel port. + + <item>If you want polled mode, don't add the + <tt/irq/ specifier: +<tscreen> +<tt>device lpt0 at isa? port? tty vector lptintr</tt> +</tscreen> + </itemize> + <item>Save the file. Then configure, build, and + install the kernel, then reboot. See <ref id="kernelconfig" + name="kernel configuration"> for more details. + </enum> + + <bf>To set the communications mode with + <tt/lptcontrol/:</bf> + <itemize> + <item> + Type +<tscreen> +<tt>lptcontrol -i -u <it/N/</tt> +</tscreen> + to set interrupt-driven mode for <tt/lpt<it/N//. + + <item> + Type +<tscreen> +<tt>lptcontrol -p -u <it/N/</tt> +</tscreen> + to set polled-mode for <tt/lpt<it/N//. + </itemize> + You could put these commands in your + <tt>/etc/rc.local</tt> file to set the mode each time + your system boots. See lptcontrol(8) for more + information. + + <sect3><heading>Checking Printer Communications<label + id="printing:testing"></heading> + + <p> Before proceeding to configure the spooling system, + you should make sure the operating system can + successfully send data to your printer. It's a lot + easier to debug printer communication and the spooling + system separately. + + To test the printer, we'll send some text to it. For + printers that can immediately print characters sent to + them, the program <tt/lptest/ is perfect: it generates + all 96 printable ASCII characters in 96 lines. + + For a PostScript (or other language-based) printer, + we'll need a more sophisticated test. A small + PostScript program, such as the following, will suffice: +<code> +%!PS +100 100 moveto 300 300 lineto stroke +310 310 moveto +/Helvetica findfont 12 scalefont setfont +(Is this thing working?) show +showpage +</code> + <em/Note:/ When this document refers to a printer + language, I'm assuming a language like PostScript, and + not Hewlett Packard's PCL. Although PCL has great + functionality, you can intermingle plain text with its + escape sequences. PostScript cannot directly print + plain text, and that's the kind of printer language for + which we must make special accomodations. + + <sect4><heading>Checking a Parallel Printer<label + id="printing:checking:parallel"></heading> + + <p> This section tells you how to check if FreeBSD can + communicate with a printer connected to a parallel port. + + <bf>To test a printer on a parallel port:</bf> + <enum> + <item>Become root with <tt/su/. + <item>Send data to the printer. + <itemize> + <item>If the printer can print plain text, then + use <tt/lptest/. Type: +<tscreen> +<tt>lptest > /dev/lpt<it/N/</tt> +</tscreen> + where <it/N/ is the number of the parallel + port, starting from zero. + + <item>If the printer understands PostScript or + other printer language, then send a small + program to the printer. Type +<tscreen> +<tt>cat > /dev/lpt<it/N/</tt> +</tscreen> + Then, line by line, type the program + <em/carefully/ as you can't edit a line once + you've pressed RETURN or ENTER. When you've + finished entering the program, press + CONTROL+D, or whatever your end of file key + is. + + <p> Alternatively, you can put the program in + a file and type +<tscreen> +<tt>cat <it/file/ > /dev/lpt<it/N/</tt> +</tscreen> + where <it/file/ is the name of the file + containing the program you want to send to + the printer. + </itemize> + </enum> + + You should see something print. Don't worry if the + text doesn't look right; we'll fix such things later. + + <sect4><heading>Checking a Serial Printer<label + id="printing:checking:serial"></heading> + + <p> This section tells you how to check if FreeBSD can + communicate with a printer on a serial port. + + <bf>To test a printer on a serial port:</bf> + <enum> + <item>Become root with <tt/su/. + + <item>Edit the file <tt>/etc/remote</tt>. Add the + following entry: +<tscreen> +<tt>printer:dv=/dev/<it/port/:br#<it/bps-rate/:pa=<it/parity/</tt> +</tscreen> + where <it/port/ is the device entry for the serial + port (<tt/ttyd0/, <tt/ttyd1/, etc.), <it/bps-rate/ + is the bits-per-second rate at which the printer + communicates, and <it/parity/ is the parity + required by the printer (either <tt/even/, + <tt/odd/, <tt/none/, or <tt/zero/). + <p> + Here's a sample entry for a printer connected + via a serial line to the third serial port at + 19200 bps with no parity: +<code> +printer:dv=/dev/ttyd2:br#19200:pa=none +</code> + + <item>Connect to the printer with <tt/tip/. Type: +<tscreen><verb> +tip printer +</verb></tscreen> + If this step doesn't work, edit the file + <tt>/etc/remote</tt> again and try using + <tt>/dev/cuaa<it/N/</tt> instead of + <tt>/dev/ttyd<it/N/</tt>. + + <item>Send data to the printer. + <itemize> + <item>If the printer can print plain text, then + use <tt/lptest/. Type: +<tscreen><verb> +~$lptest +</verb></tscreen> + + <item>If the printer understands PostScript or + other printer language, then send a small + program to the printer. Type the program, + line by line, <em/very carefully/ as + backspacing or other editing keys may be + significant to the printer. You may also need + to type a special end-of-file key for the + printer so it knows it received the whole + program. For PostScript printers, press + CONTROL+D. + + <p> Alternatively, you can put the program in + a file and type +<tscreen> +<tt>˜><it/file/</tt> +</tscreen> + where <it/file/ is the name of the file + containing the program. After <tt/tip/ + sends the file, press any required + end-of-file key. + </itemize> + </enum> + + You should see something print. Don't worry if the + text doesn't look right; we'll fix that later. + + <sect2><heading>Enabling the Spooler: The <tt>/etc/printcap</tt> File + <label id="printing:printcap"></heading> + + <p> At this point, your printer should be hooked up, your + kernel configured to communicate with it (if necessary), + and you've been able to send some simple data to the + printer. Now, we're ready to configure LPD to control + access to your printer. + + You configure LPD by editing the file + <tt>/etc/printcap</tt>. The LPD spooling system reads + this file each time the spooler is used, so updates to the + file take immediate effect. + + The format of the <tt/printcap/ file is straightforward. + Use your favorite text editor to make changes to + <tt>/etc/printcap</tt>. The format is identical to other + capability files like <tt>/usr/share/misc/termcap</tt> and + <tt>/etc/remote</tt>. For complete information about the + format, see the cgetent(3). + + The simple spooler configuration consists of the following steps: + <enum> + <item>Pick a name (and a few convenient aliases) for + the printer, and put them in the + <tt>/etc/printcap</tt> file; see <ref + id="printing:naming" name="Naming the Printer">. + + <item>Turn off header pages (which are on by default) + by inserting the <tt/sh/ capability; see <ref + id="printing:no-header-pages" name="Suppressing Header + Pages">. + + <item>Make a spooling directory, and specify its + location with the <tt/sd/ capability; see <ref + id="printing:spooldir" name="Making the Spooling + Directory">. + + <item>Set the <tt>/dev</tt> entry to use for the + printer, and note it in <tt>/etc/printcap</tt> with + the <tt/lp/ capability; see <ref id="printing:device" + name="Identifying the Printer Device">. Also, if the + printer's on a serial port, set up the communication + parameters with the <tt/fs/, <tt/fc/, <tt/xs/, and + <tt/xc/ capabilities; see <ref id="printing:commparam" + name="Configuring Spooler Communications Parameters">. + + <item>Install a plain text input filter; see <ref + id="printing:textfilter" name="Installing the Text + Filter"> + + <item>Test the setup by printing something with the + <tt/lpr/ command; see <ref id="printing:trying" + name="Trying It Out"> and <ref + id="printing:troubleshooting" name="Troubleshooting">. + </enum> + + <em/Note:/ Language-based printers, such as PostScript + printers, can't directly print plain text. The simple + setup outlined above and described in the following + sections assumes that if you're installing such a printer + you'll print only files that the printer can understand. + + Users often expect that they can print plain text to any + of the printers installed on your system. Programs that + interface to LPD to do their printing usually make the + same assumption. If you're installing such a printer and + want to be able to print jobs in the printer language + <em/and/ print plain text jobs, you're strongly urged to + add an additional step to the simple setup outlined above: + install an automatic plain-text--to--PostScript (or other + printer language) conversion program. Section <ref + id="printing:advanced:if-conversion" name="Accomodating + Plain Text Jobs on PostScript Printers"> tells how to do + this. + + <sect3><heading>Naming the Printer<label + id="printing:naming"></heading> + + <p> The first (easy) step is to pick a name for your + printer. It really doesn't matter whether you choose + functional or whimsical names since you can also provide + a number aliases for the printer. + + At least one of the printers specified in the + <tt>/etc/printcap</tt> should have the alias + <tt/lp/. This is the default printer's name. If users + don't have the PRINTER environment variable nor + specify a printer name on the command line of any of the + LPD commands, then <tt/lp/ will be the default printer + they get to use. + + Also, it's common practice to make the last alias for a + printer be a full description of the printer, including + make and model. + + Once you've picked a name and some common aliases, put + them in the <tt>/etc/printcap</tt> file. The name of + the printer should start in the leftmost column. + Separate each alias with a vertical bar and put a colon + after the last alias. + + In the following example, we start with a skeletal + <tt>/etc/printcap</tt> that defines two printers (a + Diablo 630 line printer and a Panasonic KX-P4455 + PostScript laser printer): +<code> +# +# /etc/printcap for host rose +# +rattan|line|diablo|lp|Diablo 630 Line Printer: + +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4: +</code> + In this example, the first printer is named <tt/rattan/ + and has as aliases <tt/line/, <tt/diablo/, <tt/lp/, and + <tt/Diablo 630 Line Printer/. Since it has the alias + <tt/lp/, it's also the default printer. The second is + named <tt/bamboo/, and has as aliases <tt/ps/, <tt/PS/, + <tt/S/, <tt/panasonic/, and <tt/Panasonic KX-P4455 + PostScript v51.4/. + + <sect3><heading>Suppressing Header Pages<label + id="printing:no-header-pages"></heading> + + <p> The LPD spooling system will by default print a + <em/header page/ for each job. The header page contains + the user name who requested the job, the host from which + the job came, and the name of the job, in nice large + letters. Unfortunately, all this extra text gets in the + way of debugging the simple printer setup, so we'll + suppress header pages. + + To suppress header pages, add the <tt/sh/ capability to + the entry for the printer in + <tt>/etc/printcap</tt>. Here's the example + <tt>/etc/printcap</tt> with <tt/sh/ added: +<code> +# +# /etc/printcap for host rose - no header pages anywhere +# +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :sh: + +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :sh: +</code> + Note how we used the correct format: the first line + starts in the leftmost column, and subsequent lines are + indented with a single TAB. Every line in an entry + except the last ends in a backslash character. + + <sect3><heading>Making the Spooling Directory<label + id="printing:spooldir"></heading> + + <p> The next step in the simple spooler setup is to make a + <em/spooling directory/, a directory where print jobs + reside until they're printed, and where a number of + other spooler support files live. + + Because of the variable nature of spooling directories, + it's customary to put these directories under + <tt>/var/spool</tt>. It's not necessary to backup the + contents of spooling directories, either. Recreating + them is as simple as running <tt/mkdir/. + + It's also customary to make the directory with a name + that's identical to the name of the printer, as shown + below: +<tscreen> +<tt>mkdir /var/spool/<it>printer-name</it></tt> +</tscreen> + However, if you have a lot of printers on your network, + you might want to put the spooling directories under a + single directory that you reserve just for printing with + LPD. We'll do this for our two example printers + <tt/rattan/ and <tt/bamboo/: +<tscreen><verb> +mkdir /var/spool/lpd +mkdir /var/spool/lpd/rattan +mkdir /var/spool/lpd/bamboo +</verb></tscreen> + + <em/Note:/ If you're concerned about the privacy of jobs + that users print, you might want to protect the spooling + directory so it's not publicly accessible. Spooling + directories should be owned and be readable, writable, + and searchable by user daemon and group daemon, and no + one else. We'll do this for our example printers: + +<tscreen><verb> +chown daemon.daemon /var/spool/lpd/rattan +chown daemon.daemon /var/spool/lpd/bamboo +chmod 770 /var/spool/lpd/rattan +chmod 770 /var/spool/lpd/bamboo +</verb></tscreen> + + Finally, you need to tell LPD about these directories + using the <tt>/etc/printcap</tt> file. You specify the + pathname of the spooling directory with the <tt/sd/ + capability: +<code> +# +# /etc/printcap for host rose - added spooling directories +# +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :sh:sd=/var/spool/lpd/rattan: + +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :sh:sd=/var/spool/lpd/bamboo: +</code> + Note that the name of the printer starts in the first + column but all other entries describing the printer + should be indented with a tab and each line escaped with + a backslash. + + If you don't specify a spooling directory with <tt/sd/, + the spooling system will use <tt>/var/spool/lpd</tt> as + a default. + + <sect3><heading>Identifying the Printer Device<label + id="printing:device"></heading> + + <p> In section <ref id="printing:dev-ports" name="Adding + /dev Entries for the Ports">, we identified which + entry in the <tt>/dev</tt> directory FreeBSD will use + to communicate with the printer. Now, we tell LPD + that information. When the spooling system has a job + to print, it will open the specified device on behalf + of the filter program (which is responsible for + passing data to the printer). + + List the <tt>/dev</tt> entry pathname in the + <tt>/etc/printcap</tt> file using the <tt/lp/ + capability. + + In our running example, let's assume that <tt/rattan/ is + on the first parallel port, and <tt/bamboo/ is on a + sixth serial port; here are the additions to + <tt>/etc/printcap</tt>: +<code> +# +# /etc/printcap for host rose - identified what devices to use +# +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :sh:sd=/var/spool/lpd/rattan:\ + :lp=/dev/lpt0: + +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :sh:sd=/var/spool/lpd/bamboo:\ + :lp=/dev/ttyd5: +</code> + + If you don't specify the <tt/lp/ capability for a + printer in your <tt>/etc/printcap</tt> file, LPD uses + <tt>/dev/lp</tt> as a default. <tt>/dev/lp</tt> + currently doesn't exist in FreeBSD. + + If the printer you're installing is connected to a + parallel port, skip to the section <ref name="Installing + the Text Filter" id="printing:textfilter">. Otherwise, + be sure to follow the instructions in the next section. + + <sect3><heading>Configuring Spooler Communication + Parameters<label id="printing:commparam"></heading> + + <p> For printers on serial ports, LPD can set up the bps + rate, parity, and other serial communication parameters + on behalf of the filter program that sends data to the + printer. This is advantageous since + <itemize> + <item>It lets you try different communication + parameters by simply editing the + <tt>/etc/printcap</tt> file; you don't have to + recompile the filter program. + + <item>It enables the spooling system to use the same + filter program for multiple printers which may have + different serial communication settings. + </itemize> + + The following <tt>/etc/printcap</tt> capabilities + control serial communication parameters of the device + listed in the <tt/lp/ capability: + <descrip> + <tag/<tt>br#<it/bps-rate/</tt>/ + + Sets the communications speed of the device to + <it/bps-rate/, where <it/bps-rate/ can be 50, 75, + 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, + 4800, 9600, 19200, or 38400 bits-per-second. + + <tag/<tt>fc#<it/clear-bits/</tt>/ + + Clears the flag bits <it/clear-bits/ in the + <tt/sgttyb/ structure after opening the device. + + <tag/<tt>fs#<it/set-bits/</tt>/ + + Sets the flag bits <it/set-bits/ in the <tt/sgttyb/ + structure. + + <tag/<tt>xc#<it/clear-bits/</tt>/ + + Clears local mode bits <it/clear-bits/ after opening + the device. + + <tag/<tt>xs#<it/set-bits/</tt>/ + + Sets local mode bits <it/set-bits/. + </descrip> + For more information on the bits for the <tt/fc/, + <tt/fs/, <tt/xc/, and <tt/xs/ capabilities, see the file + <tt>/usr/include/sys/ioctl_compat.h</tt>. + + When LPD opens the device specified by the <tt/lp/ + capability, it reads the flag bits in the <tt/sgttyb/ + structure; it clears any bits in the <tt/fc/ capability, + then sets bits in the <tt/fs/ capability, then applies + the resultant setting. It does the same for the local + mode bits as well. + + Let's add to our example printer on the sixth serial + port. We'll set the bps rate to 38400. For the flag + bits, we'll set the TANDEM, ANYP, LITOUT, FLUSHO, and + PASS8 flags. For the local mode bits, we'll set the + LITOUT and PASS8 flags: +<tscreen><verb> +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :sh:sd=/var/spool/lpd/bamboo:\ + :lp=/dev/ttyd5:fs#0x82000c1:xs#0x820: +</verb></tscreen> + + + <sect3><heading>Installing the Text Filter<label + id="printing:textfilter"></heading> + + <p> We're now ready to tell LPD what text filter to use to + send jobs to the printer. A <em/text filter/, also + known as an <em/input filter/, is a program that LPD + runs when it has a job to print. When LPD runs the text + filter for a printer, it sets the filter's standard + input to the job to print, and its standard output to + the printer device specified with the <tt/lp/ + capability. The filter is expected to read the job from + standard input, peform any necessary translation for the + printer, and write the results to standard output, which + will get printed. For more information on the text + filter, see section <ref id="printing:advanced:filters" + name="Filters">. + + For our simple printer setup, the text filter can be a + small shell script that just executes <tt>/bin/cat</tt> + to send the job to the printer. FreeBSD comes with + another filter called <tt/lpf/ that handles backspacing + and underlining for printers that might not deal with + such character streams well. And, of course, you can + use any other filter program you want. The filter + <tt/lpf/ is described in detail in section <ref + id="printing:advanced:lpf" name="lpf: a Text Filter">. + + First, let's make the shell script + <tt>/usr/local/libexec/if-simple</tt> be a simple text + filter. Put the following text into that file with your + favorite text editor: +<code> +#!/bin/sh +# +# if-simple - Simple text input filter for lpd +# Installed in /usr/local/libexec/if-simple +# +# Simply copies stdin to stdout. Ignores all filter arguments. + +/bin/cat &ero;&ero; exit 0 +exit 2 +</code> + Make the file executable: +<tscreen><verb> +chmod 555 /usr/local/libexec/if-simple +</verb></tscreen> + + And then tell LPD to use it by specifying it with the + <tt/if/ capability in <tt>/etc/printcap</tt>. We'll add + it to the two printers we have so far in the example + <tt>/etc/printcap</tt>: +<code> +# +# /etc/printcap for host rose - added text filter +# +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :sh:sd=/var/spool/lpd/rattan:\ + :lp=/dev/lpt0:\ + :if=/usr/local/libexec/if-simple: + +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :sh:sd=/var/spool/lpd/bamboo:\ + :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:\ + :if=/usr/local/libexec/if-simple: +</code> + + <sect3><heading>Trying It Out<label id="printing:trying"></heading> + + <p> You've reached the end of the simple LPD setup. + Unfortunately, congratulations are not quite yet in + order, since we've still got to test the setup and + correct any problems. To test the setup, try printing + something. To print with the LPD system, you use the + command <tt/lpr/, which submits a job for printing. + + You can combine <tt/lpr/ with the <tt/lptest/ program, + introduced in section <ref id="printing:testing" + name="Checking Printer Communications"> to generate some + test text. + + <bf>To test the simple LPD setup:</bf> + + <p> Type: +<tscreen> +<tt>lptest 20 5 | lpr -P<it/printer-name/</tt> +</tscreen> + where <it/printer-name/ is a the name of a printer (or + an alias) specified in <tt>/etc/printcap</tt>. To test + the default printer, type <tt/lpr/ without any <tt/-P/ + argument. Again, if you're testing a printer that + expects PostScript, send a PostScript program in that + language instead of using <tt/lptest/. You can do so by + putting the program in a file and typing <tt/lpr + <it/file//. + + For a PostScript printer, you should get the results + of the program. If you're using <tt/lptest/, then your + results should look like the following: + +<tscreen><verb> +!"#$%&ero;'()*+,-./01234 +"#$%&ero;'()*+,-./012345 +#$%&ero;'()*+,-./0123456 +$%&ero;'()*+,-./01234567 +%&ero;'()*+,-./012345678 +</verb></tscreen> + + To further test the printer, try downloading larger + programs (for language-based printers) or running + <tt/lptest/ with different arguments. For example, + <tt/lptest 80 60/ will produce 60 lines of 80 characters + each. + + If the printer didn't work, see the next section, <ref + id="printing:troubleshooting" name="Troubleshooting">. + + <sect3><heading>Troubleshooting<label + id="printing:troubleshooting"></heading> + + <p> After performing the simple test with <tt/lptest/, you + might've gotten one of the following results instead of + the correct printout: + <descrip> + <tag/It worked, after awhile; or, it didn't eject a full sheet./ + + The printer printed the above, but it sat for awhile + and did nothing. In fact, you might've needed to + press a PRINT REMAINING or FORM FEED button on the + printer to get any results to appear. + + If this is the case, the printer was probably + waiting to see if there was any more data for your + job before it printed anything. To fix this + problem, you can have the text filter send a FORM + FEED character (or whatever is necessary) to the + printer. This is usually sufficient to have the + printer immediately print any text remaining in its + internal buffer. It's also useful to make sure each + print job ends on a full sheet, so the next job + doesn't start somewhere on the middle of the last + page of the previous job. + + The following replacement for the shell script + <tt>/usr/local/libexec/if-simple</tt> prints a form + feed after it sends the job to the printer: +<code> +#!/bin/sh +# +# if-simple - Simple text input filter for lpd +# Installed in /usr/local/libexec/if-simple +# +# Simply copies stdin to stdout. Ignores all filter arguments. +# Writes a form feed character (\f) after printing job. + +/bin/cat &ero;&ero; printf "\f" &ero;&ero; exit 0 +exit 2 +</code> + + <tag/It produced the ``staircase effect.''/ + + You got the following on paper: +<tscreen><verb> +!"#$%&ero;'()*+,-./01234 + "#$%&ero;'()*+,-./012345 + #$%&ero;'()*+,-./0123456 + $%&ero;'()*+,-./01234567 +</verb></tscreen> + You've become another victim of the <em/staircase + effect/, caused by conflicting interpretations of + what characters should indicate a new-line. + UNIX-style operating systems use a single character: + ASCII code 10, the line feed (LF). MS-DOS, OS/2, + and others uses a pair of characters, ASCII code 10 + <em/and/ ASCII code 13 (the carriage return or CR). + Many printers use the MS-DOS convention for + representing new-lines. + + When you print with FreeBSD, your text used just the + line feed character. The printer, upon seeing a + line feed character, advanced the paper one line, + but maintained the same horizontal position on the + page for the next character to print. That's what + the carriage return is for: to move the location of + the next character to print to the left edge of the + paper. + + Here's what FreeBSD wants your printer to do: +<tscreen><verb> +Printer received CR Printer prints CR +Printer received LF Printer prints CR + LF +</verb></tscreen> + + Here are some ways to achieve this: + <itemize> + <item>Use the printer's configuration switches or + control panel to alter its interpretation of + these characters. Check your printer's manual + to find out how to do this. + + <p> <em/Note:/ If you boot your system into + other operating systems besides FreeBSD, you + may have to <em/reconfigure/ the printer to + use a an interpretation for CR and LF + characters that those other operating systems + use. You might prefer one of the other + solutions, below. + + <item>Have FreeBSD's serial line driver + automatically convert LF to CR+LF. Of course, + this works with printers on serial ports + <em/only/. To enable this feature, set the + CRMOD bit in <tt/fs/ capability in the + <tt>/etc/printcap</tt> file for the printer. + + <item>Send an <em/escape code/ to the printer to + have it temporarily treat LF characters + differently. Consult your printer's manual for + escape codes that your printer might support. + When you find the proper escape code, modify the + text filter to send the code first, then send + the print job. + + <p> Here's an example text filter for printers + that understand the Hewlett-Packard PCL escape + codes. This filter makes the printer treat LF + characters as a LF and CR; then it sends the + job; then it sends a form feed to eject the + last page of the job. It should work with + nearly all Hewlett Packard printers. + +<code> +#!/bin/sh +# +# hpif - Simple text input filter for lpd for HP-PCL based printers +# Installed in /usr/local/libexec/hpif +# +# Simply copies stdin to stdout. Ignores all filter arguments. +# Tells printer to treat LF as CR+LF. Writes a form feed character +# after printing job. + +printf "\033&ero;k2G" &ero;&ero; cat &ero;&ero; printf "\f" &ero;&ero; exit 0 +exit 2 +</code> + + Here's an example <tt>/etc/printcap</tt> from + a host called orchid. It has a single printer + attached to its first parallel port, a Hewlett + Packard LaserJet 3Si named <tt/teak/. It's + using the above script as its text filter: +<code> +# +# /etc/printcap for host orchid +# +teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ + :lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:\ + :if=/usr/local/libexec/hpif: +</code> + </itemize> + + <tag/It overprinted each line./ + + The printer never advanced a line. All of the lines + of text were printed on top of each other on one + line. + + This problem is the ``opposite'' of the staircase + effect, described above, and is much rarer. + Somewhere, the LF characters that FreeBSD uses to + end a line are being treated as CR characters to + return the print location to the left edge of the + paper, but not also down a line. + + Use the printer's configuration switches or control + panel to enforce the following interpretation of LF + and CR characters: +<tscreen><verb> +Printer received CR Printer prints CR +Printer received LF Printer prints CR + LF +</verb></tscreen> + + <tag/The printer lost characters./ + + While printing, the printer didn't print a few + characters in each line. The problem might've + gotten worse as the printer ran, losing more and + more characters. + + The problem is that the printer can't keep up with + the speed at which the computer sends data over a + serial line. (This problem shouldn't occur with + printers on parallel ports.) There are two ways to + overcome the problem: + <itemize> + <item>If the printer supports XON/XOFF flow + control, have FreeBSD use it by specifying the + TANDEM bit in the <tt/fs/ capability. + + <item>If the printer supports carrier flow + control, specify the MDMBUF bit in the <tt/fs/ + capability. Make sure the cable connecting the + printer to the computer is correctly wired for + carrier flow control. + + <item>If the printer doesn't support any flow + control, use some combination of the NLDELAY, + TBDELAY, CRDELAY, VTDELAY, and BSDELAY bits in + the <tt/fs/ capability to add appropriate delays + to the stream of data sent to the printer. + </itemize> + + <tag/It printed garbage./ + + The printer printed what appeared to be random + garbage, but not the desired text. + + This is usually another symptom of incorrect + communications parameters with a serial printer. + Double-check the bps rate in the <tt/br/ capability, + and the parity bits in the <tt/fs/ and <tt/fc/ + capabilities; make sure the printer is using the + same settings as specified in the + <tt>/etc/printcap</tt> file. + + <tag/Nothing happened./ + + If nothing happened, the problem is probably within + FreeBSD and not the hardware. Add the log file + (<tt/lf/) capability to the entry for the printer + you're debugging in the <tt>/etc/printcap</tt> file. + For example, here's the entry for <tt/rattan/, with + the <tt/lf/ capability: +<tscreen><verb> +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :sh:sd=/var/spool/lpd/rattan:\ + :lp=/dev/lpt0:\ + :if=/usr/local/libexec/if-simple:\ + :lf=/var/log/rattan.log +</verb></tscreen> + Then, try printing again. Check the log file (in + our example, <tt>/var/log/rattan.log</tt>) to see + any error messages that might appear. Based on the + messages you see, try to correct the problem. + + If you don't specify a <tt/lf/ capability, LPD uses + <tt>/dev/console</tt> as a default. + </descrip> + + <sect><heading>Using Printers<label id="printing:using"></heading> + + <p> This section tells you how to use printers you've setup with + FreeBSD. Here's an overview of the user-level commands: + <descrip> + <tag/<tt/lpr// + Print jobs + + <tag/<tt/lpq// + Check printer queues + + <tag/<tt/lprm// + Remove jobs from a printer's queue + + </descrip> + + There's also an administrative command, <tt/lpc/, described in + the section <ref id="printing:lpc" name="Administrating the + LPD Spooler">, used to control printers and their queues. + + All three of the commands <tt/lpr/, <tt/lprm/, and <tt/lpq/ + accept an option ``<tt/-P/ <it/printer-name/'' to specify on + which printer/queue to operate, as listed in the + <tt>/etc/printcap</tt> file. This enables you to submit, + remove, and check on jobs for various printers. If you don't + use the <tt/-P/ option, then these commands use the printer + specified in the PRINTER environment variable. Finally, if + you don't have a PRINTER environment variable, these commands + default to the printer named <tt/lp/. + + Hereafter, the terminology <em/default printer/ means the + printer named in the PRINTER environment variable, or the + printer named <tt/lp/ when there's no PRINTER environment + variable. + + <sect1><heading>Printing Jobs<label id="printing:lpr"></heading> + <p> + + To print files, type +<tscreen> +<tt>lpr <it/filename.../</tt> +</tscreen> + This prints each of the listed files to the default printer. + If you list no files, <tt/lpr/ reads data to print from + standard input. For example, this command prints some + important system files: +<tscreen><verb> +lpr /etc/host.conf /etc/hosts.equiv +</verb></tscreen> + To select a specific printer, type +<tscreen> +<tt>lpr -P <it/printer-name/ <it/filename.../</tt> +</tscreen> + This example prints a long listing of the current directory + to the printer named <tt/rattan/: +<tscreen><verb> +ls -l | lpr -P rattan +</verb></tscreen> + Because no files were listed for the <tt/lpr/ command, + <tt/lpr/ read the data to print from standard input, which + was the output of the <tt/ls -l/ command. + + The <tt/lpr/ command can also accept a wide variety of + options to control formatting, apply file conversions, + generate multiple copies, and so forth. For more + information, see the section <ref id="printing:lpr:options" + name="Printing Options">. + + <sect1><heading>Checking Jobs<label id="printing:lpq"></heading> + + <p> When you print with <tt/lpr/, the data you wish to print + is put together in a package called a <em/print job/, which + is sent to the LPD spooling system. Each printer has a + queue of jobs, and your job waits in that queue along with + other jobs from yourself and from other users. The printer + prints those jobs in a first-come, first-served order. + + To display the queue for the default printer, type <tt/lpq/. + For a specific printer, use the <tt/-P/ option. For + example, the command +<tscreen><verb> +lpq -P bamboo +</verb></tscreen> + shows the queue for the printer named <tt/bamboo/. Here's + an example of the output of the <tt/lpq/ command: +<tscreen><verb> +bamboo is ready and printing +Rank Owner Job Files Total Size +active kelly 9 /etc/host.conf, /etc/hosts.equiv 88 bytes +2nd kelly 10 (standard input) 1635 bytes +3rd mary 11 ... 78519 bytes +</verb></tscreen> + This shows three jobs in the queue for <tt/bamboo/. The + first job, submitted by user kelly, got assigned <em/job + number/ 9. Every job for a printer gets a unique job + number. Most of the time you can ignore the job number, but + you'll need it if you want to cancel the job; see section + <ref id="printing:lprm" name="Removing Jobs"> for details. + + Job number nine consists of two files; multiple files given + on the <tt/lpr/ command line are treated as part of a single + job. It's the currently active job (note the word + <tt/active/ under the ``Rank'' column), which means the + printer should be currently printing that job. The second + job consists of data passed as the standard input to the + <tt/lpr/ command. The third job came from user mary; it's a + much larger job. The pathname of the files she's trying to + print is too long to fit, so the <tt/lpq/ command just shows + three dots. + + The very first line of the output from <tt/lpq/ is also + useful: it tells what the printer is currently doing (or at + least what LPD thinks the printer is doing). + + The <tt/lpq/ command also support a <tt/-l/ option to + generate a detailed long listing. Here's an example of + <tt/lpq -l/: +<tscreen><verb> +waiting for bamboo to become ready (offline ?) + +kelly: 1st [job 009rose] + /etc/host.conf 73 bytes + /etc/hosts.equiv 15 bytes + +kelly: 2nd [job 010rose] + (standard input) 1635 bytes + +mary: 3rd [job 011rose] + /home/orchid/mary/research/venus/alpha-regio/mapping 78519 bytes +</verb></tscreen> + + <sect1><heading>Removing Jobs<label + id="printing:lprm"></heading> + + <p> If you change your mind about printing a job, you can + remove the job from the queue with the <tt/lprm/ command. + Often, you can even use <tt/lprm/ to remove an active job, + but some or all of the job might still get printed. + + To remove a job from the default printer, first use <tt/lpq/ + to find the job number. Then type +<tscreen> +<tt/lprm <it/job-number// +</tscreen> + To remove the job from a specific printer, add the <tt/-P/ + option. The following command removes job number 10 from + the queue for the printer <tt/bamboo/: +<tscreen><verb> +lprm -P bamboo 10 +</verb></tscreen> + The <tt/lprm/ command has a few shortcuts: + <descrip> + <tag/lprm -/ + + Removes all jobs (for the default printer) belonging to + you. + + <tag/lprm <it/user// + + Removes all jobs (for the default printer) belonging to + <it/user/. The superuser can remove other users' jobs; + you can remove only your own jobs. + + <tag/lprm/ + + With no job number, user name, or ``<tt/-/'' appearing + on the command line, <tt/lprm/ removes the currently + active job on the default printer, if it belongs to + you. The superuser can remove any active job. + </descrip> + + Just use the <tt/-P/ option with the above shortcuts to + operate on a specific printer instead of the default. For + example, the following command removes all jobs for the + current user in the queue for the printer named <tt/rattan/: + +<tscreen><verb> +lprm -P rattan - +</verb></tscreen> + + <em/Note:/ If you're working in a networked environment, + <tt/lprm/ will let you remove jobs only from the host from + which the jobs were submitted, even if the same printer is + available from other hosts. The following command sequence + demonstrates this: +<code> +rose% lpr -P rattan myfile +rose% rlogin orchid +orchid% lpq -P rattan +Rank Owner Job Files Total Size +active seeyan 12 ... 49123 bytes +2nd kelly 13 myfile 12 bytes +orchid% lprm -P rattan 13 +rose: Permission denied +orchid% logout +rose% lprm -P rattan 13 +dfA013rose dequeued +cfA013rose dequeued +rose% +</code> + + <sect1><heading>Beyond Plain Text: Printing Options<label + id="printing:lpr:options"></heading> + + <p> The <tt/lpr/ command supports a number of options that + control formatting text, converting graphic and other file + formats, producing multiple copies, handling of the job, and + more. This section describes the options. + + <sect2><heading>Formatting and Conversion Options<label + id="printing:lpr:options:format"></heading> + + <p> The following <tt/lpr/ options control formatting of the + files in the job. Use these options if the job doesn't + contain plain text or if you want plain text formatted + through the <tt/pr/ utility. + + For example, the following command prints a DVI file (from + the TeX typesetting system) named <tt/fish-report.dvi/ + to the printer named <tt/bamboo/: +<tscreen><verb> +lpr -P bamboo -d fish-report.dvi +</verb></tscreen> + These options apply to every file in the job, so you can't + mix (say) DVI and ditroff files together in a job. + Instead, submit the files as separate jobs, using a + different conversion option for each job. + + <em/Note:/ All of these options except <tt/-p/ and <tt/-T/ + require conversion filters installed for the destination + printer. For example, the <tt/-d/ option requires the DVI + conversion filter. Section <ref + id="printing:advanced:convfilters" name="Conversion + Filters"> gives details. + + <descrip> + <tag/<tt/-c// Print cifplot files. + + <tag/<tt/-d// Print DVI files. + + <tag/<tt/-f// Print FORTRAN text files. + + <tag/<tt/-g// Print plot data. + + <tag/<tt/-i <it/number/// + + Indent the output by <it/number/ columns; if you omit + <it/number/, indent by 8 columns. This option works + only with certain conversion filters. + + <em/Note:/ Don't put any space between the <tt/-i/ and + the number. + + <tag/<tt/-l// + + Print literal text data, including control characters. + + <tag/<tt/-n// Print ditroff (device indepdendent troff) data. + + <tag/-p/ + + Format plain text with <tt/pr/ before printing. See + pr(1) for more information. + + <tag/<tt/-T <it/title/// + + Use <it/title/ on the <tt/pr/ header instead of the + file name. This option has effect only when used with + the <tt/-p/ option. + + <tag/<tt/-t// Print troff data. + + <tag/<tt/-v// Print raster data. + + </descrip> + + Here's an example: this command prints a nicely + formatted version of the <tt/ls/ manual page on the + default printer: +<tscreen><verb> +zcat /usr/share/man/man1/ls.1.gz | troff -t -man | lpr -t +</verb></tscreen> + The <tt/zcat/ command uncompresses the source of the + <tt/ls/ manual page and passes it to the <tt/troff/ + command, which formats that source and makes GNU troff + output and passes it to <tt/lpr/, which submits the job to + the LPD spooler. Because we used the <tt/-t/ option to + <tt/lpr/, the spooler will convert the GNU troff output + into a format the default printer can understand when it + prints the job. + + <sect2><heading>Job Handling Options<label + id="printing:lpr:options:job-handling"></heading> + + <p> The following options to <tt/lpr/ tell LPD to handle the + job specially: + + <descrip> + <tag/-# <it/copies// + + Produce a number of <it/copies/ of each file in the + job instead of just one copy. An administrator may + disable this option to reduce printer wear-and-tear + and encourage photocopier usage. See section <ref + id="printing:advanced:restricting:copies" + name="Restricting Multiple Copies">. + + <p> This example prints three copies of <tt/parser.c/ + followed by three copies of <tt/parser.h/ to the + default printer: +<tscreen><verb> +lpr -#3 parser.c parser.h +</verb></tscreen> + + <tag/-m/ + + Send mail after completing the print job. With this + option, the LPD system will send mail to your account + when it finishes handling your job. In its message, + it will tell you if the job completed successfully or + if there was an error, and (often) what the error was. + + <tag/-s/ Don't copy the files to the spooling directory, + but make symbolic links to them instead. + + If you're printing a large job, you probably want to + use this option. It saves space in the spooling + directory (your job might overflow the free space on + the filesystem where the spooling directory resides). + It saves time as well since LPD won't have to copy + each and every byte of your job to the spooling + directory. + + There is a drawback, though: since LPD will refer to + the original files directly, you can't modify or + remove them until they have been printed. + + <em/Note:/ If you're printing to a remote printer, LPD + will eventually have to copy files from the local host + to the remote host, so the <tt/-s/ option will save + space only on the local spooling directory, not the + remote. It's still useful, though. + + <tag/-r/ + + Remove the files in the job after copying them to the + spooling directory, or after printing them with the + <tt/-s/ option. Be careful with this option! + + </descrip> + + <sect2><heading>Header Page Options<label + id="printing:lpr:options:misc"></heading> + + <p> These options to <tt/lpr/ adjust the text that normally + appears on a job's header page. If header pages are + suppressed for the destination printer, these options have + no effect. See section <ref name="Header Pages" + id="printing:advanced:header-pages"> for information about + setting up header pages. + + <descrip> + <tag/-C <it/text// + + Replace the hostname on the header page with + <it/text/. The hostname is normally the name of the + host from which the job was submitted. + + <tag/-J <it/text// + + Replace the job name on the header page with + <it/text/. The job name is normally the name of the + first file of the job, or ``stdin'' if you're printing + standard input. + + <tag/-h/ + + Do not print any header page. <em/Note:/ At some + sites, this option may have no effect due to the way + header pages are generated. See <ref name="Header + Pages" id="printing:advanced:header-pages"> for + details. + + </descrip> + + <sect1><heading>Administrating Printers<label + id="printing:lpc"></heading> + + <p> As an administrator for your printers, you've had to + install, set up, and test them. Using the <tt/lpc/ command, + you can interact with your printers in yet more ways. With + <tt/lpc/, you can + + <itemize> + <item>Start and stop the printers + + <item>Enable and disable their queues + + <item>Rearrange the order of the jobs in each queue. + </itemize> + + First, a note about terminology: if a printer is + <em/stopped/, it won't print anything in its queue. Users + can still submit jobs, which will wait in the queue until + the printer is <em/started/ or the queue is cleared. + + If a queue is <em/disabled/, no user (except root) can + submit jobs for the printer. An <em/enabled/ queue allows + jobs to be submitted. A printer can be <em/started/ for a + disabled queue, in which case it'll continue to print jobs + in the queue until the queue is empty. + + In general, you have to have root privileges to use the + <tt/lpc/ command. Ordinary users can use the <tt/lpc/ + command to get printer status and to restart a hung printer + only. + + Here is a summary of the <tt/lpc/ commands. Most of the + commands takes a <it/printer-name/ argument to tell on which + printer to operate. You can use <tt/all/ for the + <it/printer-name/ to mean all printers listed in + <tt>/etc/printcap</tt>. + + <descrip> + <tag/<tt/abort <it/printer-name/// + + Cancel the current job and stop the printer. Users can + still submit jobs if the queue's enabled. + + <tag/<tt/clean <it/printer-name/// + + Remove old files from the printer's spooling directory. + Occasionally, the files that make up a job aren't + properly removed by LPD, particularly if there have been + errors during printing or a lot of administrative + activity. This command finds files that don't belong in + the spooling directory and removes them. + + <tag/<tt/disable <it/printer-name/// + + Disable queuing of new jobs. If the printer's started, + it will continue to print any jobs remaining in the + queue. The superuser (root) can always submit jobs, + even to a disabled queue. + + This command is useful while you're testing a new + printer or filter installation: disable the queue and + submit jobs as root. Other users won't be able to + submit jobs until you complete your testing and reenable + the queue with the <tt/enable/ command. + + <tag/<tt/down <it/printer-name/ <it/message.../// + + Take a printer down. Equivalent to <tt/disable/ + followed by <tt/stop/. The <it/message/ appears as the + printer's status whenever a user checks the printer's + queue with <tt/lpq/ or status with <tt/lpc status/. + + <tag/<tt/enable <it/printer-name/// + + Enable the queue for a printer. Users can submit jobs + but the printer won't print anything until it's started. + + <tag/<tt/help <it/command-name/// + + Print help on the command <it/command-name/. With no + <it/command-name/, print a summary of the commands + available. + + <tag/<tt/restart <it/printer-name/// + + Start the printer. Ordinary users can use this command + if some extraordinary circumstance hangs LPD, but they + can't start a printer stopped with either the <tt/stop/ + or <tt/down/ commands. The <tt/restart/ command is + equivalent to <tt/abort/ followed by <tt/start/. + + <tag/<tt/start <it/printer-name/// + + Start the printer. The printer will print jobs in its + queue. + + <tag/<tt/stop <it/printer-name/// + + Stop the printer. The printer will finish the current + job and won't print anything else in its queue. Even + though the printer is stopped, users can still submit + jobs to an enabled queue. + + <tag/<tt/topq <it/printer-name/ <it/job-or-username.../// + + Rearrange the queue for <it/printer-name/ by placing the + jobs with the listed <it/job/ numbers or the jobs + belonging to <it/username/ at the top of the queue. For + this command, you can't use <tt/all/ as the + <it/printer-name/. + + <tag/<tt/up <it/printer-name/// + + Bring a printer up; the opposite of the <tt/down/ + command. Equivalent to <tt/start/ followed by + <tt/enable/. + + </descrip> + + <tt/lpc/ accepts the above commands on the command line. If + you don't enter any commands, <tt/lpc/ enters an interactive + mode, where you can enter commands until you type <tt/exit/, + <tt/quit/, or end-of-file. + + <sect><heading>Advanced Printer Setup<label + id="printing:advanced"></heading> + + <p> This section describes filters for printing specially + formatted files, header pages, printing across networks, and + restricting and accounting for printer usage. + + <sect1><heading>Filters<label + id="printing:advanced:filter-intro"></heading> + + <p> Although LPD handles network protocols, queuing, access + control, and other aspects of printing, most of the + <em/real/ work happens in the <em/filters/. Filters are + programs that communicate with the printer and handle its + device dependencies and special requirements. In the simple + printer setup, we installed a plain text filter---an + extremely simple one that should work with most printers + (section <ref id="printing:textfilter" name="Installing the + Text Filter">). + + However, in order to take advantage of format conversion, + printer accounting, specific printer quirks, and so on, you + should understand how filters work. It will ultimately be + the filter's responsibility to handle these aspects. And the + bad news is that most of the time <em/you/ have to provide + filters yourself. The good news is that many are generally + available; when they're not, they're usually easy to write. + + Also, FreeBSD comes with one, <tt>/usr/libexec/lpr/lpf</tt>, + that works with many printers that can print plain text. + (It handles backspacing and tabs in the file, and does + accounting, but that's about all it does.) There are also + several filters and filter components in the FreeBSD ports + collection. + + Here's what you'll find in this section: + + <itemize> + <item>Section <ref id="printing:advanced:filters" + name="How Fitlers Work">, tries to give an overview of a + filter's role in the printing process. You should read + this section to get an understanding of what's happening + ``under the hood'' when LPD uses filters. This + knowledge could help you anticipate and debug problems + you might encounter as you install more and more filters + on each of your printers. + + <item>LPD expects every printer to be able to print plain + text by default. This presents a problem for PostScript + (or other language-based printers) which can't directly + print plain text. Section <ref + id="printing:advanced:if-conversion" name="Accomodating + Plain Text Jobs on PostScript Printers"> tells you what + you should do to overcome this problem. I recommend + reading this section if you have a PostScript printer. + + <item>PostScript is a popular output format for many + programs. Even some people (myself included) write + PostScript code directly. But PostScript printers are + expensive. Section <ref id="printing:advanced:ps" + name="Simulating PostScript on Non-PostScript Printers"> + tells how you can further modify a printer's text filter + to accept and print PostScript data on a + <em/non-PostScript/ printer. I recommend reading this + section if you don't have a PostScript printer. + + <item>Section <ref id="printing:advanced:convfilters" + name="Conversion Filters"> tells about a way you can + automate the conversion of specific file formats, such + as graphic or typesetting data, into formats your + printer can understand. After reading this section, + you should be able to set up your printers such that + users can type <tt/lpr -t/ to print troff data, or + <tt/lpr -d/ to print TeX DVI data, or <tt/lpr -v/ to + print raster image data, and so forth. I recommend + reading this section. + + <item>Section <ref id="printing:advanced:of" name="Output + Filters"> tells all about a not often used feature of + LPD: output filters. Unless you're printing header + pages (see <ref id="printing:advanced:header-pages" + name="Header Pages">), you can probably skip that + section altogether. + + <item>Section <ref id="printing:advanced:lpf" name="lpf: + a Text Filter"> describes <tt/lpf/, a fairly complete + if simple text filter for line printers (and laser + printers that act like line printers) that comes with + FreeBSD. If you need a quick way to get printer + accounting working for plain text, or if you have a + printer which emits smoke when it sees backspace + characters, you should definitely consider <tt/lpf/. + </itemize> + + <sect2><heading>How Filters Work<label + id="printing:advanced:filters"></heading> + + <p> As mentioned before, a filter is an executable program + started by LPD to handle the device-dependent part of + communicating with the printer. + + When LPD wants to print a file in a job, it starts a + filter program. It sets the filter's standard input to + the file to print, its standard output to the printer, and + its standard error to the error logging file (specified in + the <tt/lf/ capability in <tt>/etc/printcap</tt>, or + <tt>/dev/console</tt> by default). + + Which filter LPD starts and the filter's arguments depend + on what's listed in the <tt>/etc/printcap</tt> file and + what arguments the user specified for the job on the + <tt/lpr/ command line. For example, if the user typed + <tt/lpr -t/, LPD would start the troff filter, listed in + the <tt/tf/ capability for the destination printer. If + the user wanted to print plain text, it would start the + <tt/if/ filter (this is mostly true: see <ref + id="printing:advanced:of" name="Output Filters"> for + details). + + There are three kinds filters you can specify in + <tt>/etc/printcap</tt>: + <itemize> + <item>The <em/text filter/, confusingly called the + <em/input filter/ in LPD documentation, handles + regular text printing. Think of it as the default + filter. LPD expects every printer to be able to print + plain text by default, and it's the text filter's job + to make sure backspaces, tabs, or other special + characters don't confuse the printer. + + If you're in an environment where you have to account + for printer usage, the text filter must also account + for pages printed, usually by counting the number of + lines printed and comparing that to the number of + lines per page the printer supports. + + The text filter is started with the following argument + list: +<tscreen> +<tt>[-c] -w<it/width/ -l<it/length/ -i<it/indent/ -n <it/login/ -h <it/host/ <it/acct-file/</tt> +</tscreen> + where + <descrip> + <tag/<tt/-c// + + appears if the job's submitted with <tt/lpr -l/ + + <tag/<tt/<it/width/// + + is the value from the <tt/pw/ (page width) + capability specified in <tt>/etc/printcap</tt>, + default 132 + + <tag/<tt/<it/length/// + + is the value from the <tt/pl/ (page length) + capability, default 66 + + <tag/<tt/<it/indent/// + + is the amount of the indentation from <tt/lpr -i/, + default 0 + + <tag/<tt/<it/login/// + + is the account name of the user printing the file + + <tag/<tt/<it/host/// + + is the host name from which the job was submitted + + <tag/<tt/<it/acct-file/// + + is the name of the accounting file from the <tt/af/ + capability. + + </descrip> + + <item>A <em/conversion filter/ converts a specific file + format into one the printer can render onto paper. + For example, ditroff typesetting data can't be + directly printed, but you can install a conversion + filter for ditroff files to convert the ditroff data + into a form the printer can digest and print. Section + <ref id="printing:advanced:convfilters" + name="Conversion Filters"> tells all about them. + Conversion filters also need to do accounting, if you + need printer accounting. + + Conversion filters are started with the following + arguments: +<tscreen> +<tt>-x<it/pixel-width/ -y<it/pixel-height/ -n <it/login/ -h <it/host/ <it/acct-file/</tt> +</tscreen> + where <it/pixel-width/ is the value from the <tt/px/ + capability (default 0) and <it/pixel-height/ is the + value from the <tt/py/ capability (default 0). + + <item>The <em/output filter/ is used only if there's no + text filter, or if header pages are enabled. In my + experience, output filters are rarely used. Section + <ref id="printing:advanced:of" name="Output Filters"> + describe them. There are only two arguments to an + output filter: +<tscreen> +<tt>-w<it/width/ -l<it/length/</tt> +</tscreen> + which are identical to the text filters <tt/-w/ and + <tt/-l/ arguments. + </itemize> + + Filters should also <em/exit/ with the following exit + status: + <descrip> + <tag/exit 0/ + + If the filter printed the file successfully. + + <tag/exit 1/ + + If the filter failed to print the file but wants LPD + to try to print the file again. LPD will restart a + filter if it exits with this status. + + <tag/exit 2/ + + If the filter failed to print the file and doesn't + want LPD to try again. LPD will throw out the file. + </descrip> + + The text filter that comes with the FreeBSD release, + <tt>/usr/libexec/lpr/lpf</tt>, takes advantage of the page + width and length arguments to determine when to send a + form feed and how to account for printer usage. It uses + the login, host, and accounting file arguments to make the + accounting entries. + + If you're shopping for filters, see if they're + LPD-compatible. If they are, they must support the + argument lists described above. If you plan on writing + filters for general use, then have them support the same + argument lists and exit codes. + + <sect2><heading>Accommodating Plain Text Jobs on PostScript Printers + <label id="printing:advanced:if-conversion"></heading> + + <p> If you're the only user of your computer and PostScript + (or other language-based) printer, and you promise to + never send plain text to your printer and to never use + features of various programs that will want to send plain + text to your printer, then you don't need to worry about + this section at all. + + But, if you would like to send both PostScript and plain + text jobs to the printer, then you're urged to augment + your printer setup. To do so, we have the text filter + detect if the arriving job is plain text or PostScript. + All PostScript jobs must start with <tt/%!/ (for + other printer languages, see your printer documentation). + If those are the first two characters in the job, we have + PostScript, and can pass the rest of the job directly. If + those aren't the first two characters in the file, then + the filter will convert the text into PostScript and print + the result. + + How do we do this? + + If you've got a serial printer, a great way to do it is to + install <tt/lprps/. <tt/lprps/ is a PostScript printer + filter which performs two-way communication with the + printer. It updates the printer's status file with + verbose information from the printer, so users and + administrators can see exactly what the state of the + printer is (such as ``toner low'' or ``paper jam''). But + more importantly, it includes a program called <tt/psif/ + which detects whether the incoming job is plain text and + calls <tt/textps/ (another program that comes with + <tt/lprps/) to convert it to PostScript. It then uses + <tt/lprps/ to send the job to the printer. + + <tt/lprps/ should be part of the FreeBSD ports collection + (see <ref id="ports" name="The Ports Collection">); if not, + it should be shortly. You can fetch, build and install it + yourself, of course. After installing <tt/lprps/, just + specify the pathname to the <tt/psif/ program that's part + of <tt/lprps/. If you installed <tt/lprps/ from the ports + collection, use the following in the serial PostScript + printer's entry in <tt>/etc/printcap</tt>: +<tscreen><verb> + :if=/usr/local/libexec/psif: +</verb></tscreen> + You should also specify the <tt/rw/ capability; that tells + LPD to open the printer in read-write mode. + + If you have a parralel PostScript printer (and therefore + can't use two-way communication with the printer, which + <tt/lprps/ needs), you can use the following shell script + as the text filter: +<code> +#!/bin/sh +# +# psif - Print PostScript or plain text on a PostScript printer +# Script version; NOT the version that comes with lprps +# Installed in /usr/local/libexec/psif +# + +read first_line +first_two_chars=`expr "$first_line" : '\(..\)'` + +if [ "$first_two_chars" = "%!" ]; then + # + # PostScript job, print it. + # + echo $first_line &ero;&ero; cat &ero;&ero; printf "\004" &ero;&ero; exit 0 + exit 2 +else + # + # Plain text, convert it, then print it. + # + ( echo $first_line; cat ) | /usr/local/bin/textps &ero;&ero; printf "\004" &ero;&ero; exit 0 + exit 2 +fi +</code> + In the above script, <tt/textps/ is a program we installed + separately to convert plain text to PostScript. You can + use any text-to-PostScript program you wish. The FreeBSD + ports collection (see <ref id="ports" name="The Ports + Collection">) includes a full featured text-to-PostScript + program called <tt/a2ps/ that you might want to + investigate. + + <sect2><heading>Simulating PostScript on Non-PostScript Printers + <label id="printing:advanced:ps"></heading> + + <p> PostScript is the <it/de facto/ standard for high + quality typesetting and printing. PostScript is, however, + an <em/expensive/ standard. Thankfully, Alladin + Enterprises has a free PostScript workalike called + <it/Ghostscript/ that runs with FreeBSD. Ghostscript can + read most PostScript files and can render their pages onto + a variety of devices, including many brands of + non-PostScript printers. By installing Ghostscript and + using a special text filter for your printer, you can make + your non-PostScript printer act like a real PostScript + printer. + + Ghostscript should be in the FreeBSD ports collection, if + you'd like to install it from there. You can fetch, + build, and install it quite easily yourself, as well. + + To simulate PostScript, we have the text filter detect if + it's printing a PostScript file. If it's not, then the + filter will pass the file directly to the printer; + otherwise, it will use Ghostscript to first convert the + file into a format the printer will understand. + + Here's an example: the following script is a text filter + for Hewlett Packard DeskJet 500 printers. For other + printers, substitute the <tt/-sDEVICE/ argument to the + <tt/gs/ (Ghostscript) command. (Type <tt/gs -h/ to get a + list of devices the current installation of Ghostscript + supports.) +<code> +#!/bin/sh +# +# ifhp - Print Ghostscript-simulated PostScript on a DesJet 500 +# Installed in /usr/local/libexec/hpif + +# +# Treat LF as CR+LF: +# +printf "\033&ero;k2G" || exit 2 + +# +# Read first two characters of the file +# +read first_line +first_two_chars=`expr "$first_line" : '\(..\)'` + +if [ "$first_two_chars" = "%!" ]; then + # + # It's PostScript; use Ghostscript to scan-convert and print it + # + /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 -sOutputFile=- - \ + &ero;&ero; exit 0 + +else + # + # Plain text or HP/PCL, so just print it directly; print a form + # at the end to eject the last page. + # + echo $first_line &ero;&ero; cat &ero;&ero; printf "\f" &ero;&ero; exit 2 +fi + +exit 2 +</code> + Finally, you need to notify LPD of the filter via the + <tt/if/ capability: +<tscreen><verb> + :if=/usr/local/libexec/hpif: +</verb></tscreen> + That's it. You can type <tt/lpr plain.text/ and <tt/lpr + whatever.ps/ and both should print successfully. + + + <sect2><heading>Conversion Filters<label + id="printing:advanced:convfilters"></heading> + + <p> After completing the simple setup described in <ref + name="Simple Printer Setup" id="printing:simple">, the + first thing you'll probably want to do is install + conversion filters for your favorite file formats + (besides plain ASCII text). + + <sect3><heading>Why Install Conversion Filters?</heading> + + <p> Conversion filters make printing various kinds of + files easy. As an example, suppose we do a lot of work + with the TeX typesetting system, and we have a + PostScript printer. Every time we generate a DVI file + from TeX, we can't print it directly until we convert + the DVI file into PostScript. The command sequence + goes like this: +<tscreen><verb> +dvips seaweed-analysis.dvi +lpr seaweed-analysis.ps +</verb></tscreen> + By installing a conversion filter for DVI files, we can + skip the hand conversion step each time by having LPD do + it for us. Now, each time we get a DVI file, we're just + one step away from printing it: +<tscreen><verb> +lpr -d seaweed-analysis.dvi +</verb></tscreen> + We got LPD to do the DVI file conversion for us by + specifying the <tt/-d/ option. Section <ref + id="printing:lpr:options:format" name="Formatting and + Conversion Options"> lists the conversion options. + + For each of the conversion options you want a printer to + support, install a <em/conversion filter/ and specify + its pathname in <tt>/etc/printcap</tt>. A conversion + filter is like the text filter for the simple printer + setup (see section <ref id="printing:textfilter" + name="Installing the Text Filter">) except that instead + of printing plain text, the filter converts the file + into a format the printer can understand. + + <sect3><heading>Which Conversions Filters Should I Install? + </heading> + + <p> You should install the conversion filters you expect + to use. If you print a lot of DVI data, then a DVI + conversion filter is in order. If you've got plenty of + troff to print out, then you probably want a troff + filter. + + The following table summarizes the filters that LPD + works with, their capability entries for the + <tt>/etc/printcap</tt> file, and how to invoke them with + the <tt/lpr/ command: +<code> + /etc/printcap +File type Capability lpr option +------------ ------------- ---------- +cifplot cf -c +DVI df -d +plot gf -g +ditroff nf -n +FORTRAN text rf -f +troff tf -t +raster vf -v +plain text if none, -p, or -l +</code> + + In our example, using <tt/lpr -d/ means the printer + needs a <tt/df/ capability in its entry in + <tt>/etc/printcap</tt>. + + Despite what others might contend, formats like FORTRAN + text and plot are probably obsolete. At your site, you + can give new meanings to these or any of the formatting + options just by installing custom filters. For example, + suppose you'd like to directly print Printerleaf files + (files from the Interleaf desktop publishing program), + but will never print plot files. You could install a + Printerleaf conversion filter under the <tt/gf/ + capability and then educate your users that <tt/lpr -g/ + mean ``print Printerleaf files.'' + + <sect3><heading>Installing Conversion Filters</heading> + + <p> Since conversion filters are programs you install + outside of the base FreeBSD installation, they should + probably go under <tt>/usr/local</tt>. The directory + <tt>/usr/local/libexec</tt> is a popular location, since + they they're specialized programs that only LPD will + run; regular users shouldn't ever need to run them. + + To enable a conversion filter, specify its pathname + under the appropriate capability for the destination + printer in <tt>/etc/printcap</tt>. + + In our example, we'll add the DVI conversion filter to + the entry for the printer named <tt/bamboo/. Here's the + example <tt>/etc/printcap</tt> file again, with the new + <tt/df/ capability for the printer <tt/bamboo/ +<code> +# +# /etc/printcap for host rose - added df filter for bamboo +# +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :sh:sd=/var/spool/lpd/rattan:\ + :lp=/dev/lpt0:\ + :if=/usr/local/libexec/if-simple: + +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :sh:sd=/var/spool/lpd/bamboo:\ + :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\ + :if=/usr/local/libexec/psif:\ + :df=/usr/local/libexec/psdf: +</code> + The DVI filter is a shell script named + <tt>/usr/local/libexec/psdf</tt>. Here's that script: +<code> +#!bin/sh +# +# DVI to PostScript printer filter +# Installed in /usr/local/libexec/psdf +# +# Invoked by lpd when user runs lpr -d +# +exec /usr/local/bin/dvips -f | /usr/local/libexec/lprps "$@" +</code> + This script runs <tt/dvips/ in filter mode (the <tt/-f/ + argument) on standard input, which is the job to print. + It then starts the PostScript printer filter <tt/lprps/ + (see section <ref id="printing:advanced:if-conversion" + name="Accomodating Plain Text Jobs on PostScript + Printers">) with the arguments LPD passed to this script. + <tt/lprps/ will use those arguments to account for the + pages printed. + + <sect3><heading>More Conversion Filter Examples</heading> + + <p> Since there's no fixed set of steps to install + conversion filters, let me instead provide more + examples. Use these as guidance to making your own + filters. Use them directly, if appropriate. + + This example script is a raster (well, GIF file, + actually) conversion filter for a Hewlett Packard + LaserJet III-Si printer: +<code> +#!/bin/sh +# +# hpvf - Convert GIF files into HP/PCL, then print +# Installed in /usr/local/libexec/hpvf + +PATH=/usr/X11R6/bin:$PATH; export PATH + +giftopnm | ppmtopgm | pgmtopbm | pbmtolj -resolution 300 \ + && exit 0 \ + || exit 2 +</code> + It works by converting the GIF file into a portable + anymap, converting that into a portable graymap, + converting that into a portable bitmap, and converting + that into LaserJet/PCL-compatible data. + + Here's the <tt>/etc/printcap</tt> file with an entry for + a printer using the above filter: +<code> +# +# /etc/printcap for host orchid +# +teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ + :lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:\ + :if=/usr/local/libexec/hpif:\ + :vf=/usr/local/libexec/hpvf: +</code> + + The following script is a conversion filter for troff + data from the groff typesetting system for the + PostScript printer named <tt/bamboo/: +<code> +#!/bin/sh +# +# pstf - Convert groff's troff data into PS, then print. +# Installed in /usr/local/libexec/pstf +# +exec grops | /usr/local/libexec/lprps "$@" +</code> + The above script makes use of <tt/lprps/ again to handle + the communication with the printer. If the printer were + on a parallel port, we'd use this script instead: +<code> +#!/bin/sh +# +# pstf - Convert groff's troff data into PS, then print. +# Installed in /usr/local/libexec/pstf +# +exec grops +</code> + That's it. Here's the entry we need to add to + <tt>/etc/printcap</tt> to enable the filter: +<tscreen><verb> + :tf=/usr/local/libexec/pstf: +</verb></tscreen> + + Here's an example that might make old hands at FORTRAN + blush. It's a FORTRAN-text filter for any printer that + can directly print plain text. We'll install it for the + printer <tt/teak/: +<code> +#!/bin/sh +# +# hprf - FORTRAN text filter for LaserJet 3si: +# Installed in /usr/local/libexec/hprf +# + +printf "\033&ero;k2G" &ero;&ero; fpr &ero;&ero; printf "\f" &ero;&ero; exit 0 +exit 2 +</code> + And we'll add this line to the <tt>/etc/printcap</tt> + for the printer <tt/teak/ to enable this filter: +<tscreen><verb> + :rf=/usr/local/libexec/hprf: +</verb></tscreen> + + Here's one final, somewhat complex example. We'll add a + DVI filter to the LaserJet printer <tt/teak/ introduced + earlier. First, the easy part: updating + <tt>/etc/printcap</tt> with the location of the DVI + filter: +<tscreen><verb> + :df=/usr/local/libexec/hpdf: +</verb></tscreen> + + Now, for the hard part: making the filter. For that, we + need a DVI-to-LaserJet/PCL conversion program. The + FreeBSD ports collection (see <ref id="ports" name="The + Ports Collection">) has one: <tt/dvi2xx/ is the name of + the package. Installing this package gives us the + program we need, <tt/dvilj2p/, which converts DVI into + LaserJet IIp, LaserJet III, and LaserJet 2000 compatible + codes. + + <tt/dvilj2p/ makes the filter <tt/hpdf/ quite complex + since <tt/dvilj2p/ can't read from standard input. It + wants to work with a filename. What's worse, the + filename has to end in <tt/.dvi/ so using + <tt>/dev/fd/0</tt> for standard input is problematic. + We can get around that problem by linking (symbolically) + a temporary file name (one that ends in <tt/.dvi/) to + <tt>/dev/fd/0</tt>, thereby forcing <tt/dvilj2p/ to read + from standard input. + + The only other fly in the ointment is the fact that we + can't use /tmp for the temporary link. Symbolic links + are owned by user and group <tt/bin/. The filter runs + as user <tt/daemon/. And the <tt>/tmp</tt> directory + has the sticky bit set. The filter can create the link, + but it won't be able clean up when done and remove it + since the link will belong to a different user. + + Instead, the filter will make the symbolic link in the + current working directory, which is the spooling + directory (specified by the <tt/sd/ capability in + <tt>/etc/printcap</tt>). This is a perfect place for + filters to do their work, especially since there's + (sometimes) more free disk space in the spooling directory + than under <tt>/tmp</tt>. + + Here, finally, is the filter: +<code> +#!/bin/sh +# +# hpdf - Print DVI data on HP/PCL printer +# Installed in /usr/local/libexec/hpdf + +PATH=/usr/local/bin:$PATH; export PATH + +# +# Define a function to clean up our temporary files. These exist +# in the current directory, which will be the spooling directory +# for the printer. +# +cleanup() { + rm -f hpdf$$.dvi +} + +# +# Define a function to handle fatal errors: print the given message +# and exit 2. Exiting with 2 tells LPD to don't try to reprint the +# job. +# +fatal() { + echo "$@" 1>&ero;2 + cleanup + exit 2 +} + +# +# If user removes the job, LPD will send SIGINT, so trap SIGINT +# (and a few other signals) to clean up after ourselves. +# +trap cleanup 1 2 15 + +# +# Make sure we're not colliding with any existing files. +# +cleanup + +# +# Link the DVI input file to standard input (the file to print). +# +ln -s /dev/fd/0 hpdf$$.dvi || fatal "Cannot symlink /dev/fd/0" + +# +# Make LF = CR+LF +# +printf "\033&ero;k2G" || fatal "Cannot initialize printer" + +# +# Convert and print. Return value from dvilj2p doesn't seem to be +# reliable, so we ignore it. +# +dvilj2p -M1 -q -e- dfhp$$.dvi + +# +# Clean up and exit +# +cleanup +exit 0 +</code> + + <sect3><heading>Automated Conversion: An Alternative To Conversion Filters + <label id="printing:advanced:autoconv"></heading> + + <p> All these conversion filters accomplish a lot for your + printing environment, but at the cost forcing the user + to specify (on the <tt/lpr/ command line) which one to + use. If your users aren't particularly computer + literate, having to specify a filter option will become + annoying. What's worse, though, is that an incorrectly + specified filter option may run a filter on the wrong + type of file and cause your printer to spew out hundreds + of sheets of paper. + + Rather than install conversion filters at all, you might + want to try having the text filter (since it's the + default filter) detect the type of file it's asked to + print and then automatically run the right conversion + filter. Tools such as <tt/file/ can be of help here. + Of course, it'll be hard to determine the differences + between <em/some/ file types---and, of course, you can + still provide conversion filters just for them. + + The FreeBSD ports collection has a text filter that + performs automatic conversion called <tt/apsfilter/. It + can detect plain text, PostScript, and DVI files, run + the proper conversions, and print. + + <sect2><heading>Output Filters<label + id="printing:advanced:of"></heading> + + <p> The LPD spooling system supports one other type of + filter that we've not yet explored: an output filter. An + output filter is intended for printing plain text only, + like the text filter, but with many simplifications. If + you're using an output filter but no text filter, then + <itemize> + <item>LPD starts an output filter once for the entire + job instead of once for each file in the job. + + <item>LPD doesn't make any provision to identify the + start or the end of files within the job for the + output filter. + + <item>LPD doesn't pass the user's login or host to + the filter, so it's not intended to do accounting. In + fact, it gets only two arguments: +<tscreen> +<tt>-w<it/width/ -l<it/length/</tt> +</tscreen> + where <it/width/ is from the <tt/pw/ capability and + <it/length/ is from the <tt/pl/ capability for the + printer in question. + </itemize> + + Don't be seduced by an output filter's simplicity. If + you'd like each file in a job to start on a different page + an output filter <em/won't work/. Use a text filter (also + known as an input filter); see section <ref + id="printing:textfilter" name="Installing the Text + Filter">. Furthermore, an output filter is actually + <em/more complex/ in that it has to examine the byte + stream being sent to it for special flag characters and + must send signals to itself on behalf of LPD. + + However, an output filter is <em/necessary/ if you want + header pages and need to send escape sequences or other + initialization strings to be able to print the header + page. (But it's also <em/futile/ if you want to charge + header pages to the requesting user's account, since LPD + doesn't give any user or host information to the output + filter.) + + On a single printer, LPD allows both an output filter and + text or other filters. In such cases, LPD will start the + output filter to print the header page (see section <ref + id="printing:advanced:header-pages" name="Header Pages">) + only. LPD then expects the output filter to <em/stop + itself/ by sending two bytes to the filter: ASCII 031 + followed by ASCII 001. When an output filter sees these + two bytes (031, 001), it should stop by sending SIGSTOP to + itself. When LPD's done running other filters, it'll + restart the output filter by sending SIGCONT to it. + + If there's an output filter but <em/no/ text filter and + LPD is working on a plain text job, LPD uses the output + filter to do the job. As stated before, the output filter + will print each file of the job in sequence with no + intervening form feeds or other paper advancement, and + this is probably <em/not/ what you want. In almost all + cases, you need a text filter. + + The program <tt/lpf/, whch we introduced earlier as a text + filter, can also run as an output filter. If you need a + quick-and-dirty output filter but don't want to write the + byte detection and signal sending code, try <tt/lpf/. You + can also wrap <tt/lpf/ in a shell script to handle any + intialization codes the printer might require. + + <sect2><heading><tt/lpf/: a Text Filter<label + id="printing:advanced:lpf"></heading> + + <p> The program <tt>/usr/libexec/lpr/lpf</tt> that comes + with FreeBSD binary distribution is a text filter (input + filter) that can indent output (job submitted with <tt/lpr + -i/), allow literal characters to pass (job submitted with + <tt/lpr -l/), adjust the printing position for backspaces + and tabs in the job, and account for pages printed. It + can also act like an output filter. + + <tt/lpf/ is suitable for many printing environments. And + although it has no capability to send initialization + sequences to a printer, it's easy to write a shell script + to do the needed initialization and then execute <tt/lpf/. + + In order for <tt/lpf/ to do page accounting correctly, it + needs correct values filled in for the <tt/pw/ and <tt/pl/ + capabilities in the <tt>/etc/printcap</tt> file. It uses + these values to determine how much text can fit on a page + and how many pages were in a user's job. For more + information on printer accounting, see <ref + id="printing:advanced:acct" name="Accounting for Printer + Usage">. + + <sect1><heading>Header Pages<label + id="printing:advanced:header-pages"></heading> + + <p> If you've got <em/lots/ of users, all of them using + various printers, then you probably want to consider + <em/header pages/ as a necessary evil. + + Header pages, also known as <em/banner/ or <em/burst pages/ + identify to whom jobs belong after they're printed. They're + usually printed in large, bold letters, perhaps with + decorative borders, so that in a stack of printouts they + stand out from the real documents that comprise users' jobs. + They enable users to locate their jobs quickly. The obvious + drawback to a header page is that it's yet one more sheet + that has to be printed for every job, their ephemeral + usefulness lasting not more than a few minutes, ultimately + finding themselves in a recycling bin or rubbish heap. + (Note that header pages go with each job, not each file in a + job, so the paper waste might not be that bad.) + + The LPD system can provide header pages automatically for + your printouts <em/if/ your printer can directly print plain + text. If you've got a PostScript printer, you'll need an + external program to generate the header page; see <ref + id="printing:advanced:header-pages:ps" name="Header Pages on + PostScript Printers">. + + <sect2><heading>Enabling Header Pages<label + id="printing:advanced:header-pages:enabling"></heading> + + <p> In the <ref id="printing:simple" name="Simple Printer + Setup">, we turned off header pages by specifying + <tt/sh/ (meaning ``suppress header'') in the + <tt>/etc/printcap</tt> file. To enable header pages for + a printer, just remove the <tt/sh/ capability. + + Sounds too easy, right? + + You're right. You <em/might/ have to provide an output + filter to send initialization strings to the printer. + Here's an example output filter for Hewlett Packard + PCL-compatible printers: +<code> +#!/bin/sh +# +# hpof - Output filter for Hewlett Packard PCL-compatible printers +# Installed in /usr/local/libexec/hpof + + +printf "\033&ero;k2G" || exit 2 +exec /usr/libexec/lpr/lpf +</code> + Specify the path to the output filter in the <tt/of/ + capability. See <ref id="printing:advanced:of" + name="Output Filters"> for more information. + + Here's an example <tt>/etc/printcap</tt> file for the printer + <tt/teak/ that we introduced earlier; we enabled header + pages and added the above output filter: +<code> +# +# /etc/printcap for host orchid +# +teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ + :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:\ + :if=/usr/local/libexec/hpif:\ + :vf=/usr/local/libexec/hpvf:\ + :of=/usr/local/libexec/hpof: +</code> + Now, when users print jobs to <tt/teak/, they get a header + page with each job. If users want to spend time searching + for their printouts, they can suppress header pages by + submitting the job with <tt/lpr -h/; see <ref + id="printing:lpr:options:misc" name="Header Page Options"> + for more <tt/lpr/ options. + + <tt/Note:/ LPD prints a form feed character after the + header page. If your printer uses a different character + or sequence of characters to eject a page, specify them + with the <tt/ff/ capability in <tt>/etc/printcap</tt>. + + <sect2><heading>Controlling Header Pages<label + id="printing:advanced:header-pages:controlling"></heading> + + <p> By enabling header pages, LPD will produce a <em/long + header/, a full page of large letters identifying the + user, host, and job. Here's an example (kelly printed + the job named outline from host rose): +<tscreen><verb> +k ll ll +k l l +k l l +k k eeee l l y y +k k e e l l y y +k k eeeeee l l y y +kk k e l l y y +k k e e l l y yy +k k eeee lll lll yyy y + y + y y + yyyy + + + ll + t l i + t l + oooo u u ttttt l ii n nnn eeee +o o u u t l i nn n e e +o o u u t l i n n eeeeee +o o u u t l i n n e +o o u uu t t l i n n e e + oooo uuu u tt lll iii n n eeee + + + + + + + + + +r rrr oooo ssss eeee +rr r o o s s e e +r o o ss eeeeee +r o o ss e +r o o s s e e +r oooo ssss eeee + + + + + + + + Job: outline + Date: Sun Sep 17 11:04:58 1995 +</verb></tscreen> + LPD appends a form feed after this text so the job starts + on a new page (unless you've got <tt/sf/ (suppress form + feeds) in the destination printer's entry in + <tt>/etc/printcap</tt>). + + If you prefer, LPD can make a <em/short header/; specify + <tt/sb/ (short banner) in the <tt>/etc/printcap</tt> file. + The header page will look like this: +<tscreen><verb> +rose:kelly Job: outline Date: Sun Sep 17 11:07:51 1995 +</verb></tscreen> + Also by default, LPD prints the header page first, then + the job. To reverse that, specify <tt/hl/ (header last) + in <tt>/etc/printcap</tt>. + + <sect2><heading>Accounting for Header Pages<label + id="printing:advanced:header-pages:accounting"></heading> + + <p> Using LPD's built-in header pages enforces a particular + paradigm when it comes to printer accounting: header pages + must be <em/free of charge/. + + Why? + + Because the output filter is the only external program + that will have control when the header page is printed + that could do accounting, and it isn't provided with any + <em/user or host/ information or an accounting file, so it + has no idea whom to charge for printer use. It's also not + enough to just ``add one page'' to the text filter or any + of the conversion filters (which do have user and host + information) since users can suppress header pages with + <tt/lpr -h/. They could still be charged for header pages + they didn't print. Basically, <tt/lpr -h/ will be the + preferred option of environmentally-minded users, but you + can't offer any incentive to use it. + + It's <em/still not enough/ to have each of the filters + generate their own header pages (thereby being able to + charge for them). If users wanted the option of + suppressing the header pages with <tt/lpr -h/, they will + still get them and be charged for them since LPD does not + pass any knowledge of the <tt/-h/ option to any of the + filters. + + So, what are your options? + + You can + <itemize> + <item>Accept LPD's paradigm and make header pages free. + + <item>Install an alternative to LPD, such as LPDng or + PLP. Section <ref name="Alternatives to the Standard + Spooler" id="printing:lpd-alternatives"> tells more + about other spooling software you can substitute for + LPD. + + <item>Write a <em/smart/ output filter. Normally, an + output filter isn't meant to do anything more than + initialize a printer or do some simple character + conversion. It's suited for header pages and plain + text jobs (when there's no text (input) filter). + + But, if there is a text filter for the plain text + jobs, then LPD will start the output filter only for + the header pages. And the output filter can parse the + header page text that LPD generates to determine what + user and host to charge for the header page. The only + other problem with this method is that the output + filter still doesn't know what accounting file to use + (it's not passed the name of the file from the <tt/af/ + capability), but if you have a well-known accounting + file, you can hard-code that into the output filter. + + To facilitate the parsing step, use the <tt/sh/ (short + header) capability in <tt>/etc/printcap</tt>. + + Then again, all that might be too much trouble, and + users will certainly appreciate the more generous + system administrator who makes header pages free. + </itemize> + + <sect2><heading>Header Pages on PostScript Printers<label + id="printing:advanced:header-pages:ps"></heading> + + <p> As described above, LPD can generate a plain text header + page suitable for many printers. Of course, PostScript + can't directly print plain text, so the header page + feature of LPD is useless---or mostly so. + + One obvious way to get header pages is to have every + conversion filter and the text filter generate the header + page. The filters should should use the user and host + arguments to generate a suitable header page. The + drawback of this method is that users will always get a + header page, even if they submit jobs with <tt/lpr -h/. + + Let's explore this method. The following script takes + three arguments (user login name, host name, and job name) + and makes a simple PostScript header page: +<code> +#!/bin/sh +# +# make-ps-header - make a PostScript header page on stdout +# Installed in /usr/local/libexec/make-ps-header +# + +# +# These are PostScript units (72 to the inch). Modify for A4 or +# whatever size paper you're using: +# +page_width=612 +page_height=792 +border=72 + +# +# Check arguments +# +if [ $# -ne 3 ]; then + echo "Usage: `basename $0` <user> <host> <job>" 1>&ero;2 + exit 1 +fi + +# +# Save these, mostly for readability in the PostScript, below. +# +user=$1 +host=$2 +job=$3 +date=`date` + +# +# Send the PostScript code to stdout. +# +exec cat <<EOF +%!PS + +% +% Make sure we don't interfere with user's job that will follow +% +save + +% +% Make a thick, unpleasant border around the edge of the paper. +% +$border $border moveto +$page_width $border 2 mul sub 0 rlineto +0 $page_height $border 2 mul sub rlineto +currentscreen 3 -1 roll pop 100 3 1 roll setscreen +$border 2 mul $page_width sub 0 rlineto closepath +0.8 setgray 10 setlinewidth stroke 0 setgray + +% +% Display user's login name, nice and large and prominent +% +/Helvetica-Bold findfont 64 scalefont setfont +$page_width ($user) stringwidth pop sub 2 div $page_height 200 sub moveto +($user) show + +% +% Now show the boring particulars +% +/Helvetica findfont 14 scalefont setfont +/y 200 def +[ (Job:) (Host:) (Date:) ] { + 200 y moveto show /y y 18 sub def +} forall + +/Helvetica-Bold findfont 14 scalefont setfont +/y 200 def +[ ($job) ($host) ($date) ] { + 270 y moveto show /y y 18 sub def +} forall + +% +% That's it +% +restore +showpage +EOF +</code> + Now, each of the conversion filters and the text filter + can call this script to first generate the header page, + and then print the user's job. Here's the DVI conversion + filter from earlier in this document, modified to make a + header page: +<code> +#!/bin/sh +# +# DVI to PostScript printer filter +# Installed in /usr/local/libexec/psdf +# +# Invoked by lpd when user runs lpr -d +# + +orig_args="$@" + +fail() { + echo "$@" 1>&ero;2 + exit 2 +} + +while getopts "x:y:n:h:" option; do + case $option in + x|y) ;; # Ignore + n) login=$OPTARG ;; + h) host=$OPTARG ;; + *) echo "LPD started `basename $0` wrong." 1>&ero;2 + exit 2 + ;; + esac +done + +[ "$login" ] || fail "No login name" +[ "$host" ] || fail "No host name" + +( /u/kelly/freebsd/printing/filters/make-ps-header $login $host "DVI File" + /usr/local/bin/dvips -f ) | eval /usr/local/libexec/lprps $orig_args +</code> + Notice how the filter has to parse the argument list in + order to determine the user and host name. The parsing + for the other conversion filters is identical. The text + filter takes a slightly different set of arguments, though + (see section <ref id="printing:advanced:filters" name="How + Filters Work">). + + As we've mentioned before, the above scheme, though fairly + simple, disables the ``suppress header page'' option (the + <tt/-h/ option) to <tt/lpr/. If users wanted to save a + tree (or a few pennies, if you charge for header pages), + they wouldn't be able to do so, since every filter's going + to print a header page with every job. + + To allow users to shut off header pages on a per-job + basis, you'll need to use the trick introduced in section + <ref id="printing:advanced:header-pages:accounting" + name="Accounting for Header Pages">: write an output + filter that parses the LPD-generated header page and + produces a PostScript version. If the user submits the + job with <tt/lpr -h/, then LPD won't generate a header + page, and neither will your output filter. Otherwise, + your output filter will read the text from LPD and send + the appropriate header page PostScript code to the + printer. + + If you've got a PostScript printer on a serial line, you + can make use of <tt/lprps/, which comes with an output + filter, <tt/psof/, which does the above. Note that + <tt/psof/ doesn't charge for header pages. + + <sect1><heading>Networked Printing<label + id="printing:advanced:network-printers"></heading> + + <p> FreeBSD supports networked printing: sending jobs to + remote printers. Networked printing generally refers to two + different things: + <itemize> + <item>Accessing a printer attached to a remote host. You + install a printer that has a conventional serial or + parallel interface on one host. Then, you set up LPD to + enable access to the printer from other hosts on the + network. Section <ref id="printing:advanced:network:rm" + name="Printers Installed on Remote Hosts"> tells how to + do this. + + <item>Accessing a printer attached directly to a network. + The printer has a network interface in addition (or in + place of) a more conventional serial or parallel + interface. Such a printer might work as follows: + + <itemize> + <item>It might understand the LPD protocol and can + even queue jobs from remote hosts. In this case, it + acts just like a regular host running LPD. Follow + the same procedure in section <ref + id="printing:advanced:network:rm" name="Printers + Installed on Remote Hosts"> to set up such a + printer. + + <item>It might support a data stream network + connection. In this case, you ``attach'' the + printer to one host on the network by making that + host responsible for spooling jobs and sending them + to the printer. Section <ref + id="printing:advanced:network:net-if" name="Printers + with Networked Data Stream Interfaces"> gives some + suggestions on installing such printers. + </itemize> + </itemize> + + <sect2><heading>Printers Installed on Remote Hosts<label + id="printing:advanced:network:rm"></heading> + + <p> The LPD spooling system has built-in support for sending + jobs to other hosts also running LPD (or are compatible + with LPD). This feature enables you to install a printer + on one host and make it accessible from other hosts. It + also works with printers that have network interfaces that + understand the LPD protocol. + + To enable this kind of remote printing, first install a + printer on one host, the <em/printer host/, using the + simple printer setup described in <ref + id="printing:simple" name="Simple Printer Setup">. Do any + advanced setup in <ref id="printing:advanced" + name="Advanced Printer Setup"> that you need. Make sure + to test the printer and see if it works with the features + of LPD you've enabled. + + If you're using a printer with a network interface that's + compatible with LPD, then the <em/printer host/ in the + discussion below is the printer itself, and the + <em/printer name/ is the name you configured for the + printer. See the documentation that accompanied your + printer and/or printer-network interface. + + Then, on the other hosts you want to have access to the + printer, make an entry in their <tt>/etc/printcap</tt> + files with the following: + <enum> + <item>Name the entry anything you want. For + simplicity, though, you probably want to use the same + name and aliases as on the printer host. + + <item>Leave the <tt/lp/ capability blank, explicitly + (<tt/:lp=:/). + + <item>Make a spooling directory and specify its + location in the <tt/sd/ capability. LPD will store + jobs here before they get sent to the printer host. + + <item>Place the name of the printer host in the <tt/rm/ + capability. + + <item>Place the printer name on the <em/printer host/ in + the <tt/rp/ capability. + </enum> + That's it. You don't need to list conversion filters, + page dimensions, or anything else in the + <tt>/etc/printcap</tt> file. + + Here's an example. The host rose has two printers, + <tt/bamboo/ and <tt/rattan/. We'll enable users on the + host orchid to print to those printers. Here's the + <tt>/etc/printcap</tt> file for orchid (back from section + <ref id="printing:advanced:header-pages:enabling" + name="Enabling Header Pages">). It already had the entry + for the printer <tt/teak/; we've added entries for the two + printers on the host rose: +<code> +# +# /etc/printcap for host orchid - added (remote) printers on rose +# + +# +# teak is local; it's connected directly to orchid: +# +teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ + :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:\ + :if=/usr/local/libexec/ifhp:\ + :vf=/usr/local/libexec/vfhp:\ + :of=/usr/local/libexec/ofhp: + +# +# rattan is connected to rose; send jobs for rattan to rose: +# +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan: + +# +# bamboo is connected to rose as well: +# +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo: +</code> + Then, we just need to make spooling directories on orchid: +<tscreen><verb> +mkdir -p /var/spool/lpd/rattan /var/spool/lpd/bamboo +chmod 770 /var/spool/lpd/rattan /var/spool/lpd/bamboo +chown daemon.daemon /var/spool/lpd/rattan /var/spool/lpd/bamboo +</verb></tscreen> + + Now, users on orchid can print to <tt/rattan/ and + <tt/bamboo/. If, for example, a user on orchid typed +<tscreen><verb> +lpr -P bamboo -d sushi-review.dvi +</verb></tscreen> + the LPD system on orchid would copy the job to the + spooling directory <tt>/var/spool/lpd/bamboo</tt> and note + that it was a DVI job. As soon as the host rose has room + in its <tt/bamboo/ spooling directory, the two + LPDs would transfer the file to rose. The file would wait + in rose's queue until it was finally printed. It would be + converted from DVI to PostScript (since bamboo is a + PostScript printer) on rose. + + <sect2><heading>Printers with Networked Data Stream Interfaces<label + id="printing:advanced:network:net-if"></heading> + + <p> Often, when you buy a network interface card for a + printer, you can get two versions: one which emulates a + spooler (the more expensive version), or one which just + lets you send data to it as if you were using a serial or + parallel port (the cheaper version). This section tells + how to use the cheaper version. For the more expensive + version, see the previous section <ref name="Printers + Installed on Remote Hosts" id="printing:advanced:network:rm">. + + The format of the <tt>/etc/printcap</tt> file lets you + specify what serial or parallel interface to use, and (if + you're using a serial interface), what baud rate, whether + to use flow control, delays for tabs, conversion of + newlines, and more. But there's no way to specify a + connection to a printer that's listening on a TCP/IP or + other network port. + + To send data to a networked printer, you need to develop a + communications program that can be called by the text and + conversion filters. Here's one such example: the script + <tt/netprint/ takes all data on standard input and sends + it to a network-attached printer. We specify the hostname + of the printer as the first argument and the port number + to which to connect as the second argument to + <tt/netprint/. Note that this supports one-way + communication only (FreeBSD to printer); many network + printers support two-way communication, and you might want + to take advantage of that (to get printer status, perform + accounting, etc.). +<code> +#!/usr/bin/perl +# +# netprint - Text filter for printer attached to network +# Installed in /usr/local/libexec/netprint +# + +$#ARGV eq 1 || die "Usage: $0 <printer-hostname> <port-number>"; + +$printer_host = $ARGV[0]; +$printer_port = $ARGV[1]; + +require 'sys/socket.ph'; + +($ignore, $ignore, $protocol) = getprotobyname('tcp'); +($ignore, $ignore, $ignore, $ignore, $address) + = gethostbyname($printer_host); + +$sockaddr = pack('S n a4 x8', &ero;AF_INET, $printer_port, $address); + +socket(PRINTER, &ero;PF_INET, &ero;SOCK_STREAM, $protocol) + || die "Can't create TCP/IP stream socket: $!"; +connect(PRINTER, $sockaddr) || die "Can't contact $printer_host: $!"; +while (<STDIN>) { print PRINTER; } +exit 0; +</code> + We can then use this script in various filters. Suppose + we had a Diablo 750-N line printer connected to the + network. The printer accepts data to print on port number + 5100. The host name of the printer is scrivener. Here's + the text filter for the printer: +<code> +#!/bin/sh +# +# diablo-if-net - Text filter for Diablo printer `scrivener' listening +# on port 5100. Installed in /usr/local/libexec/diablo-if-net +# + +exec /usr/libexec/lpr/lpf "$@" | /usr/local/libexec/netprint scrivener 5100 +</code> + + + <sect1><heading>Restricting Printer Usage<label + id="printing:advanced:restricting"></heading> + + <p> This section gives information on restricting printer + usage. The LPD system lets you control who can access a + printer, both locally or remotely, whether they can print + multiple copies, how large their jobs can be, and how large + the printer queues can get. + + <sect2><heading>Restricting Multiple Copies<label + id="printing:advanced:restricting:copies"></heading> + + <p> The LPD system makes it easy for users to print multiple + copies of a file. Users can print jobs with <tt/lpr -#5/ + (for example) and get five copies of each file in the job. + Whether this is a good thing is up to you. + + If you feel multiple copies cause unnecessary wear and + tear on your printers, you can disable the <tt/-#/ option + to <tt/lpr/ by adding the <tt/sc/ capability to the + <tt>/etc/printcap</tt> file. When users submit jobs + with the <tt/-#/ option, they'll see +<tscreen><verb> +lpr: multiple copies are not allowed +</verb></tscreen> + + Note that if you've set up access to a printer remotely + (see section <ref name="Printers Installed on Remote + Hosts" id="printing:advanced:network:rm">), you need the + <tt/sc/ capability on the remote <tt>/etc/printcap</tt> + files as well, or else users will still be able to submit + multiple-copy jobs by using another host. + + Here's an example. This is the <tt>/etc/printcap</tt> + file for the host rose. The printer <tt/rattan/ is quite + hearty, so we'll allow multiple copies, but the laser + printer <tt/bamboo/'s a bit more delicate, so we'll + disable multiple copies by adding the <tt/sc/ capability: +<code> +# +# /etc/printcap for host rose - restrict multiple copies on bamboo +# +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :sh:sd=/var/spool/lpd/rattan:\ + :lp=/dev/lpt0:\ + :if=/usr/local/libexec/if-simple: + +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :sh:sd=/var/spool/lpd/bamboo:sc:\ + :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\ + :if=/usr/local/libexec/psif:\ + :df=/usr/local/libexec/psdf: +</code> + Now, we also need to add the <tt/sc/ capability on the + host orchid's <tt>/etc/printcap</tt> (and while we're at + it, let's disable multiple copies for the printer + <tt/teak/): +<code> +# +# /etc/printcap for host orchid - no multiple copies for local +# printer teak or remote printer bamboo + +teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ + :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:sc:\ + :if=/usr/local/libexec/ifhp:\ + :vf=/usr/local/libexec/vfhp:\ + :of=/usr/local/libexec/ofhp: + +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan: + +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo:sc: +</code> + By using the <tt/sc/ capability, we prevent the use of + <tt/lpr -#/, but that still doesn't prevent users from + running <tt/lpr/ multiple times, or from submitting the + same file mutliple times in one job like this: +<tscreen><verb> +lpr forsale.sign forsale.sign forsale.sign forsale.sign forsale.sign +</verb></tscreen> + There are many ways to prevent this abuse (including + ignoring it) which you are free to explore. + + <sect2><heading>Restricting Access To Printers<label + id="printing:advanced:restricting:access"></heading> + + <p> You can control who can print to what printers by using + the UNIX group mechanism and the <tt/rg/ capability in + <tt>/etc/printcap</tt>. Just place the users you want to + have access to a printer in a certain group, and then name + that group in the <tt/rg/ capability. + + Users outside the group (including root) will be greeted + with +<tscreen><verb> +lpr: Not a member of the restricted group +</verb></tscreen> + if they try to print to the controlled printer. + + As with the <tt/sc/ (suppress multiple copies) capability, + you need to specify <tt/rg/ on remote hosts that also have + access to your printers, if you feel it's appropriate (see + section <ref name="Printers Installed on Remote Hosts" + id="printing:advanced:network:rm">). + + For example, we'll let anyone access the printer + <tt/rattan/, but only those in group <tt/artists/ can use + <tt/bamboo/. Here's the familiar <tt>/etc/printcap</tt> + for host rose: +<code> +# +# /etc/printcap for host rose - restricted group for bamboo +# +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :sh:sd=/var/spool/lpd/rattan:\ + :lp=/dev/lpt0:\ + :if=/usr/local/libexec/if-simple: + +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:\ + :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\ + :if=/usr/local/libexec/psif:\ + :df=/usr/local/libexec/psdf: +</code> + Let's leave the other example <tt>/etc/printcap</tt> file + (for the host orchid) alone. Of course, anyone on orchid + can print to <tt/bamboo/. It might be the case that we + only allow certain logins on orchid anyway, and want them + to have access to the printer. Or not. + + <em/Note:/ there can be only one restricted group per + printer. + + <sect2><heading>Controlling Sizes of Jobs Submitted<label + id="printing:advanced:restricting:sizes"></heading> + + <p> If you have many users accessing the printers, you + probably need to put an upper limit on the sizes of the + files users can submit to print. After all, there's only + so much free space on the filesystem that houses the + spooling directories, and you also need to make sure + there's room for the jobs of other users. + + LPD enables you to limit the maximum byte size a file in a + job can be with the <tt/mx/ capability. The units are in + BUFSIZ blocks, which are 1024 bytes. If you put a zero + for this capability, there'll be no limit on file size. + Note that the limit applies to <em/files/ in a job, and + <em/not/ the total job size. + + LPD won't refuse a file that's larger than the limit you + place on a printer. Instead, it'll queue as much of the + file up to the limit, which will then get printed. The + rest will be discarded. Whether this is correct behavior + is up for debate. + + Let's add limits to our example printers <tt/rattan/ and + <tt/bamboo/. Since those artists' PostScript files tend + to be large, we'll limit them to five megabytes. We'll + put no limit on the plain text line printer: +<code> +# +# /etc/printcap for host rose +# + +# +# No limit on job size: +# +rattan|line|diablo|lp|Diablo 630 Line Printer:\ + :sh:sd=/var/spool/lpd/rattan:\ + :lp=/dev/lpt0:\ + :if=/usr/local/libexec/if-simple: + +# +# Limit of five megabytes: +# +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\ + :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:\ + :if=/usr/local/libexec/psif:\ + :df=/usr/local/libexec/psdf: +</code> + Again, the limits apply to the local users only. If + you've set up access to your printers remotely, remote + users won't get those limits. You'll need to specify the + <tt/mx/ capability in the remote <tt>/etc/printcap</tt> + files as well. See section <ref name="Printers Installed + on Remote Hosts" id="printing:advanced:network:rm"> for + more information on remote printing. + + There's another specialized way to limit job sizes from + remote printers; see section <ref + id="printing:advanced:restricting:remote" + name="Restricting Jobs from Remote Printers">. + + <sect2><heading>Restricting Jobs from Remote Printers<label + id="printing:advanced:restricting:remote"></heading> + + <p> The LPD spooling system provides several ways to restrict + print jobs submitted from remote hosts: + + <descrip> + <tag/Host restrictions/ + + You can control from which remote hosts a local LPD + accepts requests with the files + <tt>/etc/hosts.equiv</tt> and <tt>/etc/hosts.lpd</tt>. + LPD checks to see if an incoming request is from a + host listed in either one of these files. If not, LPD + refuses the request. + + The format of these files is simple: one host name per + line. Note that the file <tt>/etc/hosts.equiv</tt> is + also used by the ruserok(3) protocol, and affects + programs like <tt/rsh/ and <tt/rcp/, so be careful. + + For example, here's the <tt>/etc/hosts.lpd</tt> file + on the host rose: +<code> +orchid +violet +madrigal.fishbaum.de +</code> + This means rose will accept requests from the hosts + orchid, violet, and madrigal.fishbaum.de. If any + other host tries to access rose's LPD, LPD will + refuse them. + + <tag/Size restrictions/ + + You can control how much free space there needs to + remain on the filesystem where a spooling directory + resides. Make a file called <tt/minfree/ in the + spooling directory for the local printer. Insert in + that file a number representing how many disk blocks + (512 bytes) of free space there has to be for a remote + job to be accepted. + + This lets you insure that remote users won't fill your + filesystem. You can also use it to give a certain + priority to local users: they'll be able to queue jobs + long after the free disk space has fallen below the + amount specified in the <tt/minfree/ file. + + For example, let's add a <tt/minfree/ file for the + printer <tt/bamboo/. We examine + <tt>/etc/printcap</tt> to find the spooling directory + for this printer; here's <tt/bamboo/'s entry: +<tscreen><verb> +bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ + :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\ + :lp=/dev/ttyd5:fs#0x82000e1:xs#0x820:rw:mx#5000:\ + :if=/usr/local/libexec/psif:\ + :df=/usr/local/libexec/psdf: +</verb></tscreen> + The spooling directory is the given in the <tt/sd/ + capability. We'll make three megabytes (which is 6144 + disk blocks) the amount of free disk space that must + exist on the filesystem for LPD to accept remote jobs: +<tscreen><verb> +echo 6144 > /var/spool/lpd/bamboo/minfree +</verb></tscreen> + <tag/User restrictions/ + + You can control which remote users can print to local + printers by specifying the <tt/rs/ capability in + <tt>/etc/printcap</tt>. When <tt/rs/ appears in the + entry for a locally-attached printer, LPD will accept + jobs from remote hosts <em/if/ the user submitting the + job also has an account of the same login name on the + local host. Otherwise, LPD refuses the job. + + This capability is particularly useful in an + environment where there are (for example) different + departments sharing a network, and some users + transcend departmental boundaries. By giving them + accounts on your systems, they can use your printers + from their own departmental systems. If you'd rather + allow them to use <em/only/ your printers and not your + compute resources, you can give them ``token'' + accounts, with no home directory and a useless shell + like <tt>/usr/bin/false</tt>. + </descrip> + + <sect1><heading>Accounting for Printer Usage<label + id="printing:advanced:acct"></heading> + + <p> So, you need to charge for printouts. And why not? Paper + and ink cost money. And then there are maintenance + costs---printers are loaded with moving parts and tend to + break down. You've examined your printers, usage patterns, + and maintenance fees and have come up with a per-page (or + per-foot, per-meter, or per-whatever) cost. Now, how do you + actually start accounting for printouts? + + Well, the bad news is the LPD spooling system doesn't + provide much help in this department. Accounting is highly + dependent on the kind of printer in use, the formats being + printed, and <em/your/ requirements in charging for printer + usage. + + To implement accounting, you have to modify a printer's text + filter (to charge for plain text jobs) and the conversion + filters (to charge for other file formats), to count pages + or query the printer for pages printed. You can't get away + with using the simple output filter, since it cannot do + accounting. See section <ref name="Filters" + id="printing:advanced:filter-intro">. + + Generally, there are two ways to do accounting: + <itemize> + <item><em/Periodic accounting/ is the more common way, + possibly because it's easier. Whenever someone prints a + job, the filter logs the user, host, and number of pages + to an accounting file. Every month, semester, year, or + whatever time period you prefer, you collect the + accounting files for the various printers, tally up the + pages printed by users, and charge for usage. Then you + truncate all the logging files, starting with a clean + slate for the next period. + + <item><em/Timely accounting/ is less common, probably + because it's more difficult. This method has the + filters charge users for printouts as soon as they use + the printers. Like disk quotas, the accounting is + immediate. You can prevent users from printing when + their account goes in the red, and might provide a way + for users to check and adjust their ``print quotas.'' + But this method requires some database code to track + users and their quotas. + </itemize> + + The LPD spooling system supports both methods easily: since + you have to provide the filters (well, most of the time), + you also have to provide the accounting code. But there is + a bright side: you have enormous flexibility in your + accounting methods. For example, you choose whether to use + periodic or timely accounting. You choose what information + to log: user names, host names, job types, pages printed, + square footage of paper used, how long the job took to + print, and so forth. And you do so by modifying the filters + to save this information. + + <sect2><heading>Quick and Dirty Printer Accounting</heading> + + <p> FreeBSD comes with two programs that can get you set up + with simple periodic accounting right away. They are the + text filter <tt/lpf/, described in section <ref + id="printing:advanced:lpf" name="lpf: a Text Filter">, and + <tt/pac/, a program to gather and total entries from + printer accounting files. + + As mentioned in the section on filters (<ref + id="printing:advanced:filters" name="Filters">), LPD + starts the text and the conversion filters with the name + of the accounting file to use on the filter command + line. The filters can use this argument to know where + to write an accounting file entry. The name of this + file comes from the <tt/af/ capability in + <tt>/etc/printcap</tt>, and if not specified as an + absolute path, is relative to the spooling directory. + + LPD starts <tt/lpf/ with page width and length arguments + (from the <tt/pw/ and <tt/pl/ capabilities). <tt/lpf/ + uses these arguments to determine how much paper will be + used. After sending the file to the printer, it then + writes an accounting entry in the accounting file. The + entries look like this: +<tscreen><verb> + 2.00 rose:andy + 3.00 rose:kelly + 3.00 orchid:mary + 5.00 orchid:mary + 2.00 orchid:zhang +</verb></tscreen> + You should use a separate accounting file for each + printer, as <tt/lpf/ has no file locking logic built into + it, and two <tt/lpf/s might corrupt each other's entries + if they were to write to the same file at the same time. + A easy way to insure a separate accounting file for each + printer is to use <tt/af=acct/ in <tt>/etc/printcap</tt>. + Then, each accounting file will be in the spooling directory + for a printer, in a file named <tt/acct/. + + When you're ready to charge users for printouts, run the + <tt/pac/ program. Just change to the spooling directory + for the printer you want to collect on and type <tt/pac/. + You'll get a dollar-centric summary like the following: +<code> + Login pages/feet runs price +orchid:kelly 5.00 1 $ 0.10 +orchid:mary 31.00 3 $ 0.62 +orchid:zhang 9.00 1 $ 0.18 +rose:andy 2.00 1 $ 0.04 +rose:kelly 177.00 104 $ 3.54 +rose:mary 87.00 32 $ 1.74 +rose:root 26.00 12 $ 0.52 + +total 337.00 154 $ 6.74 +</code> + These are the arguments <tt/pac/ expects: + <descrip> + <tag/<tt/-P<it/printer/// + + Which <it/printer/ to summarize. This option works + only if there's an absolute path in the <tt/af/ + capability in <tt>/etc/printcap</tt>. + + <tag/<tt/-c// + + Sort the output by cost instead of alphabetically by + user name. + + <tag/<tt/-m// + + Ignore host name in the accounting files. With this + option, user smith on host alpha is the same user + smith on host gamma. Without, they're different users. + + <tag/<tt/-p<it/price/// + + Compute charges with <it/price/ dollars per page or + per foot instead of the price from the <tt/pc/ + capabilty in <tt>/etc/printcap</tt>, or two cents (the + default). You can specify <it/price/ as a floating + point number. + + <tag/<tt/-r// + + Reverse the sort order. + + <tag/<tt/-s// + + Make an accounting summary file and truncate the + accounting file. + + <tag/<tt/<it/names.../// + + Print accounting information for the given user + <it/names/ only. + </descrip> + + In the default summary that <tt/pac/ produces, you see the + number of pages printed by each user from various hosts. + If, at your site, host doesn't matter (because users can + use any host), run <tt/pac -m/, to produce the following + summary: +<code> + Login pages/feet runs price +andy 2.00 1 $ 0.04 +kelly 182.00 105 $ 3.64 +mary 118.00 35 $ 2.36 +root 26.00 12 $ 0.52 +zhang 9.00 1 $ 0.18 + +total 337.00 154 $ 6.74 +</code> + To compute the dollar amount due, <tt/pac/ uses the + <tt/pc/ capability in the <tt>/etc/printcap</tt> file + (default of 200, or 2 cents per page). Specify, in + hundreths of cents, the price per page or per foot you + want to charge for printouts in this capability. You can + override this value when you run <tt/pac/ with the <tt/-p/ + option. The units for the <tt/-p/ option are in dollars, + though, not hundreths of cents. For example, +<tscreen><verb> +pac -p1.50 +</verb></tscreen> + makes each page cost one dollar and fifty cents. You can + really rake in the profits by using this option. + + Finally, running <tt/pac -s/ will save the summary + information in a summary accounting file, which is named + the same as the printer's accounting file, but with + <tt/_sum/ appended to the name. It then truncates the + accounting file. When you run <tt/pac/ again, it rereads + the summary file to get starting totals, then adds + information from the regular accounting file. + + + <sect2><heading>How Can You Count Pages Printed?</heading> + + <p> In order to perform even remotely accurate accounting, + you need to be able to determine how much paper a job + uses. This is the essential problem of printer + accounting. + + For plain text jobs, the problem's not that hard to solve: + you count how many lines are in a job and compare it to + how many lines per page your printer supports. Don't + forget to take into account backspaces in the file which + overprint lines, or long logical lines that wrap onto one + or more additional physical lines. + + The text filter <tt/lpf/ (introduced in <ref + id="printing:advanced:lpf" name="lpf: a Text Filter">) + takes into account these things when it does accounting. + If you're writing a text filter which needs to do + accounting, you might want to examine <tt/lpf/'s source + code. + + How do you handle other file formats, though? + + Well, for DVI-to-LaserJet or DVI-to-PostScript conversion, + you can have your filter parse the diagnostic output of + <tt/dvilj/ or <tt/dvips/ and look to see how many pages + were converted. You might be able to do similar things + with other file formats and conversion programs. + + But these methods suffer from the fact that the printer + may not actually print all those pages. For example, it + could jam, run out of toner, or explode---and the user + would still get charged. + + So, what can you do? + + There is only one <em/sure/ way to do <em/accurate/ + accounting. Get a printer that can tell you how much + paper it uses, and attach it via a serial line or a + network connection. Nearly all PostScript printers + support this notion. Other makes and models do as well + (networked Imagen laser printers, for example). Modify + the filters for these printers to get the page usage after + they print each job and have them log accounting + information based on that value <em/only/. There's no + line counting nor error-prone file examination required. + + Of course, you can always be generous and make all + printouts free. + + <sect><heading>Alternatives to the Standard Spooler<label + id="printing:lpd-alternatives"></heading> + + <p> If you've been reading straight through this manual, by now + you've learned just about everything there is to know about + the LPD spooling system that comes with FreeBSD. You can + probably appreciate many of its shortcomings, which naturally + leads to the question: ``What other spooling systems are out + there (and work with FreeBSD)?'' + + Unfortunately, I've located only <em/two/ alternatives---and + they're almost identical to each other! They are + <descrip> + <tag/PLP, the Portable Line Printer Spooler System/ + + PLP was based on software developed by Patrick Powell and + then maintained by an Internet-wide group of developers. + The main site for the software is at <htmlurl + url="ftp://ftp.iona.ie/pub/plp" + name="ftp://ftp.iona.ie/pub/plp">. There's also a <htmlurl + url="http://www.iona.ie:8000/www/hyplan/jmason/plp.html" + name="web page">. + + It's quite similar to the BSD LPD spooler, but boasts a + host of features, including: + <itemize> + <item>Better network support, including built-in support + for networked printers, NIS-maintained printcaps, and + NFS-mounted spooling directories + + <item>Sophisticated queue management, allowing multiple + printers on a queue, transfer of jobs between queues, + and queue redirection + + <item>Remote printer control functions + + <item>Prioritization of jobs + + <item>Expansive security and access options + </itemize> + + <tag/LPRng/ + + LPRng, which purportedly means ``LPR: the Next + Generation'' is a complete rewrite of PLP. Patrick Powell + and Justin Mason (the principal maintainer of PLP) + collaborated to make LPRng. The main site for LPRng is + <htmlurl url="ftp://dickory.sdsu.edu/pub/LPRng" + name="ftp://dickory.sdsu.edu/pub/LPRng">. + </descrip> + + + <sect><heading>Acknowledgments</heading> + + <p> I'd like to thank the following people who've assisted in + the development of this document: + + <descrip> + <tag/Daniel Eischen <tt/<deischen@iworks.interworks.org>// + + For providing a plethora of HP filter programs for perusal. + + <tag/Jake Hamby <tt/<jehamby@lightside.com>// + + For the Ghostscript-to-HP filter. + + <tag/My wife, Mary Kelly <tt/<urquhart@argyre.colorado.edu>// + + For allowing me to spend more time with FreeBSD than with her. + + </descrip> diff --git a/share/doc/handbook/routing.sgml b/share/doc/handbook/routing.sgml new file mode 100644 index 000000000000..5441cce05ffd --- /dev/null +++ b/share/doc/handbook/routing.sgml @@ -0,0 +1,279 @@ +<!-- $Id$ --> +<!-- The FreeBSD Documentation Project --> +<!-- <!DOCTYPE linuxdoc PUBLIC '-//FreeBSD//DTD linuxdoc//EN'> --> + + <sect><heading>Gateways and routes<label id="routing"></heading> + + <p><em>Contributed by &a.gryphon;.<newline>6 October 1995.</em> + + For one machine to be able to find another, there must be a + mechanism in place to describe how to get from one to the + other. This is called Routing. A ``route'' is a defined + pair of addresses: a <bf>destination</bf> and a + <bf>gateway</bf>. The pair indicates that if you are + trying to get to this <em>destination</em>, send along + through this <em>gateway</em>. There are three types of + destinations: individual hosts, subnets, and ``default''. The + ``default route'' is used if none of the other routes + apply. We will talk a little bit more about default routes + later on. There are also three types of gateways: + individual hosts, interfaces (also called ``links''), and + ethernet hardware addresses. + + <sect1><heading>An example</heading> + + <p>To illustrate different aspects of routing, we will use + the following example which is the output of the command + <tt>netstat -r</tt>: + +<tscreen><verb> +Destination Gateway Flags Refs Use Netif Expire + +default outside-gw UGSc 37 418 ppp0 +localhost localhost UH 0 181 lo0 +test0 0:e0:b5:36:cf:4f UHLW 5 63288 ed0 77 +10.20.30.255 link#1 UHLW 1 2421 +foobar.com link#1 UC 0 0 +host1 0:e0:a8:37:8:1e UHLW 3 4601 lo0 +host2 0:e0:a8:37:8:1e UHLW 0 5 lo0 => +host2.foobar.com link#1 UC 0 0 +224 link#1 UC 0 0 +</verb></tscreen> + + The first two lines specify the default route (which we + will cover in the next section) and the <tt>localhost</tt> route. + + The interface (<tt>Netif</tt> column) that it specifies to use + for <tt>localhost</tt> is <tt>lo0</tt>, also known as the + loopback device. This says to keep all traffic for this + destination internal, rather than sending it out over the + LAN, since it will only end up back where it started + anyway. + + The next thing that stands out are the + ``<tt>0:e0:...</tt>'' addresses. These are ethernet + hardware addresses. FreeBSD will automatically identify any + hosts (<tt>test0</tt> in the example) on the local ethernet and + add a route for that host, directly to it over the ethernet + interface, <tt>ed0</tt>. There is also a timeout + (<tt>Expire</tt> column) associated with this type of route, + which is used if we fail to hear from the host in a + specific amount of time. In this case the route will be + automatically deleted. These hosts are identified using a + mechanism known as RIP (Routing Information Protocol), + which figures out routes to local hosts based upon a + shortest path determination. + + FreeBSD will also add subnet routes for the local subnet + (<tt>10.20.30.255</tt> is the broadcast address for the subnet + <tt>10.20.30</tt>, and <tt>foobar.com</tt> is the domain name + associated with that subnet). The designation <tt>link#1</tt> + refers to the first ethernet card in the machine. You'll + notice no additional interface is specified for those. + + Both of these groups (local network hosts and local + subnets) have their routes automatically configured by a + daemon called <tt>routed</tt>. If this is not run, then only + routes which are statically defined (ie. entered + explicitly) will exist. + + The <tt>host1</tt> line refers to our host, which it knows by + ethernet address. Since we are the sending host, FreeBSD + knows to use the loopback interface (<tt>lo0</tt>) rather than + sending it out over the ethernet interface. + + The two <tt>host2</tt> lines are an example of what happens + when we use an ifconfig alias (see the section of ethernet + for reasons why we would do this). The <tt>=></tt> + symbol after the <tt>lo0</tt> interface says that not only are + we using the loopback (since this is address also refers to + the local host), but specifically it is an alias. Such + routes only show up on the host that supports the alias; + all other hosts on the local network will simply have a + <tt>link#1</tt> line for such. + + The final line (destination subnet <tt>224</tt>) deals with + MultiCasting, which will be covered in a another section. + + The other column that we should talk about are the + <tt>Flags</tt>. Each route has different attributes that are + described in the column. Below is a short table of some of + these flags and their meanings: + + <descrip> + + <tag/U/ <bf/Up:/ The route is active. + + <tag/H/ <bf/Host:/ The route destination is a single host. + + <tag/G/ <bf/Gateway:/ Send anything for this destination + on to this remote system, which will figure out from + there where to send it. + + <tag/S/ <bf/Static:/ This route was configured manually, + not automatically generated by the system. + + <tag/C/ <bf/Clone:/ Generates a new route based upon this + route for machines we connect to. This type of route is + normally used for local networks. + + <tag/W/ <bf/WasCloned/ Indicated a route that was + auto-configured based upon a local area network (Clone) + route. + + <tag/L/ <bf/Link:/ Route involves references to ethernet + hardware. + + </descrip> + + + <sect1><heading>Default routes</heading> + + <p>When the local system needs to make a connection to + remote host, it checks the routing table to determine if + a known path exists. If the remote host falls into a + subnet that we know how to reach (Cloned routes), then + the system checks to see if it can connect along that + interface. + + If all known paths fail, the system has one last option: + the <bf>default</bf> route. This route is a special type + of gateway route (usually the only one present in the + system), and is always marked with a ``<tt>c</tt>'' in + the flags field. For hosts on a local area network, this + gateway is set to whatever machine has a direct + connection to the outside world (whether via PPP link, or + your hardware device attached to a dedicated data line). + + If you are configuring the default route for a machine + which itself is functioning as the gateway to the outside + world, then the default route will be the gateway machine + at your Internet Service Provider's (ISP) site. + + Let's look at an example of default routes. This is a + common configuration: +<tscreen><verb> +[Local2] <--ether--> [Local1] <--PPP--> [ISP-Serv] <--ether--> [T1-GW] +</verb></tscreen> + + The hosts <tt>Local1</tt> and <tt>Local2</tt> are at your + site, with the formed being your PPP connection to your + ISP's Terminal Server. Your ISP has a local network at + their site, which has, among other things, the server + where you connect and a hardware device (T1-GW) attached + to the ISP's internet feed. + + The default routes for each of your machines will be: + +<tscreen><verb> +host default gateway interface +---- --------------- --------- +Local2 Local1 ethernet +Local1 T1-GW PPP +</verb></tscreen> + + A common question is ``Why (or how) would we set the + T1-GW to be the default gateway for Local1, rather than + the ISP server it is connected to?''. + + Remember, since the PPP interface is using an address on + the ISP's local network for your side of the connection, + routes for any other machines on the ISP's local network + will be automatically generated. Hence, you will already + know how to reach the T1-GW machine, so there is no need + for the intermediate step of sending traffic to the ISP + server. + + As a final note, it is common to use the address ``<tt>...1</tt>'' + as the gateway address for your local network. So (using + the same example), if your local class-C address space + was <tt>10.20.30</tt> and your ISP was using <tt>10.9.9</tt> then the + default routes would be: + +<tscreen><verb> +Local2 (10.20.30.2) --> Local1 (10.20.30.1) +Local1 (10.20.30.1, 10.9.9.30) --> T1-GW (10.9.9.1) +</verb></tscreen> + + <sect1><heading>Dual homed hosts</heading> + + <p>There is one other type of configuration that we should + cover, and that is a host that sits on two different + networks. Technically, any machine functioning as a + gateway (in the example above, using a PPP connection) + counts as a dual-homed host. But the term is really only + used to refer to a machine that sits on two local-area + networks. + + In one case, the machine as two ethernet cards, each + having an address on the seperate subnets. Alternately, + the machine may only have one ethernet card, and be using + ifconfig aliasing. The former is used if two physically + separate ethernet networks are in use, the latter if + there is one physical network segment, but two logically + seperate subnets. + + Either way, routing tables are set up so that each subnet + knows that this machine is the defined gateway (inbound + route) to the other subnet. This configuration, with the + machine acting as a Bridge between the two subnets, is + often used when we need to implement packet filtering or + firewall security in either or both directions. + + <sect1><heading>Routing propogation</heading> + + <p>We have already talked about how we define our routes to + the outside world, but not about how the outside world + finds us. + + We already know that routing tables can be set up so that + all traffic for a particular address space (in our + examples, a class-C subnet) can be sent to a particular + host on that network, which will forward the packets + inbound. + + When you get an address space assigned to your site, your + service provider will set up their routing tables so that + all traffic for your subnet will be sent down your PPP + link to your site. But how do sites across the country + know to send to your ISP? + + There is a system (much like the distributed DNS + information) that keeps track of all assigned + address-spaces, and defines their point of connection to + the Internet Backbone. The ``Backbone'' are the main + trunk lines that carry internet traffic across the + country, and around the world. Each backbone machine has + a copy of a master set of tables, which direct traffic + for a particular network to a specific backbone carrier, + and from there down the chain of service providers until + it reaches your network. + + It is the task of your service provider to advertise to + the backbone sites that they are the point of connection + (and thus the path inward) for your site. This is known + as route propogation. + +<!-- + <sect1><heading>Multicast Routing</heading> +--> + + <sect1><heading>Troubleshooting</heading> + + <p>Sometimes, there is a problem with routing propogation, + and some sites are unable to connect to you. Perhaps the + most useful command for trying to figure out where a + routing is breaking down is the <tt>traceroute(8)</tt> + command. It is equally useful if you cannot seem to make + a connection to a remote machine (ie. <tt>ping(8)</tt> + fails). + + The <tt>traceroute(8)</tt> command is run with the name + of the remote host you are trying to connect to. It will + show the gateway hosts along the path of the attempt, + eventually either reaching the target host, or + terminating because of a lack of connection. + + For more information, see the manual page for + <tt>traceroute(8)</tt>. + diff --git a/share/doc/handbook/skey.sgml b/share/doc/handbook/skey.sgml new file mode 100644 index 000000000000..865e2ca5cfe0 --- /dev/null +++ b/share/doc/handbook/skey.sgml @@ -0,0 +1,302 @@ +<!-- $Id: skey.sgml,v 1.2 1995/09/26 19:12:28 wollman Exp $ --> +<!-- The FreeBSD Documentation Project --> +<!-- +Copyright 1995 Massachusetts Institute of Technology + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that both the above copyright notice and this +permission notice appear in all copies, that both the above +copyright notice and this permission notice appear in all +supporting documentation, and that the name of M.I.T. not be used +in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. M.I.T. makes +no representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied +warranty. + +THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS +ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT +SHALL M.I.T. 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. +--> + +<sect><heading>S/Key<label id="skey"></heading> + +<p><em>Contributed by &a.wollman;<newline>25 September 1995.</em> + +<p>S/Key is a one-time password scheme based on a one-way hash function +(in our version, this is MD4 for compatibility; other versions have +used MD5 and DES-MAC). S/Key has been a standard part of all FreeBSD +distributions since version 1.1.5, and is also implemented on a large +and growing number of other systems. S/Key is a registered trademark +of Bell Communications Research, Inc. + +<!-- XXX - is there a better word to use than UNIX? --> +<p>There are three different sorts of passwords which we will talk about +in the discussion below. The first is your usual UNIX-style or Kerberos +password; we'll call this a ``UNIX password''. The second sort is the +one-time password which is generated by the S/Key `<tt/key/' program and +accepted by the `<tt/keyinit/' program and the login prompt; we'll call +this a ``one-time password''. The final sort of password is the +secret password which you give to the `<tt/key/' program (and sometimes the +`<tt/keyinit/' program) which it uses to generate one-time passwords; we'll +call it a ``secret password'' or just unqualified ``password''. + +<p>The secret password does not necessarily have anything to do with your +UNIX password (while they can be the same, this is not recommended). +While UNIX passwords are limited to eight characters in length, your +S/Key secret password can be as long as you like; I use seven-word +phrases. In general, the S/Key system operates completely +independently of the UNIX password system. + +<p>There are in addition two other sorts of data involved in the S/Key +system; one is called the ``seed'' or (confusingly) ``key'', and +consists of two letters and five digits, and the other is the +``iteration count'' and is a number between 100 and 1. S/Key +constructs a one-time password from these components by concatenating +the seed and the secret password, then applying a one-way hash (the +RSA Data Security, Inc., MD4 secure hash function) iteration-count +times, and turning the result into six short English words. The +`<tt/login/' and `<tt/su/' programs keep track of the last one-time +password used, and the user is authenticated if the hash of the +user-provided password is equal to the previous password. Because a +one-way hash function is used, it is not possible to generate future +one-time passwords having overheard one which was successfully used; +the iteration count is decremented after each successful login to keep +the user and login program in sync. (When you get the iteration count +down to 1, it's time to reinitialize S/Key.) + +<p>There are four programs involved in the S/Key system which we will +discuss below. The `<tt/key/' program accepts an iteration count, a +seed, and a secret password, and generates a one-time password. The +`<tt/keyinit/' program is used to initialized S/Key, and to change +passwords, iteration counts, or seeds; it takes either a secret +password, or an iteration count, seed, and one-time password. The +`<tt/keyinfo/' program examines the <tt>/etc/skeykeys</tt> file and +prints out the invoking user's current iteration count and seed. +Finally, the `<tt/login/' and `<tt/su/' programs contain the necessary +logic to accept S/Key one-time passwords for authentication. The +`<tt/login/' program is also capable of disallowing the use of UNIX +passwords on connections coming from specified addresses. + +<p>There are four different sorts of operations we will cover. The first +is using the `<tt/keyinit/' program over a secure connection to set up +S/Key for the first time, or to change your password or seed. The +second operation is using the `<tt/keyinit/' program over an insecure +connection, in conjunction with the `<tt/key/' program over a secure +connection, to do the same. The third is using the `<tt/key/' program to +log in over an insecure connection. The fourth is using the `<tt/key/' +program to generate a number of keys which can be written down or +printed out to carry with you when going to some location without +secure connections to anywhere (like at a conference). + +<sect1><heading>Secure connection initialization</heading> + +<p>To initialize S/Key, change your password, or change your seed while +logged in over a secure connection (e.g., on the console of a machine), +use the `<tt/keyinit/' command without any parameters while logged in as +yourself: + +<tscreen><verb> +$ keyinit +Updating wollman: ) these will not appear if you +Old key: ha73895 ) have not used S/Key before +Reminder - Only use this method if you are directly connected. +If you are using telnet or rlogin exit with no password and use keyinit -s. +Enter secret password: ) I typed my pass phrase here +Again secret password: ) I typed it again + +ID wollman s/key is 99 ha73896 ) discussed below +SAG HAS FONT GOUT FATE BOOM ) +</verb></tscreen> + +<p>There is a lot of information here. At the `Enter secret password:' +prompt, you should enter some password or phrase (I use phrases of +minimum seven words) which will be needed to generate login keys. The +line starting `ID' gives the parameters of your particular S/Key +instance: your login name, the iteration count, and seed. When +logging in with S/Key, the system will remember these parameters and +present them back to you so you don't have to remember them. The last +line gives the particular one-time password which corresponds to those +parameters and your secret password; if you were to re-login +immediately, this one-time password is the one you would use. + +<sect1><heading>Insecure connection initialization</heading> + +<p>To initialize S/Key or change your password or seed over an insecure +connection, you will need to already have a secure connection to some +place where you can run the `<tt/key/' program; this might be in the form +of a desk accessory on a Macintosh, or a shell prompt on a machine you +trust (we'll show the latter). You will also need to make up an +iteration count (100 is probably a good value), and you may make up +your own seed or use a randomly-generated one. Over on the insecure +connection (to the machine you are initializing), use the `<tt/keyinit -s/' +command: + +<tscreen><verb> +$ keyinit -s +Updating wollman: +Old key: kh94741 +Reminder you need the 6 english words from the skey command. +Enter sequence count from 1 to 9999: 100 ) I typed this +Enter new key [default kh94742]: +s/key 100 kh94742 +</verb></tscreen> + +To accept the default seed (which the `keyinit' program confusingly +calls a `key'), press return. Then move over to your secure +connection or S/Key desk accessory, and give it the same parameters: + +<tscreen><verb> +$ key 100 kh94742 +Reminder - Do not use this program while logged in via telnet or rlogin. +Enter secret password: ) I typed my secret password +HULL NAY YANG TREE TOUT VETO +</verb></tscreen> + +Now switch back over to the insecure connection, and copy the one-time +password generated by `<tt/key/' over to the `<tt/keyinit/' program: + +<tscreen><verb> +s/key access password: HULL NAY YANG TREE TOUT VETO + +ID wollman s/key is 100 kh94742 +HULL NAY YANG TREE TOUT VETO +</verb></tscreen> + +The rest of the description from the previous section applies here as +well. + +<sect1><heading>Diversion: a login prompt</heading> + +<p>Before explaining how to generate one-time passwords, we should go +over an S/Key login prompt: + +<tscreen><verb> +$ telnet himalia +Trying 18.26.0.186... +Connected to himalia.lcs.mit.edu. +Escape character is '^]'. +s/key 92 hi52030 +Password: +</verb></tscreen> + +Note that, before prompting for a password, the login program +prints out the iteration number and seed which you will need in order +to generate the appropriate key. You will also find a useful feature +(not shown here): if you press return at the password prompt, the +login program will turn echo on, so you can see what you are typing. +This can be extremely useful if you are attempting to type in an S/Key +by hand, such as from a printout. + +<p>If this machine were configured to disallow UNIX passwords over a +connection from my machine, the prompt would have also included the +annotation `<tt>(s/key required)</tt>', indicating that only S/Key one-time +passwords will be accepted. + +<sect1><heading>Generating a single one-time password</heading> + +<p>Now, to generate the one-time password needed to answer this login +prompt, we use a trusted machine and the `<tt/key/' program. (There are +versions of the `<tt/key/' program from DOS and Windows machines, and there +is an S/Key desk accessory for Macintosh computers as well.) The +command-line `<tt/key/' program takes as its parameters the iteration count +and seed; you can cut-and-paste right from the login prompt starting +at ``<tt/key/'' to the end of the line. Thus: + +<tscreen><verb> +$ key 92 hi52030 ) pasted from previous section +Reminder - Do not use this program while logged in via telnet or rlogin. +Enter secret password: ) I typed my secret password +ADEN BED WOLF HAW HOT STUN +</verb></tscreen> + +And in the other window: + +<tscreen><verb> +s/key 92 hi52030 ) from previous section +Password: + (turning echo on) +Password:ADEN BED WOLF HAW HOT STUN +Last login: Wed Jun 28 15:31:00 from halloran-eldar.l +[etc.] +</verb></tscreen> + +This is the easiest mechanism <em/if/ you have a trusted machine. + +<sect1><heading>Generating multiple one-time passwords</heading> + +<p>Sometimes we have to go places where no trusted machines or +connections are available. In this case, it is possible to use the +`<tt/key/' command to generate a number of one-time passwords in the same +command; these can then be printed out. For example: + +<tscreen><verb> +$ key -n 25 57 zz99999 +Reminder - Do not use this program while logged in via telnet or rlogin. +Enter secret password: +33: WALT THY MALI DARN NIT HEAD +34: ASK RICE BEAU GINA DOUR STAG +[...] +56: AMOS BOWL LUG FAT CAIN INCH +57: GROW HAYS TUN DISH CAR BALM +</verb></tscreen> + +The `<tt/-n 25/' requests twenty-five keys in sequence; the `<tt/57/' indicates +the <em/ending/ iteration number; and the rest is as before. Note that +these are printed out in <em/reverse/ order of eventual use. If you're +really paranoid, you might want to write the results down by hand; +otherwise you can cut-and-paste into `<tt/lpr/'. Note that each line shows +both the iteration count and the one-time password; you may still find +it handy to scratch off passwords as you use them. + +<sect1><heading>Restricting use of UNIX passwords</heading> + +<p>The configuration file <tt>/etc/skey.access</tt> can be used to +configure restrictions on the use of UNIX passwords based on the host +name, user name, terminal port, or IP address of a login session. The +complete format of the file is documented in the <em/skey.access/(5) +manual page; there are also some security cautions there which should +be read before depending on this file for security. + +<p>If there is no <tt>/etc/skey.access</tt> file (which is the default +state as FreeBSD is shipped), then all users will be allowed to use +UNIX passwords. If the file exists, however, then all users will be +required to use S/Key unless explicitly permitted to do otherwise by +configuration statements in the <tt/skey.access/ file. In all cases, +UNIX passwords are permitted on the console. + +<p>Here is a sample configuration file which illustrates the three most +common sorts of configuration statements: + +<tscreen><verb> +permit internet 18.26.0.0 255.255.0.0 +permit user jrl +permit port ttyd0 +</verb></tscreen> + +The first line (`<tt/permit internet/') allows users whose IP source +address (which is vulnerable to spoofing) matches the specified value +and mask, to use UNIX passwords. This should not be considered a +security mechanism, but rather, a means to remind authorized users +that they are using an insecure network and need to use S/Key for +authentication. + +<p>The second line (`<tt/permit user/') allows the specified user to +use UNIX passwords at any time. Generally speaking, this should only +be used for people who are either unable to use the `<tt/key/' +program, like those with dumb terminls, or those who are uneducable. + +<p>The third line (`<tt/permit port/') allows all users logging in on +the specified terminal line to use UNIX passwords; this would be used +for dial-ups. + diff --git a/share/examples/sup/ports-supfile b/share/examples/sup/ports-supfile new file mode 100644 index 000000000000..ffc078be4542 --- /dev/null +++ b/share/examples/sup/ports-supfile @@ -0,0 +1,26 @@ +ports-base release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-archivers release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-benchmarks release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-audio release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-cad release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-comms release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-databases release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-devel release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-editors release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-emulators release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-games release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-graphics release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-japanese release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-lang release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-mail release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-math release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-net release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-news release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-plan9 release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-print release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-russian release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-security release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-shells release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-sysutils release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-utils release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old +ports-x11 release=current host=SUP.FreeBSD.ORG hostbase=/home base=/usr prefix=/usr/ports delete old diff --git a/share/examples/sup/secure-stable-supfile b/share/examples/sup/secure-stable-supfile new file mode 100644 index 000000000000..61ac7f0b493a --- /dev/null +++ b/share/examples/sup/secure-stable-supfile @@ -0,0 +1,2 @@ +eBones release=stable host=sup.internat.freebsd.org hostbase=/home base=/usr prefix=/usr/src delete old compress +secure release=stable host=sup.internat.freebsd.org hostbase=/home base=/usr prefix=/usr/src delete old compress diff --git a/share/examples/sup/secure-supfile b/share/examples/sup/secure-supfile new file mode 100644 index 000000000000..716f70c0bb8f --- /dev/null +++ b/share/examples/sup/secure-supfile @@ -0,0 +1,2 @@ +eBones release=current host=sup.internat.freebsd.org hostbase=/home base=/usr prefix=/usr/src delete old compress +secure release=current host=sup.internat.freebsd.org hostbase=/home base=/usr prefix=/usr/src delete old compress diff --git a/share/examples/sup/stable-supfile b/share/examples/sup/stable-supfile new file mode 100644 index 000000000000..5ba1db895a79 --- /dev/null +++ b/share/examples/sup/stable-supfile @@ -0,0 +1,15 @@ +src-base release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-bin release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +#src-eBones release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-etc release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-games release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-gnu release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-include release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-lib release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-libexec release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-sbin release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +#src-secure release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-share release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-sys release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-usrbin release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-usrsbin release=stable host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix diff --git a/share/examples/sup/standard-supfile b/share/examples/sup/standard-supfile new file mode 100644 index 000000000000..6d0ed19485a3 --- /dev/null +++ b/share/examples/sup/standard-supfile @@ -0,0 +1,15 @@ +src-base release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-bin release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +#src-eBones release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-etc release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-games release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-gnu release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-include release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-lib release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-libexec release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-sbin release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +#src-secure release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-share release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-sys release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-usrbin release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix +src-usrsbin release=current host=sup.FreeBSD.org hostbase=/home base=/usr prefix=/usr/src delete old use-rel-suffix diff --git a/share/man/man4/man4.i386/cy.4 b/share/man/man4/man4.i386/cy.4 new file mode 100644 index 000000000000..c1e2dbd8fc3f --- /dev/null +++ b/share/man/man4/man4.i386/cy.4 @@ -0,0 +1,241 @@ +.\" Copyright (c) 1990, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Systems Programming Group of the University of Utah Computer +.\" Science Department. +.\" 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 the University of +.\" California, Berkeley and its contributors. +.\" 4. 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 BY THE REGENTS 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 REGENTS 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. +.\" +.\" from: @(#)dca.4 5.2 (Berkeley) 3/27/91 +.\" from: com.4,v 1.1 1993/08/06 11:19:07 cgd Exp +.\" from: sio.4,v 1.16 1995/06/26 06:05:30 bde Exp $ +.\" $Id$ +.\" +.Dd October 10, 1995 +.Dt CY 4 i386 +.Os FreeBSD +.Sh NAME +.Nm cy +.Nd +Cyclades Cyclom-8Y and Cyclom-16Y serial driver +.Sh SYNOPSIS +.Cd "device cy0 at isa? tty irq 10 iomem 0xd4000 iosiz 0x2000 vector cyintr +.Cd "device cy1 at isa? tty irq 11 iomem 0xd6000 iosiz 0x2000 vector cyintr +.sp +Minor numbering: +.br +0b\fIOLIMMMMM\fR +.br + call\fBO\fRut +.br + \fBL\fRock +.br + \fBI\fRnitial +.br + \fBMMMMMM\fRinor +.Sh DESCRIPTION +The +.Nm cy +driver provides support for Cyrix CD1400-based +.Tn EIA +.Tn RS-232C +.Pf ( Tn CCITT +.Tn V.24 ) +communications interfaces (ports) on Cyclades Cyclom-Y boards. +Each CD1400 provides 4 ports. +Each Cyclom-8Y has 2 CD1400's giving 8 ports. +Each Cyclom-16Y's has 4 CD1400's giving 16 ports. +.Pp +Input and output for each line may set independently +to the following speeds: +50, 75, 110, 134.5, 150, 300, 600, 1200, 1800, 2400, 4800, 9600, +19200, 38400, 57600, or 115200 bps. +Other speeds of up to 150000 are supported by the termios interface +but not by the sgttyb compatibility interface. +The CD1400 is not fast enough to handle speeds above 115200 bps +effectively. +It can transmit on a single line at slightly more than 115200 bps, +but when 4 lines are active in both directions its limit is about +90000 bps on each line. +.\" XXX the following should be true for all serial drivers and +.\" should not be repeated in the man pages for all serial drivers. +.\" It was copied from sio.4. The only change was s/sio/cy/g. +.Pp +Serial ports controlled by the +.Nm cy +driver can be used for both `callin' and `callout'. +For each port there is a callin device and a callout device. +The minor number of the callout device is 128 higher +than that of the corresponding callin port. +The callin device is general purpose. +Processes opening it normally wait for carrier +and for the callout device to become inactive. +The callout device is used to steal the port from +processes waiting for carrier on the callin device. +Processes opening it do not wait for carrier +and put any processes waiting for carrier on the callin device into +a deeper sleep so that they do not conflict with the callout session. +The callout device is abused for handling programs that are supposed +to work on general ports and need to open the port without waiting +but are too stupid to do so. +.Pp +The +.Nm cy +driver also supports an initial-state and a lock-state control +device for each of the callin and the callout "data" devices. +The minor number of the initial-state device is 32 higher +than that of the corresponding data device. +The minor number of the lock-state device is 64 higher +than that of the corresponding data device. +The termios settings of a data device are copied +from those of the corresponding initial-state device +on first opens and are not inherited from previous opens. +Use +.Xr stty 1 +in the normal way on the initial-state devices to program +initial termios states suitable for your setup. +.sp +The lock termios state acts as flags to disable changing +the termios state. E.g., to lock a flag variable such as +CRTSCTS, use +.Nm stty crtscts +on the lock-state device. Speeds and special characters +may be locked by setting the corresponding value in the lock-state +device to any nonzero value. +.sp +Correct programs talking to correctly wired external devices +work with almost arbitrary initial states and almost no locking, +but other setups may benefit from changing some of the default +initial state and locking the state. +In particular, the initial states for non (POSIX) standard flags +should be set to suit the devices attached and may need to be +locked to prevent buggy programs from changing them. +E.g., CRTSCTS should be locked on for devices that support +RTS/CTS handshaking at all times and off for devices that don't +support it at all. CLOCAL should be locked on for devices +that don't support carrier. HUPCL may be locked off if you don't +want to hang up for some reason. In general, very bad things happen +if something is locked to the wrong state, and things should not +be locked for devices that support more than one setting. The +CLOCAL flag on callin ports should be locked off for logins +to avoid certain security holes, but this needs to be done by +getty if the callin port is used for anything else. +.Sh FILES +.Bl -tag -width /dev/ttyic? -compact +.\" XXX more cloning: s/d/c/g. +.It Pa /dev/ttyc? +for callin ports +.It Pa /dev/ttyic? +.It Pa /dev/ttylc? +corresponding callin initial-state and lock-state devices +.sp +.\" XXX more cloning: s/a/c/g. No consistency :-(. +.It Pa /dev/cuac? +for callout ports +.It Pa /dev/cuaic? +.It Pa /dev/cualc? +corresponding callout initial-state and lock-state devices +.El +.sp +.Bl -tag -width /etc/rc.serial -compact +.It Pa /etc/rc.serial +examples of setting the initial-state and lock-state devices +.\" XXX no examples in rc.serial for cy ports specifically. +for sio ports (change the device names for cy ports) +.El +.Pp +The devices numbers are made from the set [0-9a-v] so that more than +10 ports can be supported. +.\" XXX this is for cy only. +[0-9a-f] are for the cy0 and [g-v] are for cy1. +For Cyclom-8Y's, only the first 8 of these are used. +.Sh DIAGNOSTICS +.Bl -diag +.\" XXX back to s/sio/cy/g. +.It cy%d: silo overflow. +Problem in the interrupt handler. +.El +.Bl -diag +.It cy%d: interrupt-level buffer overflow. +Problem in the bottom half of the driver. +.El +.Bl -diag +.It cy%d: tty-level buffer overflow. +Problem in the application. +Input has arrived faster than the given module could process it +and some has been lost. +.El +.\" .Bl -diag +.\" .It sio%d: reduced fifo trigger level to %d. +.\" Attempting to avoid further silo overflows. +.\" .El +.Sh SEE ALSO +.Xr tty 4 , +.Xr termios 4 , +.Xr comcontrol 8 , +.Xr stty 1 . +.Sh HISTORY +The +.Nm +driver is derived from the +.Nm sio +driver and the NetBSD +.Nm +driver and is +.Ud +.Sh BUGS +The naming scheme and the minor numbering scheme limit the number +of ports to 32. +.Pp +BREAK is not yet implemented. +.Pp +Serial consoles are not implemented. +.Pp +Data loss may occur at very high baud rates on slow systems, +or with too many ports on any system, +or on heavily loaded systems when crtscts cannot be used. +.Pp +There are too many compile-time-only flags. +The CD1400 has slightly smaller fifos than the NS16550 (12 bytes +instead of 16), so it needs pseudo-dma more than a NS16550. The +default configuration is optimized for generality at about a 30% +relative cost in efficiency. These compile-time defines may be +changed for higher efficiency: +.Pp +RxFifoThreshold: default 6; on a 486DX-33, this works for 8 ports +talking to each other at 115200 bps; 11 works for 8 ports talking +to each other at 57600 bps. The low threshold is not for FreeBSD, +it's for the CD1400, which can't really keep up with 115200 bps. +.Pp +PollMode: required for Cyclom-16Y's; costs 10-20% relative efficiency +on Cyclom-8Y's (more with a low RxFifoThreshold). +.Pp +SOFT_HOTCHAR: required in addition to the small RxFifoThreshold +to avoid overruns with SLIP and PPP for 8 ports at 115200 bps. +Costs 5% relative efficiency. diff --git a/share/man/man4/man4.i386/dgb.4 b/share/man/man4/man4.i386/dgb.4 new file mode 100644 index 000000000000..b72ae1412f53 --- /dev/null +++ b/share/man/man4/man4.i386/dgb.4 @@ -0,0 +1,362 @@ +.\" Copyright (c) 1990, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Systems Programming Group of the University of Utah Computer +.\" Science Department. +.\" 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 the University of +.\" California, Berkeley and its contributors. +.\" 4. 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 BY THE REGENTS 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 REGENTS 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. +.\" +.\" from: @(#)dca.4 5.2 (Berkeley) 3/27/91 +.\" from: com.4,v 1.1 1993/08/06 11:19:07 cgd Exp +.\" from: sio.4,v 1.15 1994/12/06 20:14:30 bde Exp +.\" $Id$ +.\" +.Dd Oct 13, 1995 +.Dt DGB 4 i386 +.Os FreeBSD +.Sh NAME +.Nm dgb +.Nd +DigiBoard intelligent serial cards driver +.Sh SYNOPSIS +.Cd "options" \&"NDGBPORTS=8\&" +.Cd "device dgb0 at isa? tty port 0x220 iomem 0xfc0000 iosiz ? flags 0x0 +All values are just examples. +.sp +The \fBNDGBPORTS\fR option defines the total number of ports on all cards +installed in the system. When not defined the number is computed: + +.br + default \fBNDGBPORTS\fR = number_of_described_DigiBoard_cards * 16 + +If it is less than the actual number of ports +the system will be able to use only the +first \fBNDGBPORTS\fR ports. If it is greater then all ports will be usable +but some memory will be wasted. +.sp +Meaning of \fBflags\fR: +.br +\fB0x0001\fR use alternate pinout (exchange DCD and DSR lines) +.br +\fB0x0002\fR don't use 8K window mode of PC/Xe +.sp +Device numbering: +.br +0b\fICC\fRmmmmmmmm\fIOLIPPPPP\fR +.br + \fBCC\fRard number +.br + mmmmmmmm\fRajor number +.br + call\fBO\fRut +.br + \fBL\fRock +.br + \fBI\fRnitial +.br + \fBPPPPP\fRort number +.Sh DESCRIPTION +The +.Nm dgb +driver provides support for DigiBoard PC/Xe and PC/Xi series intelligent +serial multiport cards with asynchronous interfaces based on the +.Tn EIA +.Tn RS-232C +.Pf ( Tn CCITT +.Tn V.24 ) +standard. +.Pp +Input and output for each line may set to one of following baud rates; +50, 75, 110, 134.5, 150, 300, 600, 1200, 1800, 2400, 4800, 9600, +19200, 38400, 57600, or for newer versions of cards 115200. +.Pp +The driver doesn't use any interrupts, it is ``polling-based''. This means that +it uses clock interrupts instead of interrupts generated by DigiBoard cards and +checks the state of cards 25 times per second. This is practical because the +DigiBoard cards have large input and output buffers (more than 1Kbyte per +port) and hardware that allows efficiently finding the port that needs +attention. The only problem seen with this policy is slower +SLIP and PPP response. +.sp +Each line in the kernel configuration file describes one card, not one port +as in the +.Nm sio +driver. +.sp +The +.Nm flags +keyword may be used on each +.Nm device dgb +line in the kernel configuration file +to change the pinout of the interface or to use new PC/Xe cards +which can work with an 8K memory window in compatibility mode +(with a 64K memory window). Note +that using 8K memory window doesn't mean shorter input/output buffers, it means +only that all buffers will be mapped to the same memory address and switched as +needed. +.sp +The +.Nm port +value must be the same +as the +.Nm port +set on the card by jumpers. +For PC/Xi cards the same rule is applicable to the +.Nm iomem +value. It must be the same as the memory address set on the card +by jumpers. +.\"Some documentation gives the address as a ``paragraph'' or ``segment''; +.\"you can get the value of address by adding the digit "0" at end of +.\"paragraph value, e.g., 0xfc000 -> 0xfc0000. +For PC/Xe cards there is no need to use jumpers for this purpose. +In fact there are no jumpers to do it. Just +write the address you want as the +.Nm iomem +value in kernel config file and the card will be programmed +to use this address. +.sp +The same range of memory addresses may be used +for all the DigiBoards installed +(but not for any other card or real memory). DigiBoards +with a large amount of memory (256K or 512K and perhaps +even 128K) must be mapped +to memory addresses outside of the first megabyte. If the computer +has more than 15 megabytes of memory then there is no free address space +outside of the first megabyte where such DigiBoards can be mapped. +In this case you +may need to reduce the amount of memory in the computer. +But many machines provide a better solution. They have the ability to +``turn off'' the memory in the 16th megabyte (addresses 0xF00000 - 0xFFFFFF) +using the +BIOS setup. Then the DigiBoard's address space can be set to this ``hole''. +.\" XXX the following should be true for all serial drivers and +.\" should not be repeated in the man pages for all serial drivers. +.\" It was copied from sio.4. The only changes were s/sio/dgb/g. +.Pp +Serial ports controlled by the +.Nm dgb +driver can be used for both `callin' and `callout'. +For each port there is a callin device and a callout device. +The minor number of the callout device is 128 higher +than that of the corresponding callin port. +The callin device is general purpose. +Processes opening it normally wait for carrier +and for the callout device to become inactive. +The callout device is used to steal the port from +processes waiting for carrier on the callin device. +Processes opening it do not wait for carrier +and put any processes waiting for carrier on the callin device into +a deeper sleep so that they do not conflict with the callout session. +The callout device is abused for handling programs that are supposed +to work on general ports and need to open the port without waiting +but are too stupid to do so. +.Pp +The +.Nm dgb +driver also supports an initial-state and a lock-state control +device for each of the callin and the callout "data" devices. +The minor number of the initial-state device is 32 higher +than that of the corresponding data device. +The minor number of the lock-state device is 64 higher +than that of the corresponding data device. +The termios settings of a data device are copied +from those of the corresponding initial-state device +on first opens and are not inherited from previous opens. +Use +.Xr stty 1 +in the normal way on the initial-state devices to program +initial termios states suitable for your setup. +.sp +The lock termios state acts as flags to disable changing +the termios state. E.g., to lock a flag variable such as +CRTSCTS, use +.Nm stty crtscts +on the lock-state device. Speeds and special characters +may be locked by setting the corresponding value in the lock-state +device to any nonzero value. +.sp +Correct programs talking to correctly wired external devices +.\" XXX change next line in other man pages too, and rewrite this paragraph. +work with almost arbitrary initial states and no locking, +but other setups may benefit from changing some of the default +initial state and locking the state. +In particular, the initial states for non (POSIX) standard flags +should be set to suit the devices attached and may need to be +locked to prevent buggy programs from changing them. +E.g., CRTSCTS should be locked on for devices that support +RTS/CTS handshaking at all times and off for devices that don't +support it at all. CLOCAL should be locked on for devices +that don't support carrier. HUPCL may be locked off if you don't +want to hang up for some reason. In general, very bad things happen +if something is locked to the wrong state, and things should not +be locked for devices that support more than one setting. The +CLOCAL flag on callin ports should be locked off for logins +to avoid certain security holes, but this needs to be done by +getty if the callin port is used for anything else. +.Sh FILES +.Bl -tag -width /dev/ttyiD?? -compact +.It Pa /dev/ttyD?? +for callin ports +.It Pa /dev/ttyiD?? +.It Pa /dev/ttylD?? +corresponding callin initial-state and lock-state devices +.sp +.It Pa /dev/cuaD?? +for callout ports +.It Pa /dev/cuaiD?? +.It Pa /dev/cualD?? +corresponding callout initial-state and lock-state devices +.El +.sp +.Bl -tag -width /etc/rc.serial -compact +.It Pa /etc/rc.serial +examples of setting the initial-state and lock-state devices +.El +.Pp +The first question mark in these device names +means the number of the card from the set [0-9] and the +second question mark means the number of the port on the card from the set +[0-9a-v]. +.Sh DIAGNOSTICS +You may enable extended diagnostics by defining DEBUG at the +start of the source file dgb.c. +.Bl -diag +.It dgb\fIX\fB: warning: address \fIN\fB truncated to \fIM\fB +The memory address for the PC/Xe's 8K window is misaligned (it should be +on an 8K boundary) or outside of the first megabyte. +.El +.Bl -diag +.It dgb\fIX\fB: 1st reset failed +Problems with accessing I/O port of the card, probably +the wrong \fBport\fR value is specified in the kernel config file. +.El +.Bl -diag +.It dgb\fIX\fB: 2nd reset failed +Problems with hardware. +.El +.Bl -diag +.It dgb\fIX\fB: \fIN\fB[st,nd,rd,th] memory test failed +Problems with accessing the memory of the card, probably +the wrong \fBiomem\fR value is specified in the kernel config file. +.El +.Bl -diag +.It dgb\fIX\fB: BIOS start failed +Problems with starting the on-board BIOS. Probably the memory addresses of the +DigiBoard overlap with some other device or with RAM. +.El +.Bl -diag +.It dgb\fIX\fB: BIOS download failed +Problems with the on-board BIOS. Probably the memory addresses of the +DigiBoard overlap with some other device or with RAM. +.El +.Bl -diag +.It dgb\fIX\fB: FEP code download failed +Problems with downloading of the Front-End Processor's micro-OS. +Probably the memory addresses of the +DigiBoard overlap with some other device or with RAM. +.El +.Bl -diag +.It dgb\fIX\fB: FEP/OS start failed +Problems with starting of the Front-End Processor's micro-OS. +Probably the memory addresses of the +DigiBoard overlap with some other device or with RAM. +.El +.Bl -diag +.It dgb\fIX\fB: too many ports +This DigiBoard reports that it has more than 32 ports. +Perhaps a hardware problem or +the memory addresses of the +DigiBoard overlap with some other device or with RAM. +.El +.Bl -diag +.It dgb\fIX\fB: only \fIN\fB ports are usable +The NDGBPORTS parameter is too small and there is only enough space allocated +for \fIN\fR ports on this card. +.El +.Bl -diag +.It dgb\fIX\fB: port \fIY\fB is broken +The on-board diagnostic has reported that the specified port has hardware +problems. +.El +.Bl -diag +.It dgb\fIX\fB: polling of disabled board stopped +Internal problems in the polling logic of driver. +.El +.Bl -diag +.It dgb\fIX\fB: event queue's head or tail is wrong! +Internal problems in the driver or hardware. +.El +.Bl -diag +.It dgb\fIX\fB: port \fIY\fB: got event on nonexisting port +Some status changed on a port that is physically present but is +unusable due to misconfiguration. +.El +.Bl -diag +.It dgb\fIX\fB: port \fIY\fB: event \fIN\fB mstat \fIM\fB lstat \fIK\fB +The driver got a strange event from card. Probably this means that you have a +newer card with an extended list of events or some other hardware problem. +.El +.Bl -diag +.It dgb\fIX\fB: port \fIY\fB: overrun +Input buffer has filled up. Problems in polling logic of driver. +.El +.Bl -diag +.It dgb\fIX\fB: port \fIY\fB: FEP command on disabled port +Internal problems in driver. +.El +.Bl -diag +.It dgb\fIX\fB: port \fIY\fB: timeout on FEP command +Problems in hardware. +.Sh SEE ALSO +.Xr tty 4 , +.Xr termios 4 , +.Xr comcontrol 8 , +.\" XXX add next line to many other drivers. +.Xr MAKEDEV 8 , +.Xr stty 1 . +.Sh HISTORY +The +.Nm +driver is derived from the +.Nm sio +driver and the DigiBoard driver from +.Nm Linux +and is +.Ud +.Sh BUGS +The implementation of sending BREAK is broken. BREAK of fixed length of 1/4 s +is sent anyway. +.Pp +There was a bug in implementation of +.Xr select 2 . +It is fixed now but not widely tested yet. +.Pp +There is no ditty command. Most of its functions (alternate pinout, +speed up to 115200 baud, etc.) are implemented in the driver itself. Some +other functions are missing. diff --git a/share/man/man4/man4.i386/si.4 b/share/man/man4/man4.i386/si.4 new file mode 100644 index 000000000000..aa346f614167 --- /dev/null +++ b/share/man/man4/man4.i386/si.4 @@ -0,0 +1,169 @@ +.\" $Id$ +.\" The following requests are required for all man pages. +.Dd September 16, 1995 +.Os FreeBSD +.Dt SI 4 +.Sh NAME +.Nm si +- Driver for Specialix International SI/XIO 8-32 port intelligent serial card. +.Sh SYNOPSIS +.Nm "device si0 at isa? tty irq 12 iomem 0xd0000 vector siintr" +.Sh DESCRIPTION +The Specialix SI and XIO hardware makes up an 8 to 32 port RS-232 serial +multiplexor. +.Pp +This driver was ported and tested on an ISA bus machine, and has rudimentry +support for operation on an EISA bus system as well, but as of this time the +EISA version has not been tested by the Author - it may or may not work. +.Pp +The system uses two components.. A "Host adapter", which is plugged into +an ISA/EISA slot and provides intelligence and buffering/processing +capabilities, as well as an external bus in the form of a 50 pin cable. +.Pp +On this cable, "modules" are connected. The "SI" module comes in a 4 and 8 +port version, and has simple UARTS. The "XIO" module comes only in an 8 port +version, and has two powerful RISC-like UARTS as well. +.Pp +The host adapter polls and transfers data between the modules and the main +Operating system. The Host adapter provides a 256 byte transmit and 256 byte +receive FIFO for each of the 32 ports that it can maintain. +.Pp +The XIO module panels can operate each of their 8 ports at 115,200 baud, while +the SI version can run at 57,600 baud. +.Pp +The host adapter uses a shared memory block in the traditional ISA bus +"hole" betweem 0xA0000 and 0xEFFFF. The adapter can be configured outside +range, but requires the memory range to be explicitly non-cached. The +driver does not yet support this mode of operation. +.Pp +The adapter can use Irq's 11, 12 or 15. It is rumoured that the ISA adapter +cards provide their own tri-state drivers and pullups, and may be able to +share an IRQ between all SI/XIO host cards. This has not been tested, and +the driver does not support this mode of operation. The actual IRQ used is +soft-configured onto the host card at boot time, but automatic selection +of a free IRQ is not yet implemented in the FreeBSD version. +.Pp +The si device driver may have some of it's configuration settings changed +at run-time with the +.Xr sicontrol 8 +utility. +.Pp +The si device driver also responds to the +.Xr comcontrol 8 +utility for configuring drain-on-close timeouts. +.Pp +An open on a /dev device node controlled by the si driver obeys the same +semantics as the +.Xr sio 4 +driver. It fully supports the usual semantics of the cua ports, and the +"initial termios" and "locked termios" settings. In summary, an open on a +tty port will block until DCD is raised, unless O_NONBLOCK is specified. +CLOCAL is honored. An open on a cua port will always succeed, but DCD +transitions will be honored after DCD rises for the first time. +by the si driver obeys the same +semantics as the +.Xr sio 4 +driver. It fully supports the usual semantics of the cua ports, and the +"initial termios" and "locked termios" settings. In summary, an open on a +tty port will block until DCD is raised, unless O_NONBLOCK is specified. +CLOCAL is honored. An open on a cua port will always succeed, but DCD +transitions will be honored after DCD rises for the first time. +.Pp +Normally, up to four SI/XIO host cards may be controlled by the si driver, +but due to the lack of available interrupts that the card can be configured +to use, only three may be presently used. Polling operation is not currently +implemented, although it is a standard mode of operation for Specialix shipped +drivers. Once this is implemented, all four cards may be used. +.Pp +The lowest 5 bits of the minor device number are used to select the port +number on the mudule cluster. +si driver, +but due to the lack of available interrupts that the card can be configured +to use, only three may be presently used. Polling operation is not currently +implemented, although it is a standard mode of operation for Specialix shipped +drivers. Once this is implemented, all four cards may be used. +.Pp +The lowest 5 bits of the minor device number are used to select the port +number on the mudule cluster. The next 2 bits select which of 4 host adapter +cards. This allows a maximum of 128 ports on this driver. +.Pp +Bit 7 is used to differentiate a tty/dialin port (bit 7=0) and a +cua/callout port (bit 7=1). +.Pp +Bit 8 through 15 (on FreeBSD) are unavailable as they are a shadow of the +major device number. +.Pp +If bit 16 is a 1, the device node is referring to the "initial state" device. +This "initial state" is used to prime the +.Xr termios 4 +settings of the device when it is initially opened. +If bit 17 is a 1, the device node is referring to the "locked state" device. +The "locked state" is used to prevent the +.Xr termios 4 +settings from being changed. +.Pp +To manipulate the initial/locked settings, the +.Xr stty 1 +command is useful. When setting the "locked" variables, enabling the mode +on the lock device will lock the termios mode, while disabling the mode will +unlock it. +.\" The following requests should be uncommented and used where appropriate. +.\" This next request is for sections 2 and 3 function return values only. +.\" .Sh RETURN VALUES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" .Sh ENVIRONMENT +.Sh FILES +.Bl -tag -width /dev/si_control -compact +.It Pa /dev/si_control +global driver control file for +.Xr sicontrol 8 +.It Pa /dev/ttyA* +terminal/dialin ports +.It Pa /dev/cuaA* +dialout ports +.It Pa /dev/ttyiA* +initial termios state devices +.It Pa /dev/ttylA* +locked termios state devices +.El +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and fprintf/stderr type diagnostics) +.\" .Sh DIAGNOSTICS +.\" The next request is for sections 2 and 3 error and signal handling only. +.\" .Sh ERRORS +.Sh SEE ALSO +.Xr stty 1 , +.Xr termios 4 , +.Xr tty 4 , +.Xr sio 4 , +.Xr sicontrol 8 , +.Xr comcontrol 8 . +.\" .Sh STANDARDS +.Sh HISTORY +This driver is loosely based on driver code originating at Specialix, which +was ported to run on BSDI by +.Nm Andy Rutter <andy@specialix.co.uk> . +The System V driver source is/was available by ftp from +.Nm ftp.specialix.co.uk . +.Pp +This driver is not supported by Specialix International. +.Sh AUTHORS +.Nm Peter Wemm <peter@freebsd.org> +obtained the code from Andy Rutter and ported it to FreeBSD, with a large +amount of invalueable assistance from +.Nm Bruce Evans <bde@zeta.org.au> +.Pp +Man page by Peter Wemm. +.Sh BUGS +The EISA support is untested. +.Pp +The interrupt tuning rate is not believed to be optimal at this time for +maximum efficiency. +.Pp +Receiver tty buffer flushing is not yet enabled, like many other drivers. +.Pp +POLL mode is not implemented yet. +.Pp +Operation outside the traditional ISA "hole" is not yet supported, although it +should work if the test is removed from the probe routine. diff --git a/sys/i386/boot/kzipboot/tail.S b/sys/i386/boot/kzipboot/tail.S new file mode 100644 index 000000000000..1a345412fa2f --- /dev/null +++ b/sys/i386/boot/kzipboot/tail.S @@ -0,0 +1,12 @@ +/* + * Boot unpacker startup routine. + * Copyright (C) Serge Vakulenko + */ + .text + .globl start +start: + popl %eax # remove return addr + pushl 4(%esp) # pass howto arg + call _boot # unpack the kernel image + popl %eax # discard howto arg + ljmp $CSEG, $KADDR # jump to unpacked kernel diff --git a/sys/i386/isa/atapi.c b/sys/i386/isa/atapi.c new file mode 100644 index 000000000000..540c2bd2d26b --- /dev/null +++ b/sys/i386/isa/atapi.c @@ -0,0 +1,856 @@ +/* + * Device-independent level for ATAPI drivers. + * + * Copyright (C) 1995 Cronyx Ltd. + * Author Serge Vakulenko, <vak@cronyx.ru> + * + * This software is distributed with NO WARRANTIES, not even the implied + * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Authors grant any other persons or organisations permission to use + * or modify this software as long as this message is kept with the software, + * all derivative works or modified versions. + * + * Version 1.5, Thu Sep 21 23:08:11 MSD 1995 + */ + +/* + * The ATAPI level is implemented as a machine-dependent layer + * between the device driver and the IDE controller. + * All the machine- and controller dependency is isolated inside + * the ATAPI level, while all the device dependency is located + * in the device subdriver. + * + * It seems that an ATAPI bus will became popular for medium-speed + * storage devices such as CD-ROMs, magneto-optical disks, tape streamers etc. + * + * To ease the development of new ATAPI drivers, the subdriver + * interface was designed to be as simple as possible. + * + * Three routines are available for the subdriver to access the device: + * + * struct atapires atapi_request_wait (ata, unit, cmd, a1, a2, a3, a4, a5, + * a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, addr, count); + * struct atapi *ata; -- atapi controller descriptor + * int unit; -- device unit number on the IDE bus + * u_char cmd; -- ATAPI command code + * u_char a1..a15; -- ATAPI command arguments + * char *addr; -- address of the data buffer for i/o + * int count; -- data length, >0 for read ops, <0 for write ops + * + * The atapi_request_wait() function puts the op in the queue of ATAPI + * commands for the IDE controller, starts the controller, the waits for + * operation to be completed (using tsleep). + * The function should be called from the user phase only (open(), close(), + * ioctl() etc). + * Ata and unit args are the values which the subdriver gets from the ATAPI + * level via attach() call. + * Buffer pointed to by *addr should be placed in core memory, static + * or dynamic, but not in stack. + * The function returns the error code structure, which consists of: + * - atapi driver code value + * - controller status port value + * - controller error port value + * + * struct atapires atapi_request_immediate (ata, unit, cmd, a1, a2, a3, + * a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, + * addr, count); + * + * The atapi_request_immediate() function is similar to atapi_request_wait(), + * but it does not use interrupts for performing the request. + * It should be used during an attach phase to get parameters from the device. + * + * void atapi_request_callback (ata, unit, cmd, a1, a2, a3, a4, a5, + * a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, + * addr, count, done, x, y); + * struct atapi *ata; -- atapi controller descriptor + * int unit; -- device unit number on the IDE bus + * u_char cmd; -- ATAPI command code + * u_char a1..a15; -- ATAPI command arguments + * char *addr; -- address of the data buffer for i/o + * int count; -- data length, >0 for read ops, <0 for write ops + * void (*done)(); -- function to call when op finished + * void *x, *y; -- arguments for done() function + * + * The atapi_request_callback() function puts the op in the queue of ATAPI + * commands for the IDE controller, starts the controller, then returns. + * When the operation finishes, then the callback function done() + * will be called on the interrupt level. + * The function is designed to be callable from the interrupt phase. + * The done() functions is called with the following arguments: + * (void) (*done) (x, y, count, errcode) + * void *x, *y; -- arguments from the atapi_request_callback() + * int count; -- the data residual count + * struct atapires errcode; -- error code structure, see above + * + * The new driver could be added in three steps: + * 1. Add entries for the new driver to bdevsw and cdevsw tables in conf.c. + * You will need to make at least three routines: open(), close(), + * strategy() and possibly ioctl(). + * 2. Make attach() routine, which should allocate all the needed data + * structures and print the device description string (see wcdattach()). + * 3. Add an appropriate case to the switch in atapi_attach() routine, + * call attach() routine of the new driver here. Add the appropriate + * #include line at the top of attach.c. + * That's all! + * + * Use #define DEBUG in atapi.c to enable tracing of all i/o operations + * on the IDE bus. + */ +#undef DEBUG + +#include "wdc.h" +#include "wcd.h" +/* #include "wmt.h" -- add your driver here */ +/* #include "wmd.h" -- add your driver here */ + +#if NWDC > 0 && defined (ATAPI) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <i386/include/cpufunc.h> +#include <i386/include/clock.h> +#include <i386/isa/atapi.h> + +#ifdef DEBUG +# define print(s) printf s +#else +# define print(s) {/*void*/} +#endif + +#define MAXCMD (8*NWDC) + +/* + * ATAPI packet command phase. + */ +#define PHASE_CMDOUT (ARS_DRQ | ARI_CMD) +#define PHASE_DATAIN (ARS_DRQ | ARI_IN) +#define PHASE_DATAOUT ARS_DRQ +#define PHASE_COMPLETED (ARI_IN | ARI_CMD) +#define PHASE_ABORTED 0 /* nonstandard - for NEC 260 */ + +struct atapicmd { /* ATAPI command block */ + struct atapicmd *next; /* next command in queue */ + int busy; /* busy flag */ + u_char cmd[16]; /* command and args */ + int unit; /* drive unit number */ + int count; /* byte count, >0 - read, <0 - write */ + char *addr; /* data to transfer */ + void (*callback) (); /* call when done */ + void *cbarg1; /* callback arg 1 */ + void *cbarg2; /* callback arg 1 */ + struct atapires result; /* resulting error code */ +}; + +struct atapi { /* ATAPI controller data */ + u_short port; /* i/o port base */ + u_char ctrlr; /* physical controller number */ + u_char debug : 1; /* trace enable flag */ + u_char cmd16 : 1; /* 16-byte command flag */ + u_char intrcmd : 1; /* interrupt before cmd flag */ + u_char slow : 1; /* slow reaction device */ + struct atapicmd *queue; /* queue of commands to perform */ + struct atapicmd *tail; /* tail of queue */ + struct atapicmd *free; /* queue of free command blocks */ + struct atapicmd cmdrq[MAXCMD]; /* pool of command requests */ +}; + +struct atapi atapitab[NWDC]; + +static struct atapi_params *atapi_probe (int port, int unit); +static int atapi_wait (int port, u_char bits_wanted); +static void atapi_send_cmd (struct atapi *ata, struct atapicmd *ac); +static int atapi_io (struct atapi *ata, struct atapicmd *ac); +static int atapi_start_cmd (struct atapi *ata, struct atapicmd *ac); +static int atapi_wait_cmd (struct atapi *ata, struct atapicmd *ac); + +extern int wdstart (int ctrlr); + +void atapi_attach (int ctlr, int unit, int port, struct kern_devconf *parent) +{ + struct atapi *ata = atapitab + ctlr; + struct atapi_params *ap; + char buf [sizeof(ap->model) + 1]; + char revbuf [sizeof(ap->revision) + 1]; + struct atapicmd *ac; + + print (("atapi%d.%d at 0x%x: attach called\n", ctlr, unit, port)); + ap = atapi_probe (port, unit); + if (! ap) + return; + + bcopy (ap->model, buf, sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; + + bcopy (ap->revision, revbuf, sizeof(revbuf)-1); + revbuf[sizeof(revbuf)-1] = 0; + + printf ("wdc%d: unit %d (atapi): <%s/%s>", ctlr, unit, buf, revbuf); + + /* device is removable */ + if (ap->removable) + printf (", removable"); + + /* packet command size */ + switch (ap->cmdsz) { + case AT_PSIZE_12: break; + case AT_PSIZE_16: printf (", cmd16"); ata->cmd16 = 1; break; + default: printf (", cmd%d", ap->cmdsz); + } + + /* DRQ type */ + switch (ap->drqtype) { + case AT_DRQT_MPROC: ata->slow = 1; break; + case AT_DRQT_INTR: printf (", intr"); ata->intrcmd = 1; break; + case AT_DRQT_ACCEL: printf (", accel"); break; + default: printf (", drq%d", ap->drqtype); + } + + /* overlap operation supported */ + if (ap->ovlapflag) + printf (", ovlap"); + + /* interleaved DMA supported */ + if (ap->idmaflag) + printf (", idma"); + /* DMA supported */ + else if (ap->dmaflag) + printf (", dma"); + + /* IORDY can be disabled */ + if (ap->iordydis) + printf (", iordis"); + /* IORDY supported */ + else if (ap->iordyflag) + printf (", iordy"); + + printf ("\n"); + + ata->port = port; + ata->ctrlr = ctlr; +#ifdef DEBUG + ata->debug = 1; +#else + ata->debug = 0; +#endif + /* Initialize free queue. */ + ata->cmdrq[MAXCMD-1].next = 0; + for (ac = ata->cmdrq+MAXCMD-2; ac >= ata->cmdrq; --ac) + ac->next = ac+1; + ata->free = ata->cmdrq; + + if (ap->proto != AT_PROTO_ATAPI) { + printf ("wdc%d: unit %d: unknown ATAPI protocol=%d\n", + ctlr, unit, ap->proto); + free (ap, M_TEMP); + return; + } + switch (ap->devtype) { + default: + /* unknown ATAPI device */ + printf ("wdc%d: unit %d: unknown ATAPI type=%d\n", + ctlr, unit, ap->devtype); + break; + + case AT_TYPE_DIRECT: /* direct-access */ + case AT_TYPE_CDROM: /* CD-ROM device */ +#if NWCD > 0 + /* ATAPI CD-ROM */ + { + int wcdattach (struct atapi*, int, struct atapi_params*, + int, struct kern_devconf*); + if (wcdattach (ata, unit, ap, ata->debug, parent) < 0) + break; + } + /* Device attached successfully. */ + return; +#else + printf ("wdc%d: ATAPI CD-ROMs not configured\n", ctlr); + break; +#endif + + case AT_TYPE_TAPE: /* streaming tape (QIC-121 model) */ +#if NWMT > 0 + /* Add your driver here */ +#else + printf ("wdc%d: ATAPI streaming tapes not supported yet\n", ctlr); + break; +#endif + + case AT_TYPE_OPTICAL: /* optical disk */ +#if NWMD > 0 + /* Add your driver here */ +#else + printf ("wdc%d: ATAPI optical disks not supported yet\n", ctlr); + break; +#endif + } + /* Attach failed. */ + free (ap, M_TEMP); +} + +static void bswap (char *buf, int len) +{ + u_short *p = (u_short*) (buf + len); + while (--p >= (u_short*) buf) + *p = ntohs (*p); +} + +static void btrim (char *buf, int len) +{ + char *p; + + /* Remove the trailing spaces. */ + for (p=buf; p<buf+len; ++p) + if (! *p) + *p = ' '; + for (p=buf+len-1; p>=buf && *p==' '; --p) + *p = 0; +} + +/* + * Issue IDENTIFY command to ATAPI drive to ask it what it is. + */ +static struct atapi_params *atapi_probe (int port, int unit) +{ + struct atapi_params *ap; + char tb [DEV_BSIZE]; + + /* Wait for controller not busy. */ + if (atapi_wait (port, 0) < 0) { + print (("atapiX.%d at 0x%x: controller busy, status=%b\n", + unit, port, inb (port + AR_STATUS), ARS_BITS)); + return (0); + } + + /* Issue ATAPI IDENTIFY command. */ + outb (port + AR_DRIVE, unit ? ARD_DRIVE1 : ARD_DRIVE0); + outb (port + AR_COMMAND, ATAPIC_IDENTIFY); + + /* Check that device is present. */ + if (inb (port + AR_STATUS) == 0xff) { + print (("atapiX.%d at 0x%x: no device\n", unit, port)); + if (unit == 1) + /* Select unit 0. */ + outb (port + AR_DRIVE, ARD_DRIVE0); + return (0); + } + + /* Wait for data ready. */ + if (atapi_wait (port, ARS_DRQ) != 0) { + print (("atapiX.%d at 0x%x: identify not ready, status=%b\n", + unit, port, inb (port + AR_STATUS), ARS_BITS)); + if (unit == 1) + /* Select unit 0. */ + outb (port + AR_DRIVE, ARD_DRIVE0); + return (0); + } + + /* Obtain parameters. */ + insw (port + AR_DATA, tb, sizeof(tb) / sizeof(short)); + + ap = malloc (sizeof *ap, M_TEMP, M_NOWAIT); + if (! ap) + return (0); + bcopy (tb, ap, sizeof *ap); + + /* + * Shuffle string byte order. + * Mitsumi and NEC drives don't need this. + */ + if (! ((ap->model[0] == 'N' && ap->model[1] == 'E') || + (ap->model[0] == 'F' && ap->model[1] == 'X'))) { + bswap (ap->model, sizeof(ap->model)); + bswap (ap->serial, sizeof(ap->serial)); + bswap (ap->revision, sizeof(ap->revision)); + } + + /* Clean up the model name, serial and revision numbers. */ + btrim (ap->model, sizeof(ap->model)); + btrim (ap->serial, sizeof(ap->serial)); + btrim (ap->revision, sizeof(ap->revision)); + return (ap); +} + +/* + * Wait uninterruptibly until controller is not busy and certain + * status bits are set. + * The wait is usually short unless it is for the controller to process + * an entire critical command. + * Return 1 for (possibly stale) controller errors, -1 for timeout errors, + * or 0 for no errors. + */ +static int atapi_wait (int port, u_char bits_wanted) +{ + int cnt; + u_char s; + + /* Wait 5 sec for BUSY deassert. */ + for (cnt=500000; cnt>0; --cnt) { + s = inb (port + AR_STATUS); + if (! (s & ARS_BSY)) + break; + DELAY (10); + } + if (cnt <= 0) + return (-1); + if (! bits_wanted) + return (s & ARS_CHECK); + + /* Wait 50 msec for bits wanted. */ + for (cnt=5000; cnt>0; --cnt) { + s = inb (port + AR_STATUS); + if ((s & bits_wanted) == bits_wanted) + return (s & ARS_CHECK); + DELAY (10); + } + return (-1); +} + +void atapi_debug (struct atapi *ata, int on) +{ + ata->debug = on; +} + +static struct atapicmd *atapi_alloc (struct atapi *ata) +{ + struct atapicmd *ac; + + while (! ata->free) + tsleep ((caddr_t)ata, PRIBIO, "atacmd", 0); + ac = ata->free; + ata->free = ac->next; + ac->busy = 1; + return (ac); +} + +static void atapi_free (struct atapi *ata, struct atapicmd *ac) +{ + if (! ata->free) + wakeup ((caddr_t)&ata); + ac->busy = 0; + ac->next = ata->free; + ata->free = ac; +} + +/* + * Add new command request to the end of the queue. + */ +static void atapi_enqueue (struct atapi *ata, struct atapicmd *ac) +{ + ac->next = 0; + if (ata->tail) + ata->tail->next = ac; + else + ata->queue = ac; + ata->tail = ac; +} + +static void atapi_done (struct atapi *ata) +{ + struct atapicmd *ac = ata->queue; + + if (! ac) + return; /* cannot happen */ + + ata->queue = ac->next; + if (! ata->queue) + ata->tail = 0; + + if (ac->callback) { + (*ac->callback) (ac->cbarg1, ac->cbarg2, ac->count, ac->result); + atapi_free (ata, ac); + } else + wakeup ((caddr_t)ac); +} + +/* + * Start new packet op. Called from wdstart(). + * Return 1 if op started, and we are waiting for interrupt. + * Return 0 when idle. + */ +int atapi_start (int ctrlr) +{ + struct atapi *ata = atapitab + ctrlr; + struct atapicmd *ac; +again: + ac = ata->queue; + if (! ac) + return (0); + + /* Start packet command. */ + if (atapi_start_cmd (ata, ac) < 0) { + atapi_done (ata); + goto again; + } + + if (ata->intrcmd) + /* Wait for interrupt before sending packet command */ + return (1); + + /* Wait for DRQ. */ + if (atapi_wait_cmd (ata, ac) < 0) { + atapi_done (ata); + goto again; + } + + /* Send packet command. */ + atapi_send_cmd (ata, ac); + return (1); +} + +/* + * Start new packet op. Returns -1 on errors. + */ +int atapi_start_cmd (struct atapi *ata, struct atapicmd *ac) +{ + ac->result.error = 0; + ac->result.status = 0; + + outb (ata->port + AR_DRIVE, ac->unit ? ARD_DRIVE1 : ARD_DRIVE0); + if (atapi_wait (ata->port, 0) < 0) { + printf ("atapi%d.%d: controller not ready for cmd\n", + ata->ctrlr, ac->unit); + ac->result.code = RES_NOTRDY; + return (-1); + } + + /* Set up the controller registers. */ + outb (ata->port + AR_FEATURES, 0); + outb (ata->port + AR_IREASON, 0); + outb (ata->port + AR_TAG, 0); + outb (ata->port + AR_CNTLO, ac->count & 0xff); + outb (ata->port + AR_CNTHI, ac->count >> 8); + outb (ata->port + AR_COMMAND, ATAPIC_PACKET); + + if (ata->debug) + printf ("atapi%d.%d: start\n", ata->ctrlr, ac->unit); + return (0); +} + +/* + * Wait for DRQ before sending packet cmd. Returns -1 on errors. + */ +int atapi_wait_cmd (struct atapi *ata, struct atapicmd *ac) +{ + /* Wait for DRQ from 50 usec to 3 msec for slow devices */ + int cnt = ata->intrcmd ? 10000 : ata->slow ? 3000 : 50; + + for (; cnt>0; cnt-=10) { + ac->result.status = inb (ata->port + AR_STATUS); + if (ac->result.status & ARS_DRQ) + break; + DELAY (10); + } + if (! (ac->result.status & ARS_DRQ)) { + printf ("atapi%d.%d: no cmd drq\n", ata->ctrlr, ac->unit); + ac->result.code = RES_NODRQ; + ac->result.error = inb (ata->port + AR_ERROR); + return (-1); + } + return (0); +} + +/* + * Send packet cmd. + */ +void atapi_send_cmd (struct atapi *ata, struct atapicmd *ac) +{ + outsw (ata->port + AR_DATA, ac->cmd, ata->cmd16 ? 8 : 6); + if (ata->debug) + printf ("atapi%d.%d: send cmd %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x\n", + ata->ctrlr, ac->unit, ac->cmd[0], ac->cmd[1], + ac->cmd[2], ac->cmd[3], ac->cmd[4], ac->cmd[5], + ac->cmd[6], ac->cmd[7], ac->cmd[8], ac->cmd[9], + ac->cmd[10], ac->cmd[11], ac->cmd[12], + ac->cmd[13], ac->cmd[14], ac->cmd[15]); +} + +/* + * Interrupt routine for the controller. Called from wdintr(). + * Finish the started op, wakeup wait-type commands, + * run callbacks for callback-type commands, then return. + * Do not start new op here, it will be done by wdstart, + * which is called just after us. + * Return 1 if op continues, and we are waiting for new interrupt. + * Return 0 when idle. + */ +int atapi_intr (int ctrlr) +{ + struct atapi *ata = atapitab + ctrlr; + struct atapicmd *ac = ata->queue; + + if (! ac) { + printf ("atapi%d: stray interrupt\n", ata->ctrlr); + return (0); + } + if (atapi_io (ata, ac) > 0) + return (1); + atapi_done (ata); + return (0); +} + +/* + * Process the i/o phase, transferring the command/data to/from the device. + * Return 1 if op continues, and we are waiting for new interrupt. + * Return 0 when idle. + */ +int atapi_io (struct atapi *ata, struct atapicmd *ac) +{ + u_char ireason; + u_short len, i; + + if (atapi_wait (ata->port, 0) < 0) { + ac->result.status = inb (ata->port + AR_STATUS); + ac->result.error = inb (ata->port + AR_ERROR); + ac->result.code = RES_NOTRDY; + printf ("atapi%d.%d: controller not ready, status=%b, error=%b\n", + ata->ctrlr, ac->unit, ac->result.status, ARS_BITS, + ac->result.error, AER_BITS); + return (0); + } + + ac->result.status = inb (ata->port + AR_STATUS); + ac->result.error = inb (ata->port + AR_ERROR); + len = inb (ata->port + AR_CNTLO); + len |= inb (ata->port + AR_CNTHI) << 8; + ireason = inb (ata->port + AR_IREASON); + + if (ata->debug) { + printf ("atapi%d.%d: intr ireason=0x%x, len=%d, status=%b, error=%b\n", + ata->ctrlr, ac->unit, ireason, len, + ac->result.status, ARS_BITS, + ac->result.error, AER_BITS); + } + switch ((ireason & (ARI_CMD | ARI_IN)) | (ac->result.status & ARS_DRQ)) { + default: + printf ("atapi%d.%d: unknown phase\n", ata->ctrlr, ac->unit); + ac->result.code = RES_ERR; + break; + + case PHASE_CMDOUT: + /* Send packet command. */ + if (! (ac->result.status & ARS_DRQ)) { + printf ("atapi%d.%d: no cmd drq\n", + ata->ctrlr, ac->unit); + ac->result.code = RES_NODRQ; + break; + } + atapi_send_cmd (ata, ac); + return (1); + + case PHASE_DATAOUT: + /* Write data */ + if (ac->count > 0) { + printf ("atapi%d.%d: invalid data direction\n", + ata->ctrlr, ac->unit); + ac->result.code = RES_INVDIR; + break; + } + if (-ac->count < len) { + print (("atapi%d.%d: send data underrun, %d bytes left\n", + ata->ctrlr, ac->unit, -ac->count)); + ac->result.code = RES_UNDERRUN; + outsw (ata->port + AR_DATA, ac->addr, + -ac->count / sizeof(short)); + for (i= -ac->count; i<len; i+=sizeof(short)) + outw (ata->port + AR_DATA, 0); + } else + outsw (ata->port + AR_DATA, ac->addr, + len / sizeof(short)); + ac->addr += len; + ac->count += len; + return (1); + + case PHASE_DATAIN: + /* Read data */ + if (ac->count < 0) { + printf ("atapi%d.%d: invalid data direction\n", + ata->ctrlr, ac->unit); + ac->result.code = RES_INVDIR; + break; + } + if (ac->count < len) { + print (("atapi%d.%d: recv data overrun, %d bytes left\n", + ata->ctrlr, ac->unit, ac->count)); + ac->result.code = RES_OVERRUN; + insw (ata->port + AR_DATA, ac->addr, + ac->count / sizeof(short)); + for (i=ac->count; i<len; i+=sizeof(short)) + inw (ata->port + AR_DATA); + } else + insw (ata->port + AR_DATA, ac->addr, + len / sizeof(short)); + ac->addr += len; + ac->count -= len; + return (1); + + case PHASE_ABORTED: + case PHASE_COMPLETED: + if (ac->result.status & (ARS_CHECK | ARS_DF)) + ac->result.code = RES_ERR; + else if (ac->count < 0) { + print (("atapi%d.%d: send data overrun, %d bytes left\n", + ata->ctrlr, ac->unit, -ac->count)); + ac->result.code = RES_OVERRUN; + } else if (ac->count > 0) { + print (("atapi%d.%d: recv data underrun, %d bytes left\n", + ata->ctrlr, ac->unit, ac->count)); + ac->result.code = RES_UNDERRUN; + bzero (ac->addr, ac->count); + } else + ac->result.code = RES_OK; + break; + } + return (0); +} + +/* + * Queue new packet request, then call wdstart(). + * Called on splbio(). + */ +void atapi_request_callback (struct atapi *ata, int unit, + u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, + u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, + u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, + char *addr, int count, void (*done)(), void *x, void *y) +{ + struct atapicmd *ac; + + ac = atapi_alloc (ata); + ac->cmd[0] = cmd; ac->cmd[1] = a1; + ac->cmd[2] = a2; ac->cmd[3] = a3; + ac->cmd[4] = a4; ac->cmd[5] = a5; + ac->cmd[6] = a6; ac->cmd[7] = a7; + ac->cmd[8] = a8; ac->cmd[9] = a9; + ac->cmd[10] = a10; ac->cmd[11] = a11; + ac->cmd[12] = a12; ac->cmd[13] = a13; + ac->cmd[14] = a14; ac->cmd[15] = a15; + ac->unit = unit; + ac->addr = addr; + ac->count = count; + ac->callback = done; + ac->cbarg1 = x; + ac->cbarg2 = y; + + if (ata->debug) + printf ("atapi%d.%d: req cb %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x len=%d\n", + ata->ctrlr, ac->unit, ac->cmd[0], ac->cmd[1], + ac->cmd[2], ac->cmd[3], ac->cmd[4], ac->cmd[5], + ac->cmd[6], ac->cmd[7], ac->cmd[8], ac->cmd[9], + ac->cmd[10], ac->cmd[11], ac->cmd[12], + ac->cmd[13], ac->cmd[14], ac->cmd[15], count); + atapi_enqueue (ata, ac); + wdstart (ata->ctrlr); +} + +/* + * Queue new packet request, then call wdstart(). + * Wait until the request is finished. + * Called on spl0(). + * Return atapi error. + * Buffer pointed to by *addr should be placed in core memory, not in stack! + */ +struct atapires atapi_request_wait (struct atapi *ata, int unit, + u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, + u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, + u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, + char *addr, int count) +{ + struct atapicmd *ac; + int x = splbio (); + struct atapires result; + + ac = atapi_alloc (ata); + ac->cmd[0] = cmd; ac->cmd[1] = a1; + ac->cmd[2] = a2; ac->cmd[3] = a3; + ac->cmd[4] = a4; ac->cmd[5] = a5; + ac->cmd[6] = a6; ac->cmd[7] = a7; + ac->cmd[8] = a8; ac->cmd[9] = a9; + ac->cmd[10] = a10; ac->cmd[11] = a11; + ac->cmd[12] = a12; ac->cmd[13] = a13; + ac->cmd[14] = a14; ac->cmd[15] = a15; + ac->unit = unit; + ac->addr = addr; + ac->count = count; + ac->callback = 0; + ac->cbarg1 = 0; + ac->cbarg2 = 0; + + if (ata->debug) + printf ("atapi%d.%d: req w %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x len=%d\n", + ata->ctrlr, ac->unit, ac->cmd[0], ac->cmd[1], + ac->cmd[2], ac->cmd[3], ac->cmd[4], ac->cmd[5], + ac->cmd[6], ac->cmd[7], ac->cmd[8], ac->cmd[9], + ac->cmd[10], ac->cmd[11], ac->cmd[12], + ac->cmd[13], ac->cmd[14], ac->cmd[15], count); + atapi_enqueue (ata, ac); + wdstart (ata->ctrlr); + tsleep ((caddr_t)ac, PRIBIO, "atareq", 0); + + result = ac->result; + atapi_free (ata, ac); + splx (x); + return (result); +} + +/* + * Perform a packet command on the device. + * Should be called on splbio(). + * Return atapi error. + */ +struct atapires atapi_request_immediate (struct atapi *ata, int unit, + u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, + u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, + u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, + char *addr, int count) +{ + struct atapicmd cmdbuf, *ac = &cmdbuf; + int cnt; + + ac->cmd[0] = cmd; ac->cmd[1] = a1; + ac->cmd[2] = a2; ac->cmd[3] = a3; + ac->cmd[4] = a4; ac->cmd[5] = a5; + ac->cmd[6] = a6; ac->cmd[7] = a7; + ac->cmd[8] = a8; ac->cmd[9] = a9; + ac->cmd[10] = a10; ac->cmd[11] = a11; + ac->cmd[12] = a12; ac->cmd[13] = a13; + ac->cmd[14] = a14; ac->cmd[15] = a15; + ac->unit = unit; + ac->addr = addr; + ac->count = count; + ac->callback = 0; + ac->cbarg1 = 0; + ac->cbarg2 = 0; + + if (ata->debug) + printf ("atapi%d.%d: req im %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x len=%d\n", + ata->ctrlr, ac->unit, ac->cmd[0], ac->cmd[1], + ac->cmd[2], ac->cmd[3], ac->cmd[4], ac->cmd[5], + ac->cmd[6], ac->cmd[7], ac->cmd[8], ac->cmd[9], + ac->cmd[10], ac->cmd[11], ac->cmd[12], + ac->cmd[13], ac->cmd[14], ac->cmd[15], count); + + /* Start packet command, wait for DRQ. */ + if (atapi_start_cmd (ata, ac) >= 0 && atapi_wait_cmd (ata, ac) >= 0) { + /* Send packet command. */ + atapi_send_cmd (ata, ac); + + /* Wait for data i/o phase. */ + for (cnt=20000; cnt>0; --cnt) + if (((inb (ata->port + AR_IREASON) & (ARI_CMD | ARI_IN)) | + (inb (ata->port + AR_STATUS) & ARS_DRQ)) != PHASE_CMDOUT) + break; + + /* Do all needed i/o. */ + while (atapi_io (ata, ac)) + /* Wait for DRQ deassert. */ + for (cnt=2000; cnt>0; --cnt) + if (! (inb (ata->port + AR_STATUS) & ARS_DRQ)) + break; + } + return (ac->result); +} +#endif /* NWDC && ATAPI */ diff --git a/sys/i386/isa/atapi.h b/sys/i386/isa/atapi.h new file mode 100644 index 000000000000..cb46dccea0aa --- /dev/null +++ b/sys/i386/isa/atapi.h @@ -0,0 +1,215 @@ +/* + * Device-independent level for ATAPI drivers. + * + * Copyright (C) 1995 Cronyx Ltd. + * Author Serge Vakulenko, <vak@cronyx.ru> + * + * This software is distributed with NO WARRANTIES, not even the implied + * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Authors grant any other persons or organisations permission to use + * or modify this software as long as this message is kept with the software, + * all derivative works or modified versions. + * + * Version 1.8, Thu Sep 28 20:24:38 MSK 1995 + */ + +/* + * Disk Controller ATAPI register definitions. + */ +#define AR_DATA 0x0 /* RW - data register (16 bits) */ +#define AR_ERROR 0x1 /* R - error register */ +#define AR_FEATURES 0x1 /* W - features */ +#define AR_IREASON 0x2 /* RW - interrupt reason */ +#define AR_TAG 0x3 /* - reserved for SAM TAG byte */ +#define AR_CNTLO 0x4 /* RW - byte count, low byte */ +#define AR_CNTHI 0x5 /* RW - byte count, high byte */ +#define AR_DRIVE 0x6 /* RW - drive select */ +#define AR_COMMAND 0x7 /* W - command register */ +#define AR_STATUS 0x7 /* R - immediate status */ + +/* + * Status register bits + */ +#define ARS_CHECK 0x01 /* error occured, see sense key/code */ + /* bit 0x02 reserved */ +#define ARS_CORR 0x04 /* correctable error occured */ +#define ARS_DRQ 0x08 /* data request / ireason valid */ +#define ARS_DSC 0x10 /* immediate operation completed */ +#define ARS_DF 0x20 /* drive fault */ +#define ARS_DRDY 0x40 /* ready to get command */ +#define ARS_BSY 0x80 /* registers busy */ + /* for overlap mode only: */ +#define ARS_SERVICE 0x10 /* service is requested */ +#define ARS_DMARDY 0x20 /* ready to start a DMA transfer */ +#define ARS_BITS "\20\010busy\7ready\6fault\5opdone\4drq\3corr\1check" + +/* + * Error register bits + */ +#define AER_ILI 0x01 /* illegal length indication */ +#define AER_EOM 0x02 /* end of media detected */ +#define AER_ABRT 0x04 /* command aborted */ +#define AER_MCR 0x08 /* media change requested */ +#define AER_SKEY 0xf0 /* sense key mask */ +#define AER_SK_NO_SENSE 0x00 /* no spesific sense key info */ +#define AER_SK_RECOVERED_ERROR 0x10 /* command succeeded, data recovered */ +#define AER_SK_NOT_READY 0x20 /* no access to drive */ +#define AER_SK_MEDIUM_ERROR 0x30 /* non-recovered data error */ +#define AER_SK_HARDWARE_ERROR 0x40 /* non-recoverable hardware failure */ +#define AER_SK_ILLEGAL_REQUEST 0x50 /* invalid command parameter(s) */ +#define AER_SK_UNIT_ATTENTION 0x60 /* media changed */ +#define AER_SK_DATA_PROTECT 0x70 /* reading read-protected sector */ +#define AER_SK_ABORTED_COMMAND 0xb0 /* command aborted, try again */ +#define AER_SK_MISCOMPARE 0xe0 /* data did not match the medium */ +#define AER_BITS "\20\4mchg\3abort\2eom\1ili" + +/* + * Feature register bits + */ +#define ARF_DMA 0x01 /* transfer data via DMA */ +#define ARF_OVERLAP 0x02 /* release the bus until completion */ + +/* + * Interrupt reason register bits + */ +#define ARI_CMD 0x01 /* command(1) or data(0) */ +#define ARI_IN 0x02 /* transfer to(1) or from(0) the host */ +#define ARI_RELEASE 0x04 /* bus released until completion */ + +/* + * Drive register values + */ +#define ARD_DRIVE0 0xa0 /* drive 0 selected */ +#define ARD_DRIVE1 0xb0 /* drive 1 selected */ + +/* + * ATA commands + */ +#define ATAPIC_IDENTIFY 0xa1 /* get drive parameters */ +#define ATAPIC_PACKET 0xa0 /* execute packet command */ + +/* + * Mandatory packet commands + */ +#define ATAPI_TEST_UNIT_READY 0x00 /* check if the device is ready */ +#define ATAPI_REQUEST_SENSE 0x03 /* get sense data */ +#define ATAPI_START_STOP 0x1b /* start/stop the media */ +#define ATAPI_PREVENT_ALLOW 0x1e /* prevent/allow media removal */ +#define ATAPI_READ_CAPACITY 0x25 /* get volume capacity */ +#define ATAPI_READ_BIG 0x28 /* read data */ +#define ATAPI_READ_TOC 0x43 /* get table of contents */ +#define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */ +#define ATAPI_MODE_SELECT_BIG 0x55 /* set device parameters */ +#define ATAPI_MODE_SENSE 0x5a /* get device parameters */ +#define ATAPI_PLAY_CD 0xb4 /* universal play command */ + +/* + * Optional packet commands + */ +#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */ +#define ATAPI_PAUSE 0x4b /* stop/start audio operation */ + +/* + * Nonstandard packet commands + */ +#define ATAPI_PLAY_TRACK 0x48 /* play by track number */ +#define ATAPI_PLAY_BIG 0xa5 /* play by logical block address */ + +/* + * Drive parameter information + */ +struct atapi_params { + unsigned cmdsz : 2; /* packet command size */ +#define AT_PSIZE_12 0 /* 12 bytes */ +#define AT_PSIZE_16 1 /* 16 bytes */ + unsigned : 3; + unsigned drqtype : 2; /* DRQ type */ +#define AT_DRQT_MPROC 0 /* microprocessor DRQ - 3 msec delay */ +#define AT_DRQT_INTR 1 /* interrupt DRQ - 10 msec delay */ +#define AT_DRQT_ACCEL 2 /* accelerated DRQ - 50 usec delay */ + unsigned removable : 1; /* device is removable */ + unsigned devtype : 5; /* device type */ +#define AT_TYPE_DIRECT 0 /* direct-access (magnetic disk) */ +#define AT_TYPE_TAPE 1 /* streaming tape (QIC-121 model) */ +#define AT_TYPE_CDROM 5 /* CD-ROM device */ +#define AT_TYPE_OPTICAL 7 /* optical disk */ + unsigned : 1; + unsigned proto : 2; /* command protocol */ +#define AT_PROTO_ATAPI 2 + short reserved1[9]; + char serial[20]; /* serial number - optional */ + short reserved2[3]; + char revision[8]; /* firmware revision */ + char model[40]; /* model name */ + short reserved3[2]; + u_char vendor_cap; /* vendor unique capabilities */ + unsigned dmaflag : 1; /* DMA supported */ + unsigned lbaflag : 1; /* LBA supported - always 1 */ + unsigned iordydis : 1; /* IORDY can be disabled */ + unsigned iordyflag : 1; /* IORDY supported */ + unsigned : 1; + unsigned ovlapflag : 1; /* overlap operation supported */ + unsigned : 1; + unsigned idmaflag : 1; /* interleaved DMA supported */ + short reserved4; + u_short pio_timing; /* PIO cycle timing */ + u_short dma_timing; /* DMA cycle timing */ + u_short flags; +#define AT_FLAG_54_58 1 /* words 54-58 valid */ +#define AT_FLAG_64_70 2 /* words 64-70 valid */ + short reserved5[8]; + u_char swdma_flag; /* singleword DMA mode supported */ + u_char swdma_active; /* singleword DMA mode active */ + u_char mwdma_flag; /* multiword DMA mode supported */ + u_char mwdma_active; /* multiword DMA mode active */ + u_char apio_flag; /* advanced PIO mode supported */ + u_char reserved6; + u_short mwdma_min; /* min. M/W DMA time per word (ns) */ + u_short mwdma_dflt; /* recommended M/W DMA time (ns) - optional */ + u_short pio_nfctl_min; /* min. PIO cycle time w/o flow ctl - optional */ + u_short pio_iordy_min; /* min. PIO c/t with IORDY flow ctl - optional */ + short reserved7[2]; + u_short rls_ovlap; /* release time (us) for overlap cmd - optional */ + u_short rls_service; /* release time (us) for service cmd - optional */ +}; + +/* + * ATAPI operation result structure + */ +struct atapires { + u_char code; /* result code */ +#define RES_OK 0 /* i/o done */ +#define RES_ERR 1 /* i/o finished with error */ +#define RES_NOTRDY 2 /* controller not ready */ +#define RES_NODRQ 3 /* no data request */ +#define RES_INVDIR 4 /* invalid bus phase direction */ +#define RES_OVERRUN 5 /* data overrun */ +#define RES_UNDERRUN 6 /* data underrun */ + u_char status; /* status register contents */ + u_char error; /* error register contents */ +}; + +#ifdef KERNEL +struct atapi; +struct kern_devconf; +void atapi_attach (int ctlr, int unit, int port, struct kern_devconf*); +int atapi_start (int ctrlr); +int atapi_intr (int ctrlr); +void atapi_debug (struct atapi *ata, int on); +struct atapires atapi_request_wait (struct atapi *ata, int unit, + u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, + u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, + u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, + char *addr, int count); +void atapi_request_callback (struct atapi *ata, int unit, + u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, + u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, + u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, + char *addr, int count, void (*done)(), void *x, void *y); +struct atapires atapi_request_immediate (struct atapi *ata, int unit, + u_char cmd, u_char a1, u_char a2, u_char a3, u_char a4, + u_char a5, u_char a6, u_char a7, u_char a8, u_char a9, + u_char a10, u_char a11, u_char a12, u_char a13, u_char a14, u_char a15, + char *addr, int count); +#endif diff --git a/sys/i386/isa/wcd.c b/sys/i386/isa/wcd.c new file mode 100644 index 000000000000..a5a2dffc5a24 --- /dev/null +++ b/sys/i386/isa/wcd.c @@ -0,0 +1,984 @@ +/* + * IDE CD-ROM driver for FreeBSD. + * Supports ATAPI-compatible drives. + * + * Copyright (C) 1995 Cronyx Ltd. + * Author Serge Vakulenko, <vak@cronyx.ru> + * + * This software is distributed with NO WARRANTIES, not even the implied + * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Authors grant any other persons or organisations permission to use + * or modify this software as long as this message is kept with the software, + * all derivative works or modified versions. + * + * Version 1.8, Thu Sep 28 21:04:16 MSK 1995 + */ + +#include "wdc.h" +#include "wcd.h" +#if NWCD > 0 && NWDC > 0 && defined (ATAPI) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/buf.h> +#include <sys/ioctl.h> +#include <sys/devconf.h> +#include <sys/disklabel.h> +#include <sys/cdio.h> +#include <i386/include/cpufunc.h> +#include <i386/isa/atapi.h> + +#define NUNIT (NWDC*2) /* Max. number of devices */ +#define UNIT(d) ((minor(d) >> 3) & 3) /* Unit part of minor device number */ +#define SECSIZE 2048 /* CD-ROM sector size in bytes */ + +#define F_OPEN 0x0001 /* The drive os opened */ +#define F_MEDIA_CHANGED 0x0002 /* The media have changed since open */ +#define F_DEBUG 0x0004 /* The media have changed since open */ +#define F_NOPLAYCD 0x0008 /* The PLAY_CD op not supported */ + +/* + * Disc table of contents. + */ +#define MAXTRK 99 +struct toc { + struct ioc_toc_header hdr; + struct cd_toc_entry tab[MAXTRK+1]; /* One extra for the leadout */ +}; + +/* + * Volume size info. + */ +struct volinfo { + u_long volsize; /* Volume size in blocks */ + u_long blksize; /* Block size in bytes */ +} info; + +/* + * Current subchannel status. + */ +struct subchan { + u_char void0; + u_char audio_status; + u_short data_length; + u_char data_format; + u_char control; + u_char track; + u_char indx; + u_long abslba; + u_long rellba; +}; + +/* + * Audio Control Parameters Page + */ +struct audiopage { + /* Mode data header */ + u_short data_length; + u_char medium_type; + u_char reserved1[5]; + + /* Audio control page */ + u_char page_code; +#define AUDIO_PAGE 0x0e +#define AUDIO_PAGE_MASK 0x4e /* changeable values */ + u_char param_len; + u_char flags; +#define CD_PA_SOTC 0x02 /* mandatory */ +#define CD_PA_IMMED 0x04 /* always 1 */ + u_char reserved3[3]; + u_short lb_per_sec; + struct port_control { + u_char channels : 4; +#define CHANNEL_0 1 /* mandatory */ +#define CHANNEL_1 2 /* mandatory */ +#define CHANNEL_2 4 /* optional */ +#define CHANNEL_3 8 /* optional */ + u_char volume; + } port[4]; +}; + +/* + * CD-ROM Capabilities and Mechanical Status Page + */ +struct cappage { + /* Mode data header */ + u_short data_length; + u_char medium_type; +#define MDT_UNKNOWN 0x00 +#define MDT_DATA_120 0x01 +#define MDT_AUDIO_120 0x02 +#define MDT_COMB_120 0x03 +#define MDT_PHOTO_120 0x04 +#define MDT_DATA_80 0x05 +#define MDT_AUDIO_80 0x06 +#define MDT_COMB_80 0x07 +#define MDT_PHOTO_80 0x08 +#define MDT_NO_DISC 0x70 +#define MDT_DOOR_OPEN 0x71 +#define MDT_FMT_ERROR 0x72 + u_char reserved1[5]; + + /* Capabilities page */ + u_char page_code; +#define CAP_PAGE 0x2a + u_char param_len; + u_char reserved2[2]; + + u_char audio_play : 1; /* audio play supported */ + u_char composite : 1; /* composite audio/video supported */ + u_char dport1 : 1; /* digital audio on port 1 */ + u_char dport2 : 1; /* digital audio on port 2 */ + u_char mode2_form1 : 1; /* mode 2 form 1 (XA) read */ + u_char mode2_form2 : 1; /* mode 2 form 2 format */ + u_char multisession : 1; /* multi-session photo-CD */ + u_char : 1; + u_char cd_da : 1; /* audio-CD read supported */ + u_char cd_da_stream : 1; /* CD-DA streaming */ + u_char rw : 1; /* combined R-W subchannels */ + u_char rw_corr : 1; /* R-W subchannel data corrected */ + u_char c2 : 1; /* C2 error pointers supported */ + u_char isrc : 1; /* can return the ISRC info */ + u_char upc : 1; /* can return the catalog number UPC */ + u_char : 1; + u_char lock : 1; /* could be locked */ + u_char locked : 1; /* current lock state */ + u_char prevent : 1; /* prevent jumper installed */ + u_char eject : 1; /* can eject */ + u_char : 1; + u_char mech : 3; /* loading mechanism type */ +#define MECH_CADDY 0 +#define MECH_TRAY 1 +#define MECH_POPUP 2 +#define MECH_CHANGER 4 +#define MECH_CARTRIDGE 5 + u_char sep_vol : 1; /* independent volume of channels */ + u_char sep_mute : 1; /* independent mute of channels */ + u_char : 6; + + u_short max_speed; /* max raw data rate in bytes/1000 */ + u_short max_vol_levels; /* number of discrete volume levels */ + u_short buf_size; /* internal buffer size in bytes/1024 */ + u_short cur_speed; /* current data rate in bytes/1000 */ + + /* Digital drive output format description (optional?) */ + u_char reserved3; + u_char bckf : 1; /* data valid on failing edge of BCK */ + u_char rch : 1; /* high LRCK indicates left channel */ + u_char lsbf : 1; /* set if LSB first */ + u_char dlen: 2; +#define DLEN_32 0 /* 32 BCKs */ +#define DLEN_16 1 /* 16 BCKs */ +#define DLEN_24 2 /* 24 BCKs */ +#define DLEN_24_I2S 3 /* 24 BCKs (I2S) */ + u_char : 3; + u_char reserved4[2]; +}; + +struct wcd { + struct atapi *ata; /* Controller structure */ + int unit; /* IDE bus drive unit */ + int lun; /* Logical device unit */ + int flags; /* Device state flags */ + struct buf queue; /* Queue of i/o requests */ + struct atapi_params *param; /* Drive parameters table */ + struct toc toc; /* Table of disc contents */ + struct volinfo info; /* Volume size info */ + struct audiopage au; /* Audio page info */ + struct cappage cap; /* Capabilities page info */ + struct audiopage aumask; /* Audio page mask */ + struct subchan subchan; /* Subchannel info */ + struct kern_devconf cf; /* Driver configuration info */ + char description[80]; /* Device description */ +}; + +struct wcd *wcdtab[NUNIT]; /* Drive info by unit number */ +static int wcdnlun = 0; /* Number of configured drives */ + +static void wcd_start (struct wcd *t); +static void wcd_done (struct wcd *t, struct buf *bp, int resid, + struct atapires result); +static void wcd_error (struct wcd *t, struct atapires result); +static int wcd_read_toc (struct wcd *t); +static int wcd_request_wait (struct wcd *t, u_char cmd, u_char a1, u_char a2, + u_char a3, u_char a4, u_char a5, u_char a6, u_char a7, u_char a8, + u_char a9, char *addr, int count); +static int wcd_externalize (struct proc*, struct kern_devconf*, void*, size_t); +static int wcd_goaway (struct kern_devconf *kdc, int force); +static void wcd_describe (struct wcd *t); +static int wcd_setchan (struct wcd *t, + u_char c0, u_char c1, u_char c2, u_char c3); + +static struct kern_devconf cftemplate = { + 0, 0, 0, "wcd", 0, { MDDT_DISK, 0 }, + wcd_externalize, 0, wcd_goaway, DISK_EXTERNALLEN, + 0, 0, DC_IDLE, "ATAPI compact disc", +}; + +/* + * Dump the array in hexadecimal format for debugging purposes. + */ +static void wcd_dump (int lun, char *label, void *data, int len) +{ + u_char *p = data; + + printf ("wcd%d: %s %x", lun, label, *p++); + while (--len > 0) + printf ("-%x", *p++); + printf ("\n"); +} + +static int wcd_externalize (struct proc *p, struct kern_devconf *kdc, + void *userp, size_t len) +{ + return disk_externalize (wcdtab[kdc->kdc_unit]->unit, userp, &len); +} + +static int wcd_goaway (struct kern_devconf *kdc, int force) +{ + dev_detach (kdc); + return 0; +} + +void wcdattach (struct atapi *ata, int unit, struct atapi_params *ap, int debug, + struct kern_devconf *parent) +{ + struct wcd *t; + struct atapires result; + + if (wcdnlun >= NUNIT) { + printf ("wcd: too many units\n"); + return; + } + t = malloc (sizeof (struct wcd), M_TEMP, M_NOWAIT); + if (! t) { + printf ("wcd: out of memory\n"); + return; + } + wcdtab[wcdnlun] = t; + bzero (t, sizeof (struct wcd)); + t->ata = ata; + t->unit = unit; + t->lun = wcdnlun++; + t->param = ap; + t->flags = F_MEDIA_CHANGED; + if (debug) { + t->flags |= F_DEBUG; + /* Print params. */ + wcd_dump (t->lun, "info", ap, sizeof *ap); + } + + /* Get drive capabilities. */ + result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE, + 0, CAP_PAGE, 0, 0, 0, 0, sizeof (t->cap) >> 8, sizeof (t->cap), + 0, 0, 0, 0, 0, 0, 0, (char*) &t->cap, sizeof (t->cap)); + + /* Do it twice to avoid the stale media changed state. */ + if (result.code == RES_ERR && + (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION) + result = atapi_request_immediate (ata, unit, ATAPI_MODE_SENSE, + 0, CAP_PAGE, 0, 0, 0, 0, sizeof (t->cap) >> 8, + sizeof (t->cap), 0, 0, 0, 0, 0, 0, 0, + (char*) &t->cap, sizeof (t->cap)); + + /* Some drives have shorter capabilities page. */ + if (result.code == RES_UNDERRUN) + result.code = 0; + + if (result.code == 0) { + wcd_describe (t); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "cap", &t->cap, sizeof t->cap); + } + + /* Register driver */ + t->cf = cftemplate; + t->cf.kdc_unit = t->lun; + t->cf.kdc_parent = parent; + t->cf.kdc_description = t->description; + strcpy (t->description, cftemplate.kdc_description); + strcat (t->description, ": "); + strncpy (t->description + strlen(t->description), + ap->model, sizeof(ap->model)); + dev_attach (&t->cf); +} + +void wcd_describe (struct wcd *t) +{ + char *m; + + t->cap.max_speed = ntohs (t->cap.max_speed); + t->cap.max_vol_levels = ntohs (t->cap.max_vol_levels); + t->cap.buf_size = ntohs (t->cap.buf_size); + t->cap.cur_speed = ntohs (t->cap.cur_speed); + + printf ("wcd%d: ", t->lun); + if (t->cap.cur_speed != t->cap.max_speed) + printf ("%d/", t->cap.cur_speed * 1000 / 1024); + printf ("%dKb/sec", t->cap.max_speed * 1000 / 1024); + if (t->cap.buf_size) + printf (", %dKb cache", t->cap.buf_size); + + if (t->cap.audio_play) + printf (", audio play"); + if (t->cap.max_vol_levels) + printf (", %d volume levels", t->cap.max_vol_levels); + + switch (t->cap.mech) { + default: m = 0; break; + case MECH_CADDY: m = "caddy"; break; + case MECH_TRAY: m = "tray"; break; + case MECH_POPUP: m = "popup"; break; + case MECH_CHANGER: m = "changer"; break; + case MECH_CARTRIDGE: m = "cartridge"; break; + } + if (m) + printf (", %s%s", t->cap.eject ? "ejectable " : "", m); + else if (t->cap.eject) + printf (", eject"); + printf ("\n"); + + printf ("wcd%d: ", t->lun); + switch (t->cap.medium_type) { + case MDT_UNKNOWN: printf ("medium type unknown"); break; + case MDT_DATA_120: printf ("120mm data disc loaded"); break; + case MDT_AUDIO_120: printf ("120mm audio disc loaded"); break; + case MDT_COMB_120: printf ("120mm data/audio disc loaded"); break; + case MDT_PHOTO_120: printf ("120mm photo disc loaded"); break; + case MDT_DATA_80: printf ("80mm data disc loaded"); break; + case MDT_AUDIO_80: printf ("80mm audio disc loaded"); break; + case MDT_COMB_80: printf ("80mm data/audio disc loaded"); break; + case MDT_PHOTO_80: printf ("80mm photo disc loaded"); break; + case MDT_NO_DISC: printf ("no disc inside"); break; + case MDT_DOOR_OPEN: printf ("door open"); break; + case MDT_FMT_ERROR: printf ("medium format error"); break; + default: printf ("medium type=0x%x", t->cap.medium_type); break; + } + if (t->cap.lock) + printf (t->cap.locked ? ", locked" : ", unlocked"); + if (t->cap.prevent) + printf (", lock protected"); + printf ("\n"); +} + +int wcdopen (dev_t dev, int flags, int fmt, struct proc *p) +{ + int lun = UNIT(dev); + struct wcd *t; + struct atapires result; + + /* Check the unit is legal. */ + if (lun >= wcdnlun) + return (ENXIO); + t = wcdtab[lun]; + + /* If already opened, that's all. */ + if (t->flags & F_OPEN) { + /* If it's been invalidated, forbid re-entry. + * (may have changed media) */ + if (t->flags & F_MEDIA_CHANGED) + return (ENXIO); + return (0); + } + + /* On the first open: check for the media. + * Do it twice to avoid the stale media changed state. */ + result = atapi_request_wait (t->ata, t->unit, ATAPI_TEST_UNIT_READY, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + if (result.code == RES_ERR && + (result.error & AER_SKEY) == AER_SK_UNIT_ATTENTION) { + t->flags |= F_MEDIA_CHANGED; + result = atapi_request_wait (t->ata, t->unit, + ATAPI_TEST_UNIT_READY, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + if (result.code) { + wcd_error (t, result); + return (ENXIO); + } + + /* Read table of contents. */ + if (wcd_read_toc (t) != 0) + bzero (&t->toc, sizeof (t->toc)); + + /* Read disc capacity. */ + if (wcd_request_wait (t, ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, + 0, sizeof(t->info), 0, (char*)&t->info, sizeof(t->info)) != 0) + bzero (&t->info, sizeof (t->info)); + t->info.volsize = ntohl (t->info.volsize); + t->info.blksize = ntohl (t->info.blksize); + + /* Print the disc description string on every disc change. + * It would help to track the history of disc changes. */ + if (t->info.volsize && t->toc.hdr.ending_track && + (t->flags & F_MEDIA_CHANGED) && (t->flags & F_DEBUG)) { + printf ("wcd%d: ", t->lun); + if (t->toc.tab[0].control & 4) + printf ("%ldMB ", t->info.volsize / 512); + else + printf ("%ld:%ld audio ", t->info.volsize/75/60, + t->info.volsize/75%60); + printf ("(%ld sectors), %d tracks\n", t->info.volsize, + t->toc.hdr.ending_track - t->toc.hdr.starting_track + 1); + } + /* Lock the media. */ + wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + + t->flags &= ~F_MEDIA_CHANGED; + t->flags |= F_OPEN; + return (0); +} + +/* + * Close the device. Only called if we are the LAST + * occurence of an open device. + */ +int wcdclose (dev_t dev, int flags, int fmt, struct proc *p) +{ + int lun = UNIT(dev); + struct wcd *t = wcdtab[lun]; + + /* If we were the last open of the entire device, release it. */ + wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + t->flags &= ~F_OPEN; + return (0); +} + +/* + * Actually translate the requested transfer into one the physical driver can + * understand. The transfer is described by a buf and will include only one + * physical transfer. + */ +void wcdstrategy (struct buf *bp) +{ + int lun = UNIT(bp->b_dev); + struct wcd *t = wcdtab[lun]; + int x; + + /* If the device has been made invalid, error out + * maybe the media changed. */ + if (t->flags & F_MEDIA_CHANGED) { + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + biodone (bp); + return; + } + + /* Can't ever write to a CD. */ + if (! (bp->b_flags & B_READ)) { + bp->b_error = EROFS; + bp->b_flags |= B_ERROR; + biodone (bp); + return; + } + + /* If it's a null transfer, return immediatly. */ + if (bp->b_bcount == 0) { + bp->b_resid = 0; + biodone (bp); + return; + } + + /* Process transfer request. */ + bp->b_pblkno = bp->b_blkno; + bp->b_resid = bp->b_bcount; + x = splbio(); + + /* Place it in the queue of disk activities for this disk. */ + disksort (&t->queue, bp); + + /* Tell the device to get going on the transfer if it's + * not doing anything, otherwise just wait for completion. */ + wcd_start (t); + splx(x); +} + +/* + * Look to see if there is a buf waiting for the device + * and that the device is not already busy. If both are true, + * It dequeues the buf and creates an ATAPI command to perform the + * transfer in the buf. + * The bufs are queued by the strategy routine (wcdstrategy). + * Must be called at the correct (splbio) level. + */ +static void wcd_start (struct wcd *t) +{ + struct buf *bp = t->queue.b_actf; + u_long blkno, nblk; + + /* See if there is a buf to do and we are not already doing one. */ + if (! bp) + return; + + /* Unqueue the request. */ + t->queue.b_actf = bp->b_actf; + + /* Should reject all queued entries if media have changed. */ + if (t->flags & F_MEDIA_CHANGED) { + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + biodone (bp); + return; + } + + /* We have a buf, now we should make a command + * First, translate the block to absolute and put it in terms of the + * logical blocksize of the device. + * What if something asks for 512 bytes not on a 2k boundary? */ + blkno = bp->b_blkno / (SECSIZE / 512); + nblk = (bp->b_bcount + (SECSIZE - 1)) / SECSIZE; + + atapi_request_callback (t->ata, t->unit, ATAPI_READ_BIG, 0, + blkno>>24, blkno>>16, blkno>>8, blkno, 0, nblk>>8, nblk, 0, 0, + 0, 0, 0, 0, 0, (u_char*) bp->b_un.b_addr, bp->b_bcount, + wcd_done, t, bp); + t->cf.kdc_state = DC_BUSY; +} + +static void wcd_done (struct wcd *t, struct buf *bp, int resid, + struct atapires result) +{ + if (result.code) { + wcd_error (t, result); + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + } else + bp->b_resid = resid; + biodone (bp); + t->cf.kdc_state = DC_IDLE; + wcd_start (t); +} + +static void wcd_error (struct wcd *t, struct atapires result) +{ + if (result.code != RES_ERR) + return; + switch (result.error & AER_SKEY) { + case AER_SK_NOT_READY: + if (result.error & ~AER_SKEY) { + /* Audio disc. */ + printf ("wcd%d: cannot read audio disc\n", t->lun); + return; + } + /* Tray open. */ + if (! (t->flags & F_MEDIA_CHANGED)) + printf ("wcd%d: tray open\n", t->lun); + t->flags |= F_MEDIA_CHANGED; + return; + + case AER_SK_UNIT_ATTENTION: + /* Media changed. */ + if (! (t->flags & F_MEDIA_CHANGED)) + printf ("wcd%d: media changed\n", t->lun); + t->flags |= F_MEDIA_CHANGED; + return; + + case AER_SK_ILLEGAL_REQUEST: + /* Unknown command or invalid command arguments. */ + if (t->flags & F_DEBUG) + printf ("wcd%d: invalid command\n", t->lun); + return; + } + printf ("wcd%d: i/o error, status=%b, error=%b\n", t->lun, + result.status, ARS_BITS, result.error, AER_BITS); +} + +static int wcd_request_wait (struct wcd *t, u_char cmd, u_char a1, u_char a2, + u_char a3, u_char a4, u_char a5, u_char a6, u_char a7, u_char a8, + u_char a9, char *addr, int count) +{ + struct atapires result; + + t->cf.kdc_state = DC_BUSY; + result = atapi_request_wait (t->ata, t->unit, cmd, + a1, a2, a3, a4, a5, a6, a7, a8, a9, 0, 0, 0, 0, 0, 0, + addr, count); + t->cf.kdc_state = DC_IDLE; + if (result.code) { + wcd_error (t, result); + return (EIO); + } + return (0); +} + +static int wcd_play (struct wcd *t, u_char cmd, u_char a1, u_char a2, + u_char a3, u_char a4, u_char a5, u_char a6, u_char a7, u_char a8, + u_char a9, char *addr, int count) +{ + struct atapires result; + + if (! (t->flags & F_NOPLAYCD)) { + t->cf.kdc_state = DC_BUSY; + result = atapi_request_wait (t->ata, t->unit, ATAPI_PLAY_CD, + cmd == ATAPI_PLAY_MSF ? 2 : 0, a2, a3, a4, a5, a6, + a7, a8, a9, 0, 0, 0, 0, 0, 0, addr, count); + t->cf.kdc_state = DC_IDLE; + if (result.code == RES_ERR && + (result.error & AER_SKEY) == AER_SK_ILLEGAL_REQUEST) { + /* Some drives don't support a PLAY_CD command. + * Remember this and use PLAY_MSF instead. */ + t->flags |= F_NOPLAYCD; + result.code = 0; + } + if (result.code) { + wcd_error (t, result); + return (EIO); + } + } + return wcd_request_wait (t, cmd, a1, a2, a3, a4, a5, a6, + a7, a8, a9, addr, count); +} + +static inline void lba2msf (int lba, u_char *m, u_char *s, u_char *f) +{ + lba += 150; /* offset of first logical frame */ + lba &= 0xffffff; /* negative lbas use only 24 bits */ + *m = lba / (60 * 75); + lba %= (60 * 75); + *s = lba / 75; + *f = lba % 75; +} + +/* + * Perform special action on behalf of the user. + * Knows about the internals of this device + */ +int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p) +{ + int lun = UNIT(dev); + struct wcd *t = wcdtab[lun]; + int error = 0; + + /* If the device is not valid.. abandon ship. */ + if (t->flags & F_MEDIA_CHANGED) + return (EIO); + switch (cmd) { + default: + return (ENOTTY); + + case CDIOCSETDEBUG: + if (p->p_cred->pc_ucred->cr_uid) + return (EPERM); + t->flags |= F_DEBUG; + atapi_debug (t->ata, 1); + return 0; + + case CDIOCCLRDEBUG: + if (p->p_cred->pc_ucred->cr_uid) + return (EPERM); + t->flags &= ~F_DEBUG; + atapi_debug (t->ata, 0); + return 0; + + case CDIOCRESUME: + return wcd_request_wait (t, ATAPI_PAUSE, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0); + + case CDIOCPAUSE: + return wcd_request_wait (t, ATAPI_PAUSE, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCSTART: + return wcd_request_wait (t, ATAPI_START_STOP, + 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCSTOP: + return wcd_request_wait (t, ATAPI_START_STOP, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCALLOW: + return wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCPREVENT: + return wcd_request_wait (t, ATAPI_PREVENT_ALLOW, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCRESET: + if (p->p_cred->pc_ucred->cr_uid) + return (EPERM); + return wcd_request_wait (t, ATAPI_TEST_UNIT_READY, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + case CDIOCEJECT: + /* Stop the disc. */ + error = wcd_request_wait (t, ATAPI_START_STOP, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + if (error) + return (error); + /* Give it some time to stop spinning. */ + tsleep ((caddr_t)&lbolt, PRIBIO, "wcdejct", 0); + tsleep ((caddr_t)&lbolt, PRIBIO, "wcdejct", 0); + /* Eject. */ + return wcd_request_wait (t, ATAPI_START_STOP, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0); + + case CDIOREADTOCHEADER: + if (! t->toc.hdr.ending_track) + return (ENODEV); + bcopy (&t->toc.hdr, addr, sizeof t->toc.hdr); + break; + + case CDIOREADTOCENTRYS: { + struct ioc_read_toc_entry *te = + (struct ioc_read_toc_entry*) addr; + struct toc *toc = &t->toc; + struct toc buf; + u_long len; + + if (! t->toc.hdr.ending_track) + return (ENODEV); + if (te->starting_track < toc->hdr.starting_track || + te->starting_track > toc->hdr.ending_track) + return (EINVAL); + + len = (toc->hdr.ending_track - te->starting_track + 2) * + sizeof(toc->tab[0]); + if (te->data_len < len) + len = te->data_len; + if (len <= 0) + return (EINVAL); + + /* Convert to MSF format, if needed. */ + if (te->address_format == CD_MSF_FORMAT) { + struct cd_toc_entry *e; + + buf = t->toc; + toc = &buf; + e = toc->tab + toc->hdr.ending_track - + te->starting_track + 2; + while (--e >= toc->tab) + lba2msf (e->addr.lba, &e->addr.msf.minute, + &e->addr.msf.second, &e->addr.msf.frame); + } + if (copyout (toc->tab + te->starting_track - + toc->hdr.starting_track, te->data, len) != 0) + error = EFAULT; + break; + } + case CDIOCREADSUBCHANNEL: { + struct ioc_read_subchannel *args = + (struct ioc_read_subchannel*) addr; + struct cd_sub_channel_info data; + u_long len = args->data_len; + int abslba, rellba; + + if (len > sizeof(data) || + len < sizeof(struct cd_sub_channel_header)) + return (EINVAL); + + if (wcd_request_wait (t, ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, + 0, 0, sizeof (t->subchan) >> 8, sizeof (t->subchan), + 0, (char*)&t->subchan, sizeof (t->subchan)) != 0) + return (EIO); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "subchan", &t->subchan, sizeof t->subchan); + + abslba = ntohl (t->subchan.abslba); + rellba = ntohl (t->subchan.rellba); + if (args->address_format == CD_MSF_FORMAT) { + lba2msf (abslba, + &data.what.position.absaddr.msf.minute, + &data.what.position.absaddr.msf.second, + &data.what.position.absaddr.msf.frame); + lba2msf (rellba, + &data.what.position.reladdr.msf.minute, + &data.what.position.reladdr.msf.second, + &data.what.position.reladdr.msf.frame); + } else { + data.what.position.absaddr.lba = abslba; + data.what.position.reladdr.lba = rellba; + } + data.header.audio_status = t->subchan.audio_status; + data.what.position.control = t->subchan.control & 0xf; + data.what.position.track_number = t->subchan.track; + data.what.position.index_number = t->subchan.indx; + + if (copyout (&data, args->data, len) != 0) + error = EFAULT; + break; + } + case CDIOCPLAYMSF: { + struct ioc_play_msf *args = (struct ioc_play_msf*) addr; + + return wcd_play (t, ATAPI_PLAY_MSF, 0, 0, + args->start_m, args->start_s, args->start_f, + args->end_m, args->end_s, args->end_f, 0, 0, 0); + } + case CDIOCPLAYBLOCKS: { + struct ioc_play_blocks *args = (struct ioc_play_blocks*) addr; + + return wcd_play (t, ATAPI_PLAY_BIG, 0, + args->blk >> 24 & 0xff, args->blk >> 16 & 0xff, + args->blk >> 8 & 0xff, args->blk & 0xff, + args->len >> 24 & 0xff, args->len >> 16 & 0xff, + args->len >> 8 & 0xff, args->len & 0xff, 0, 0); + } + case CDIOCPLAYTRACKS: { + struct ioc_play_track *args = (struct ioc_play_track*) addr; + u_long start, len; + int t1, t2; + + if (! t->toc.hdr.ending_track) + return (ENODEV); + + /* Ignore index fields, + * play from start_track to end_track inclusive. */ + if (args->end_track < t->toc.hdr.ending_track+1) + ++args->end_track; + if (args->end_track > t->toc.hdr.ending_track+1) + args->end_track = t->toc.hdr.ending_track+1; + t1 = args->start_track - t->toc.hdr.starting_track; + t2 = args->end_track - t->toc.hdr.starting_track; + if (t1 < 0 || t2 < 0) + return (EINVAL); + start = t->toc.tab[t1].addr.lba; + len = t->toc.tab[t2].addr.lba - start; + + return wcd_play (t, ATAPI_PLAY_BIG, 0, + start >> 24 & 0xff, start >> 16 & 0xff, + start >> 8 & 0xff, start & 0xff, + len >> 24 & 0xff, len >> 16 & 0xff, + len >> 8 & 0xff, len & 0xff, 0, 0); + } + case CDIOCGETVOL: { + struct ioc_vol *arg = (struct ioc_vol*) addr; + + error = wcd_request_wait (t, ATAPI_MODE_SENSE, 0, AUDIO_PAGE, + 0, 0, 0, 0, sizeof (t->au) >> 8, sizeof (t->au), 0, + (char*) &t->au, sizeof (t->au)); + if (error) + return (error); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "au", &t->au, sizeof t->au); + if (t->au.page_code != AUDIO_PAGE) + return (EIO); + arg->vol[0] = t->au.port[0].volume; + arg->vol[1] = t->au.port[1].volume; + arg->vol[2] = t->au.port[2].volume; + arg->vol[3] = t->au.port[3].volume; + break; + } + case CDIOCSETVOL: { + struct ioc_vol *arg = (struct ioc_vol*) addr; + + error = wcd_request_wait (t, ATAPI_MODE_SENSE, 0, AUDIO_PAGE, + 0, 0, 0, 0, sizeof (t->au) >> 8, sizeof (t->au), 0, + (char*) &t->au, sizeof (t->au)); + if (error) + return (error); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "au", &t->au, sizeof t->au); + if (t->au.page_code != AUDIO_PAGE) + return (EIO); + + error = wcd_request_wait (t, ATAPI_MODE_SENSE, 0, + AUDIO_PAGE_MASK, 0, 0, 0, 0, sizeof (t->aumask) >> 8, + sizeof (t->aumask), 0, (char*) &t->aumask, + sizeof (t->aumask)); + if (error) + return (error); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "mask", &t->aumask, sizeof t->aumask); + + t->au.port[0].channels = CHANNEL_0; + t->au.port[1].channels = CHANNEL_1; + t->au.port[0].volume = arg->vol[0] & t->aumask.port[0].volume; + t->au.port[1].volume = arg->vol[1] & t->aumask.port[1].volume; + t->au.port[2].volume = arg->vol[2] & t->aumask.port[2].volume; + t->au.port[3].volume = arg->vol[3] & t->aumask.port[3].volume; + return wcd_request_wait (t, ATAPI_MODE_SELECT_BIG, 0x10, + 0, 0, 0, 0, 0, sizeof (t->au) >> 8, sizeof (t->au), + 0, (char*) &t->au, - sizeof (t->au)); + } + case CDIOCSETPATCH: { + struct ioc_patch *arg = (struct ioc_patch*) addr; + + return wcd_setchan (t, arg->patch[0], arg->patch[1], + arg->patch[2], arg->patch[3]); + } + case CDIOCSETMONO: + return wcd_setchan (t, CHANNEL_0 | CHANNEL_1, + CHANNEL_0 | CHANNEL_1, 0, 0); + + case CDIOCSETSTERIO: + return wcd_setchan (t, CHANNEL_0, CHANNEL_1, 0, 0); + + case CDIOCSETMUTE: + return wcd_setchan (t, 0, 0, 0, 0); + + case CDIOCSETLEFT: + return wcd_setchan (t, CHANNEL_0, CHANNEL_0, 0, 0); + + case CDIOCSETRIGHT: + return wcd_setchan (t, CHANNEL_1, CHANNEL_1, 0, 0); + } + return (error); +} + +/* + * Read the entire TOC for the disc into our internal buffer. + */ +static int wcd_read_toc (struct wcd *t) +{ + int ntracks, len, i; + + /* First read just the header, so we know how long the TOC is. */ + len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry); + if (wcd_request_wait (t, ATAPI_READ_TOC, 0, 0, 0, 0, 0, 0, + len >> 8, len & 0xff, 0, (char*)&t->toc, len) != 0) + return (EIO); + + ntracks = t->toc.hdr.ending_track - t->toc.hdr.starting_track + 1; + if (ntracks <= 0) + return (EIO); + if (ntracks > MAXTRK) + ntracks = MAXTRK; + + /* Now read the whole schmeer. */ + len = sizeof(struct ioc_toc_header) + + (ntracks+1) * sizeof(struct cd_toc_entry); + if (wcd_request_wait (t, ATAPI_READ_TOC, 0, 0, 0, 0, 0, 0, + len >> 8, len & 0xff, 0, (char*)&t->toc, len) & 0xff) + return (EIO); + + t->toc.hdr.len = ntohs (t->toc.hdr.len); + for (i=0; i<=ntracks; i++) + t->toc.tab[i].addr.lba = ntohl (t->toc.tab[i].addr.lba); + return (0); +} + +/* + * Set up the audio channel masks. + */ +static int wcd_setchan (struct wcd *t, + u_char c0, u_char c1, u_char c2, u_char c3) +{ + int error; + + error = wcd_request_wait (t, ATAPI_MODE_SENSE, 0, AUDIO_PAGE, + 0, 0, 0, 0, sizeof (t->au) >> 8, sizeof (t->au), 0, + (char*) &t->au, sizeof (t->au)); + if (error) + return (error); + if (t->flags & F_DEBUG) + wcd_dump (t->lun, "au", &t->au, sizeof t->au); + if (t->au.page_code != AUDIO_PAGE) + return (EIO); + + t->au.port[0].channels = c0; + t->au.port[1].channels = c1; + t->au.port[2].channels = c2; + t->au.port[3].channels = c3; + return wcd_request_wait (t, ATAPI_MODE_SELECT_BIG, 0x10, + 0, 0, 0, 0, 0, sizeof (t->au) >> 8, sizeof (t->au), + 0, (char*) &t->au, - sizeof (t->au)); +} +#endif /* NWCD && NWDC && ATAPI */ diff --git a/usr.bin/ee/nls/de_DE.ISO_8859-1/ee.msg b/usr.bin/ee/nls/de_DE.ISO_8859-1/ee.msg new file mode 100644 index 000000000000..f1aa1014bd75 --- /dev/null +++ b/usr.bin/ee/nls/de_DE.ISO_8859-1/ee.msg @@ -0,0 +1,170 @@ +$ This file contains the messages for ee ("easy editor"). See the file +$ ee.i18n.guide for more information +$ +$ For ee patchlevel 3 +$ +$ $Header$ +$ +$set 1 +$quote " +1 "Modus-Menü" +2 "Tab -> Leerzeichen " +3 "Suche ohne Groß/Klein" +4 "Ränder beachten " +5 "Automatische Absätze " +6 "8-Bit Zeichen (Uml.) " +7 "Hilfefenster " +8 "rechter Rand " +9 "Ende-Menü" +10 "Speichern" +11 "Verwerfen" +12 "Dateimenü" +13 "Öffnen" +14 "Schreiben in Datei" +15 "Speichern" +16 "Aktuellen Inhalt drucken" +17 "Textsuche" +18 "Suche nach ..." +19 "Suchen" +20 "Rechtschreibung" +21 "'spell' benutzen" +22 "'ispell' benutzen" +23 "Verschiedenes" +24 "Absatz formatieren" +25 "Unix-Kommando" +26 "Rechtschreibung prüfen" +27 "Hauptmenü" +28 "Editor beenden" +29 "Hilfe" +30 "Dateioperationen" +31 "Bildschirm regenerieren" +32 "Einstellungen" +33 "Suche" +34 "Verschiedenes" +35 "Steuertasten: " +36 "^a ASCII-Code direkt ^i Tabulator ^r nach rechts " +37 "^b Ende des Textes ^j neue Zeile ^t Anfang des Textes " +38 "^c Befehl ^k Zeichen löschen ^u hoch " +39 "^d runter ^l nach links ^v Wort zurückholen " +40 "^e Textsuche (Menü) ^m neue Zeile ^w Wort löschen " +41 "^f Zeichen zurückholen ^n nächste Seite ^x Weitersuchen " +42 "^g zum Zeilenanfang ^o zum Zeilenende ^y Zeile löschen " +43 "^h Rückschritt ^p vorige Seite ^z Zeile zurückholen " +44 "^[ (Escape) Menü " +45 " " +46 "Befehle: " +47 "hilfe : diese Hilfe anzeigen datei : Dateinamen anzeigen " +48 "lesen : Datei öffnen zeichen : ASCII-Code anzeigen " +49 "schreiben:Datei schreiben grosskl : Suche mit Groß/Kleinschr." +50 "ende : Sichern und Beenden klein : Suche ohne Groß/Klein. " +51 "abbruch : Abbruch ohne Sichern !bef : Unix-Befehl \"bef\" ausf. " +52 "zeile : Zeilennummer anzeigen 0-9 : Zur angegebenen Zeile " +53 "leer : Tabulat. in Leerz. wandeln tabs : Tabulatoren belassen " +54 " " +55 " ee [-i] [-e] [-h] [datei(en)] " +56 " -i : ohne Hilfefenster -e : Tabulatoren lassen -h : k. Hervorheb." +57 "^[ (Escape) Menü ^e Textsuche ^y Zeile löschen ^u hoch ^p Seite zur. " +58 "^a ASCII-Code ^x Weitersuchen ^z Zeile rückhl. ^d runter ^n Seite vor " +59 "^b Textende ^g Zeilenanfang ^w Wort löschen ^l links " +60 "^t Textanfang ^o Zeilenende ^v Wort rückhol. ^r rechts " +61 "^c Befehl ^k Zeichen lösch. ^f Zeichen rückholen " +62 "hilfe: Hilfe |datei : Dateiname anzeigen |zeile: Zeilennumer " +63 "lesen: Datei lesen |zeichen:ASCII-Code des Zeichens |0-9 : zur Zeile " +64 "schre: Datei schreib. |grosskl:Suche mit Groß/Klein |ende : Speichern,Ende " +65 "!bef : Unix-\"bef\" |klein: Suche ohne Groß/Klein |abbr : Abbruch " +66 "leer : Tab -> Leerz. |tabs : Tabulatoren belassen " +67 " Escape (^[) drücken für Menü" +68 "Keine Datei" +69 "ASCII-Code: " +70 "Pufferinhalt nach \"%s\" schreiben " +71 "Befehl: " +72 "Dateiname zum Schreiben: " +73 "Dateiname zum Lesen: " +74 "Zeichen = %d" +75 "Unbekannter Befehl \"%s\"" +76 "Angegebener Befehl ist nicht eindeutig" +77 "Zeile %d " +78 "Länge = %d" +79 "Aktuelle Datei ist \"%s\" " +80 "Benutzung: %s [-i] [-e] [-h] [+zeilennummer] [dateien]\n" +81 " -i Hilfefenster ausschalten\n" +82 " -e Tabulatoren nicht in Leerzeichen wandeln\" +83 " -h keine Hervorhebungen\n" +84 "Datei \"%s\" ist ein Verzeichnis" +85 "Neue Datei \"%s\"" +86 "Datei \"%s\" kann nicht geöffnet werden" +87 "Datei \"%s\", %d Zeilen" +88 "Lesen der Datei \"%s\" beendet" +89 "Lese die Datei \"%s\"" +90 ", schreibgeschützt" +91 "Datei \"%s\", %d Zeilen" +92 "Dateinamen eingeben: " +93 "Kein Name angegeben; Datei nicht gespeichert" +94 "Pufferinhalt geändert, wirklich verlassen? (j/n [n]) " +95 "j" +96 "Datei existiert bereits, überschreiben? (j/n) [n] " +97 "Datei \"%s\" kann nicht erzeugt werden" +98 "Schreibe Datei \"%s\"" +99 "\"%s\" %d Zeilen, %d Zeichen" +100 " ...Suche läuft" +101 "Zeichenfolge \"%s\" nicht gefunden" +102 "Suchen nach: " +103 "Kann %s nicht ausführen\n" +104 "Bitte die Eingabetaste drücken " +105 "Escape zum Beenden" +106 "Menü ist zu groß für das Fenster" +107 "eine beliebige Taste drücken " +108 "Unix-Befehl: " +109 "...formatiere Absatz..." +110 "<!echo 'Liste der nicht gefundenen Wörter'; echo -=-=-=-=-=-" +111 "Sende den Pufferinhalt an 'spell'" +112 "Rechter Rand: " +113 "Eingeschränkter Modus: gewünschte Operation unzulässig" +114 "EIN" +115 "AUS" +116 "HILFE" +117 "SCHREIBEN" +118 "LESEN" +119 "ZEILE" +120 "DATEI" +121 "ZEICHEN" +122 "REGENERIEREN" +123 "UMNUMERIEREN" +124 "AUTOR" +125 "VERSION" +126 "GROSSKL" +127 "KLEIN" +128 "LEER" +129 "TABS" +130 "ENDE" +131 "ABBRUCH" +132 "INFO" +133 "[INFO]" +134 "RAND" +135 "[RAND]" +136 "FORMAT." +137 "[FORMAT.]" +138 "ECHO" +139 "DRUCKBEFEHL" +140 "RECHTERRAND" +141 "HERVORHEB." +142 "[HERVORHEB.]" +143 "8-BIT" +144 "[8-BIT]" +145 "Emacs-Tastenbelegung " +146 "^a Zeilenanfang ^i Tabulator ^r Wort zurückholen " +147 "^b ein Zeichen zurück ^j Zeichen zurückholen ^t Textanfang " +148 "^c Befehl ^k Zeile löschen ^u Textende " +149 "^d Zeichen löschen ^l Zeile zurückholen ^v nächste Seite " +150 "^e Zeilenendee ^m neue Zeile ^w Wort löschen " +151 "^f ein Zeichen vorwärts ^n neue Zeile ^x Weitersuchen " +152 "^g vorige Seite ^o ASCII-Zeichen einfü. ^y Textsuche " +153 "^h Rückschritt ^p vorige Zeile ^z nächstes Wort " +154 "^[ (Escape) Menü ^y Suchtext eing. ^k Zeile löschen ^p vor.Zeile ^g vor.Seite" +155 "^o ASCII-Zeichen ^x Weitersuchen ^l Zeile rückhol ^n nä. Zeile ^v nä. Seite" +156 "^u Textende ^a Zeilenanfang ^w Wort löschen ^b ein Zeichen zurück " +157 "^t Textanfang ^e Zeilenende ^r Wort rückhol. ^f ein Zeichen vor " +158 "^c Befehl ^d Zeichen lösch. ^j Zeich. rückh. ^z nächstes Wort " +159 "EMACS" +160 "[EMACS]" +161 " +<zahl> Zeiger auf Zeile <zahl> setzen" diff --git a/usr.sbin/sicontrol/sicontrol.8 b/usr.sbin/sicontrol/sicontrol.8 new file mode 100644 index 000000000000..ce25794a004b --- /dev/null +++ b/usr.sbin/sicontrol/sicontrol.8 @@ -0,0 +1,113 @@ +.\" $Id$ +.\" The following requests are required for all man pages. +.Dd September 26,1995 +.Dt SICONTROL 8 +.Os FreeBSD +.Sh NAME +.Nm sicontrol +.Nd Specialix SI/XIO driver configuration and debugging +.Sh SYNOPSIS +.Nm sicontrol +device +.Ar command Op Cm Ar param ... +.Sh DESCRIPTION +.Nm sicontrol +is used to configure and monitor the SI/XIO device driver. +.Pp +.Nm sicontrol +operates on the specified +.Ar device +to indicate which port is to be used. +.Pp +The special +.Ar device +string `-' is used to indicate the global driver settings instead. +.Pp +A '/dev/' is included if necessary. +.Pp +The following commands are used for the global settings and should be +specified with the '-' device name. +.Bl -tag -width 4n +.It Cm int_throttle Op Cm value +Configure the `aggregate interrupt throttle value'. +The maximum number of host adapter interrupts per second is determined by: +.Pp +.Ar "controller CPU clock / (8 * int_throttle)" +.Pp +The default value at boot time is 25000. The host adapter cpu clock is +25Mhz. This gives a maximum interrupt rate of about 125 interrupts per +second. +.Pp +Lowering this value will increase the rate in which the host adapter can +interrupt the operating system for attention. +.\" +.It Cm rxint_throttle Op Cm value +Configure the receiver interrupt throttle value. +The default value of 4 at boot time allows an interrupt rate of +approximately 25. +.Pp +Lowering this value will increase the rate in which the host adapter can +interrupt the operating system to empty the receviver fifos. +.\" +.It Cm nport +Returns the number of ports under the control of the device driver. +.El +.Pp +The following commands are used for the individual ports and should be +specified with a device name from /dev. +.Bl -tag -width 4n +.It Cm mstate +Shows the current incoming modem control signals. +.It Cm ccbstat +Shows the current "ccb" structure for the specified port. This is not of +much use outside of debugging the driver and determining why a port is +wedged. +.It Cm ttystat +Shows the current "tty" structure that the kernel has for the specified port. +This is not much use outside of debugging the driver. +.El +.\" The following requests should be uncommented and used where appropriate. +.\" This next request is for sections 2 and 3 function return values only. +.\" .Sh RETURN VALUES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" .Sh ENVIRONMENT +.Sh FILES +.Bl -tag -width /dev/si_control -compact +.It Pa /dev/si_control +global driver control file for use by +.Xr sicontrol 8 . +.It Pa /dev/ttyA* +terminal control ports +.It Pa /dev/ttyiA* +initial termios state devices, for use by +.Xr stty 1 +.It Pa /dev/ttylA* +locked termios state devices, for use by +.Xr stty 1 +.El +.\" .Sh EXAMPLES +.\" This next request is for sections 1, 6, 7 & 8 only +.\" (command return values (to shell) and fprintf/stderr type diagnostics) +.Sh DIAGNOSTICS +Generally self explanatory..... +.\" The next request is for sections 2 and 3 error and signal handling only. +.\" .Sh ERRORS +.Sh SEE ALSO +.Xr stty 1 , +.Xr termios 4 , +.Xr tty 4 , +.Xr si 4 , +.Xr comcontrol 8 . +.\" .Sh STANDARDS +.Sh HISTORY +.Nm sicontrol +is loosely based on a utility called +.Nm siconfig +which was written by +.Nm "Andy Rutter <andy@acronym.co.uk>" +.Pp +Specialix International do not support this device driver in any way. +.Sh AUTHORS +Peter Wemm <peter@freebsd.org> +.Sh BUGS +Bound to be many... :-) |
