patch-2.1.77 linux/drivers/cdrom/bpcd.c

Next file: linux/drivers/cdrom/cdrom.c
Previous file: linux/drivers/cdrom/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.76/linux/drivers/cdrom/bpcd.c linux/drivers/cdrom/bpcd.c
@@ -1,793 +0,0 @@
-/* 
-	bpcd.c	(c) 1996  Grant R. Guenther <grant@torque.net>
-		          Under the terms of the GNU public license.
-
-	bpcd.c is a driver for the MicroSolutions "backpack" CDrom,
-	an external parallel port device.  
-
-	There are apparently two versions of the backpack protocol.  This 
-        driver knows about the version 2 protocol - as is used in the 4x 
-	and 6x products.  There is no support for the sound hardware that
-        is included in some models.  It should not be difficult to add 
-        support for the ATAPI audio play functions and the corresponding 
-        ioctls.
-
-	The driver was developed by reverse engineering the protocol
-        and testing it on the backpack model 164550.  This model
-	is actually a stock ATAPI drive packaged with a custom 
-	ASIC that implements the IDE over parallel protocol.
-	I tested with a backpack that happened to contain a Goldstar
-        drive, but I've seen reports of Sony and Mitsumi drives as well.
-
-	bpcd.c can be compiled for version 1.2.13 of the Linux kernel
-        and for the 2.0 series.  (It should also work with most of the
-        later 1.3 kernels.)
-
-        If you have a copy of the driver that has not been integrated into
-        the kernel source tree, you can compile the driver manually, as a 
-        module.  Ensure that /usr/include/linux and /usr/include/asm are 
-	links to the correct include files for the target system.  Compile 
-        the driver with
-
-                cc -D__KERNEL__ -DMODULE -O2 -c bpcd.c
-
-        You must then load it with insmod.  If you are using
-        MODVERSIONS, add the following to the cc command:
-
-		-DMODVERSIONS -I /usr/include/linux/modversions.h
-
-	Before attempting to access the new driver, you will need to
-        create a new device special file.  The following commands will
-	do that for you:
-
-		mknod /dev/bpcd b 41 0
-		chown root:disk /dev/bpcd
-		chmod 660 /dev/bpcd
-
-	Afterward, you can mount a disk in the usual way:
-
-		mount -t iso9660 /dev/bpcd /cdrom
-
-	(assuming you have made a directory /cdrom to use as a
-        mount point).
-
-	The driver will attempt to detect which parallel port your
-        backpack is connected to.  If this fails for any reason, you
-        can override it by specifying a port on the LILO command line
-        (for built in drivers) or the insmod command (for drivers built
-        as modules).   If your drive is on the port at 0x3bc, you would
-        use one of these commands:
-
-		LILO:	   bpcd=0x3bc
-
-		insmod:    insmod bpcd bp_base=0x3bc
-
-	The driver can detect if the parallel port supports 8-bit
-        transfers.  If so, it will use them.  You can force it to use
-        4-bit (nybble) mode by setting the variable bp_nybble to 1 on
-        an insmod command, or using the following LILO parameters:
-
-		bpcd=0x3bc,1
-
-	(you must specify the correct port address if you use this method.)
-
-	There is currently no support for EPP or ECP modes.  Also,
-        as far as I can tell, the MicroSolutions protocol does not
-        support interrupts in the 4-bit and 8-bit modes.
-
-	MicroSolutions' protocol allows for several drives to be
-        chained together off the same parallel port.  Currently, this
-        driver will recognise only one of them.  If you do have more
-        than one drive, it will choose the one with the lowest id number,
-        where the id number is the last two digits of the product's
-        serial number.
-
-	It is not currently possible to connect a printer to the chained
-        port on the BackPack and expect Linux to use both devices at once.
-
-	If you need to use this driver together with a printer on the
-        same port, build both the bpcd and lp drivers are modules.
-
-	Keep an eye on http://www.torque.net/bpcd.html for news and
-        other information about the driver.  If you have any problems
-        with this driver, please send me, grant@torque.net, some mail 
-        directly before posting into the newsgroups or mailing lists.
-
-*/
-
-#define	BP_VERSION	"0.14" 
-
-#define	BP_BASE		0	/* set to 0 for autoprobe */
-#define BP_REP		4
-
-#include <linux/version.h>
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <linux/kernel.h>
-#include <linux/tqueue.h>
-#include <linux/delay.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#ifndef BPCD_MAJOR
-#define BPCD_MAJOR   41	
-#endif
-
-#define MAJOR_NR BPCD_MAJOR
-
-/* set up defines for blk.h,  why don't all drivers do it this way ? */
-
-#define DEVICE_NAME "BackPack"
-#define DEVICE_REQUEST do_bp_request
-#define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-
-#include <linux/blk.h>
-
-#define BP_TMO		   300		/* timeout in jiffies */
-#define BP_DELAY            50          /* spin delay in uS */
-
-#define BP_SPIN		(10000/BP_DELAY)*BP_TMO
-
-int bpcd_init(void);
-void bpcd_setup(char * str, int * ints);
-void cleanup_module( void );
-
-static int 	bp_open(struct inode *inode, struct file *file);
-static void 	do_bp_request(void);
-static void 	do_bp_read(void);
-static int 	bp_ioctl(struct inode *inode,struct file *file,
-                         unsigned int cmd, unsigned long arg);
-static int 	bp_release (struct inode *inode, struct file *file);
-
-static int 	bp_detect(void);
-static int      bp_lock(void);
-static void     bp_unlock(void);
-static void     bp_eject(void);
-static void     bp_interrupt(void *data);
-
-static int	bp_base = BP_BASE;
-static int	bp_rep = BP_REP;
-static int	bp_nybble = 0;		/* force 4-bit mode ? */
-
-static int      bp_unit_id;
-
-static int bp_access = 0;		/* count of active opens ... */
-static int bp_mode = 1;			/* 4- or 8-bit mode */
-static int bp_busy = 0;			/* request being processed ? */
-static int bp_timeout;                  /* "interrupt" loop limiter */
-static int bp_sector;			/* address of next requested sector */
-static int bp_count;			/* number of blocks still to do */
-static char * bp_buf;			/* buffer for request in progress */
-static char bp_buffer[2048];		/* raw block buffer */
-static int bp_bufblk = -1;		/* block in buffer, in CD units,
-					   -1 for nothing there */
-static  int	nyb_map[256];		/* decodes a nybble */
-static	int	PortCache = 0;		/* cache of the control port */
-
-static struct tq_struct bp_tq = {0,0,bp_interrupt,NULL}; 
-
-/* kernel glue structures */
-
-static struct file_operations bp_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	bp_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	bp_open,		/* open */
-	bp_release,		/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	NULL,                   /* media change ? */
-	NULL			/* revalidate new media */
-};
-
-
-/* the MicroSolutions protocol uses bits 3,4,5 & 7 of the status port to
-   deliver a nybble in 4 bit mode.  We use a table lookup to extract the
-   nybble value.  The following function initialises the table.
-*/
-
-__initfunc(static void init_nyb_map( void ))
-
-{	int	i, j;
-
-	for(i=0;i<256;i++) { 
-	   j = (i >> 3) & 0x7;
-	   if (i & 0x80) j |= 8;
-	   nyb_map[i] = j;
-	}
-}
-
-__initfunc(int bpcd_init (void))	/* preliminary initialisation */
-
-{	init_nyb_map();
-
-        if (bp_detect()) return -1;
-
-	if (register_blkdev(MAJOR_NR,"bpcd",&bp_fops)) {
-		printk("bpcd: unable to get major number %d\n",MAJOR_NR);
-		return -1;
-	}
-	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
-	read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB) read ahead */
-
-	return 0;
-}
-
-static int bp_open (struct inode *inode, struct file *file)
-
-{	
-	if (file->f_mode & 2) return -EROFS;  /* wants to write ? */
-
-	MOD_INC_USE_COUNT;
-
-	if (!bp_access)
-	   if (bp_lock()) {
-		MOD_DEC_USE_COUNT;
-		return -ENXIO;
-	   }
-	bp_access++;
-	return 0;
-}
-
-static void do_bp_request (void)
-
-{       if (bp_busy) return;
-        while (1) {
-	    if ((!CURRENT) || (CURRENT->rq_status == RQ_INACTIVE)) return;
-	    INIT_REQUEST;
-	    if (CURRENT->cmd == READ) {
-	        bp_sector = CURRENT->sector;
-	        bp_count = CURRENT->nr_sectors;
-	        bp_buf = CURRENT->buffer;
-	        do_bp_read();
-		if (bp_busy) return;
-	    } 
-	    else end_request(0);
-	}
-}
-
-static int bp_ioctl(struct inode *inode,struct file *file,
-		    unsigned int cmd, unsigned long arg)
-
-/* we currently support only the EJECT ioctl. */
-
-{	switch (cmd) {
-            case CDROMEJECT: if (bp_access == 1) {
-				bp_eject();
-				return 0;
-			     }
-	    default:
-	        return -EINVAL;
-	}
-}
-
-static int bp_release (struct inode *inode, struct file *file)
-
-{	kdev_t	devp;
-
-	bp_access--;
-	if (!bp_access) { 
-	    devp = inode->i_rdev;
-	    fsync_dev(devp);
-	    invalidate_inodes(devp);
-	    invalidate_buffers(devp);
-	    bp_unlock();
-	}
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-#ifdef MODULE
-
-/* Glue for modules ... */
-
-int	init_module(void)
-
-{	int	err;
-	long    flags;
-
-	save_flags(flags);
-	cli();
-
-	err = bpcd_init();
-
-	restore_flags(flags);
-	return err;
-}
-
-void	cleanup_module(void)
-
-{	long flags;
-
-	save_flags(flags);
-	cli();
-	unregister_blkdev(MAJOR_NR,"bpcd");
-	release_region(bp_base,3);
-	restore_flags(flags);
-}
-
-#else 
-
-/* bpcd_setup:  process lilo command parameters ...
-
-   syntax:	bpcd=base[,nybble[,rep]]
-*/
-
-__initfunc(void bpcd_setup(char *str, int *ints))
-
-{       if (ints[0] > 0) bp_base = ints[1];
-        if (ints[0] > 1) bp_nybble = ints[2];
-        if (ints[0] > 2) bp_rep = ints[3];
-} 
-
-#endif
-
-static	void    out_p( short port, char byte)
-
-{       int i;
-
-	for(i=0;i<bp_rep;i++) outb(byte,bp_base+port);
-}
-
-static	int     in_p( short port)
-
-{       int i;
-	char c;
-
-	for(i=0;i<bp_rep;i++) c=inb(bp_base+port);
-	c=inb(bp_base+port);
-	return c & 0xff;
-}
-
-/* Unlike other PP devices I've worked on, the backpack protocol seems
-   to be driven by *changes* in the values of certain bits on the control
-   port, rather than their absolute value.  Hence the unusual macros ...
-*/
-
-#define w0(byte)  		out_p(0,byte)
-#define r0()      		(in_p(0) & 0xff)
-#define w1(byte)  		out_p(1,byte)
-#define r1()      		(in_p(1) & 0xff)
-#define w2(byte)  		out_p(2,byte) ; PortCache = byte
-#define t2(pat)   		PortCache ^= pat; out_p(2,PortCache)
-#define e2()			PortCache &= 0xfe; out_p(2,PortCache)
-#define o2()			PortCache |= 1; out_p(2,PortCache)
-
-static int read_byte( void )
-
-{	int l, h;
-
-	t2(4); 
-	if (bp_mode == 2) return r0();
-	l = nyb_map[r1()];
-	t2(4);
-	h = nyb_map[r1()];
-	return (h << 4) + l;
-}
-
-static int read_regr( char regr )
-
-{       int r;
-
-       	w0(regr & 0xf); w0(regr); t2(2);
-	if (bp_mode == 2) { e2(); t2(0x20); }
-	r = read_byte();
-	if (bp_mode == 2) { t2(1); t2(0x20); }
-	return r;
-}	
-
-static void write_regr( char regr, char val )
-
-{	w0(regr);
-	t2(2);
-	w0(val);
-	o2(); t2(4); t2(1);
-}
-
-static void write_cmd( char * cmd, int len )
-
-{	int i, f;
-
-	if (bp_mode == 2) f = 0x10; else f = 0;
-	write_regr(4,0x40|f);
-	w0(0x40); t2(2); t2(1);
-	i = 0;
-	while (i < len) {
-	   w0(cmd[i++]); 
-	   t2(4);
-	}
-	write_regr(4,f);
-}
-
-static void read_data( char * buf, int len )
-
-{	int i, f;
-
-	if (bp_mode == 2) f = 0x50; else f = 0x40;
-	write_regr(4,f);
-	w0(0x40); t2(2);
-	if (bp_mode == 2) t2(0x20);
-	for(i=0;i<len;i++) buf[i] = read_byte();
-	if (bp_mode == 2) { t2(1); t2(0x20); }
-}
-
-__initfunc(static int probe( int id ))
-
-{	int l, h, t;
-	int r = -1;
-
-	w2(4); w2(0xe); w2(0xec); w1(0x7f);
-	if ((r1() & 0xf8) != 0x78) return -1;
-	w0(255-id); w2(4); w0(id);
-	t2(8); t2(8); t2(8);
-	t2(2); t = (r1() & 0xf8);
-	if (t != 0x78) {
-		l = nyb_map[t];
-		t2(2); h = nyb_map[r1()];
-		t2(8);
-		r = 0;
-	}
-	w0(0); t2(2); w2(0x4c); w0(0x13);
-	return r;
-}
-	
-static void connect ( void  )
-
-{	int	f;
-
-	w0(0xff-bp_unit_id); w2(4); w0(bp_unit_id);
-	t2(8); t2(8); t2(8); 
-	t2(2); t2(2); t2(8);
-	if (bp_mode == 2) f = 0x10; else f = 0;
-	write_regr(4,f);
-	write_regr(5,8);
-	write_regr(0x46,0x10);
-	write_regr(0x4c,0x38);
-	write_regr(0x4d,0x88);
-	write_regr(0x46,0xa0);
-	write_regr(0x41,0);
-	write_regr(0x4e,8);
-}
-
-static void disconnect ( void )
-
-{	w0(0); t2(2); w2(0x4c);
-	if (bp_mode == 2) w0(0xff); else  w0(0x13);
-} 
-
-static int bp_wait_drq( char * lab, char * fun )
-
-{	int j, r, e;
-
-	j = 0;
-
-	while (1)  {
-        	r = read_regr(0x47);
-		e = read_regr(0x41);
-		if ((r & 9) || (j++ >= BP_SPIN)) break;
-		udelay(BP_DELAY);
-	}
-
-	if ((j >= BP_SPIN) || (r & 1)) {
-	    if (lab && fun) 
-		   printk("bpcd: %s (%s): %s status: %x error: %x\n",
-			  lab,fun,(j >= BP_SPIN)?"timeout, ":"",r,e);
-	    return -1;
-	}
-	return 0;
-}
-
-static int bp_wait( char * lab, char * fun )
-
-{	int j, r, e;
-
-	j = 0;
-	while ((!(read_regr(0xb) & 0x80)) && (j++ < BP_SPIN)) udelay(BP_DELAY);
-        r = read_regr(0x47);
-	e = read_regr(0x41);
-	if ((j >= BP_SPIN) || (r & 1)) {
-	    if (lab && fun) 
-		   printk("bpcd: %s (%s): %s status: %x error: %x\n",
-			  lab,fun,(j >= BP_SPIN)?"timeout, ":"",r,e);
-	    return -1;
-	}
-	return 0;
-}
-
-static int bp_command( char * cmd, int dlen, char * fun )
-
-{	int	r;
-
-	connect();
-	write_regr(0x44,dlen % 256);
-	write_regr(0x45,dlen / 256);
-	write_regr(0x46,0xa0);		/* drive 0 */
-	write_regr(0x47,0xa0);		/* ATAPI packet command */
-	if ((r=bp_wait_drq("bp_command",fun))) {
-	   disconnect();
-	   return r;
-	}
-	write_cmd(cmd,12);
-	return 0;
-}
-
-static int bp_completion( char * fun )
-
-{	int r, n;
-
-	if (!(r=bp_wait("bp_completion",fun))) {
-	    if (read_regr(0x42) == 2) {
-	        n = (read_regr(0x44) + 256*read_regr(0x45));
-	        read_data(bp_buffer,n);
-	        r=bp_wait("transfer done",fun);
-	    }
-	}
-	disconnect(); 
-	return r;
-}
-
-static int bp_atapi( char * cmd, int dlen, char * fun )
-
-{	int r;
-
-	if (!(r=bp_command(cmd,dlen,fun)))
-	  r = bp_completion(fun);
-	return r;
-}
-
-static int bp_req_sense( char * msg )
-
-{	char	rs_cmd[12] = { 0x03,0,0,0,18,0,0,0,0,0,0,0 };
-	int r;
-
-	r = bp_atapi(rs_cmd,18,"request sense");
-	if (msg) printk("bpcd: %s:  sense key: %x, ASC: %x, ASQ: %x\n",msg,
-			 bp_buffer[2]&0xf, bp_buffer[12], bp_buffer[13]);
-	return r;
-}
-
-static int bp_lock(void)
-
-{	char	lo_cmd[12] = { 0x1e,0,0,0,1,0,0,0,0,0,0,0 };
-	char	cl_cmd[12] = { 0x1b,0,0,0,3,0,0,0,0,0,0,0 };
-
-	bp_atapi(cl_cmd,0,"close door");
-        if (bp_req_sense(NULL)) return -1;  /* check for disk */
-	bp_atapi(lo_cmd,0,NULL);
-	bp_req_sense(NULL);  /* in case there was a media change */
-	bp_atapi(lo_cmd,0,"lock door");
-	return 0;
-}
-
-static void bp_unlock( void)
-
-{	char	un_cmd[12] = { 0x1e,0,0,0,0,0,0,0,0,0,0,0 };
-
-	bp_atapi(un_cmd,0,"unlock door");
-}
-
-static void bp_eject( void)
-
-{	char	ej_cmd[12] = { 0x1b,0,0,0,2,0,0,0,0,0,0,0 };
-
-	bp_unlock();
-	bp_atapi(ej_cmd,0,"eject");
-}
-
-__initfunc(static int bp_reset( void ))
-
-/* the ATAPI standard actually specifies the contents of all 7 registers
-   after a reset, but the specification is ambiguous concerning the last
-   two bytes, and different drives interpret the standard differently.
-*/
-
-{	int	i, flg;
-	int	expect[5] = {1,1,1,0x14,0xeb};
-	long	flags;
-
-	connect();
-	write_regr(0x46,0xa0);
-	write_regr(0x47,8);
-
-	save_flags(flags);
-	sti();
-	udelay(500000);  	/* delay 0.5 seconds */
-	restore_flags(flags);
-
-	flg = 1;
-	for(i=0;i<5;i++) flg &= (read_regr(i+0x41) == expect[i]);
-	
-	disconnect();
-	return flg-1;	
-}
-
-__initfunc(static int bp_identify( char * id ))
-
-{	int k;
-	char   id_cmd[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0};
-
-	bp_bufblk = -1;
-        if (bp_atapi(id_cmd,36,"identify")) return -1;
-	for (k=0;k<16;k++) id[k] = bp_buffer[16+k];
-	id[16] = 0;
-	return 0;
-}
-
-__initfunc(static int bp_port_check( void )) 	/* check for 8-bit port */
-
-{	int	r;
-
-        w2(0); 
-	w0(0x55); if (r0() != 0x55) return 0;
-	w0(0xaa); if (r0() != 0xaa) return 0;
-	w2(0x20); w0(0x55); r = r0(); w0(0xaa);
-	if (r0() == r) return 2;
-	if (r0() == 0xaa) return 1;
-	return 0;
-}
-
-__initfunc(static int bp_locate( void ))
-
-{	int	k;
-
-	for(k=0;k<100;k++) 
-	  if (!probe(k)) {
-		bp_unit_id = k;
-		return 0;
-	  }
-	return -1;
-}
-
-__initfunc(static int bp_do_detect( int autop ))
-
-{	char   id[18];
-
-	if (autop) bp_base = autop;
-
-	if (check_region(bp_base,3)) {
-		if (!autop) 
-		  printk("bpcd: Ports at 0x%x are not available\n",bp_base);
-		return -1;
-	}
-
-	bp_mode = bp_port_check();
-
-	if (!bp_mode) {
-		if (!autop)
-		  printk("bpcd: No parallel port at 0x%x\n",bp_base);
-		return -1;
-	}
-
-	if (bp_nybble) bp_mode = 1;
-
-	if (bp_locate()) {
-		if (!autop)
-		  printk("bpcd: Couldn't find a backpack adapter at 0x%x\n",
-			  bp_base);
-		return -1;
-	}
-
-	if (bp_reset()) {
-		if (!autop)
-		  printk("bpcd: Failed to reset CD drive\n");
-		return -1;
-	}
-
-	if (bp_identify(id)) {
-		if (!autop)
-		  printk("bpcd: ATAPI inquiry failed\n");
-		return -1;
-	}
-
-	request_region(bp_base,3,"bpcd");
-
-	printk("bpcd: Found %s, ID %d, using port 0x%x in %d-bit mode\n",
-	       id,bp_unit_id,bp_base,4*bp_mode);
-
-	return 0;
-}
-
-/* If you know about some other weird parallel port base address,
-   add it here ....
-*/
-
-__initfunc(static int bp_detect( void ))
-
-{	if (bp_base) return bp_do_detect(0);
-	if (!bp_do_detect(0x378)) return 0;
-	if (!bp_do_detect(0x278)) return 0;
-	if (!bp_do_detect(0x3bc)) return 0;
-	printk("bpcd: Autoprobe failed\n");
-	return -1;
-}
-
-
-static void bp_transfer( void )
-
-{	int	k, o;
-
-	while (bp_count && (bp_sector/4 == bp_bufblk)) {
-		o = (bp_sector % 4) * 512;
-		for(k=0;k<512;k++) bp_buf[k] = bp_buffer[o+k];
-		bp_count--;
-		bp_buf += 512;
-		bp_sector++;
-	}
-}
-
-static void do_bp_read( void )
-
-{	int	b, i;
-	char	rd_cmd[12] = {0xa8,0,0,0,0,0,0,0,0,1,0,0};
-
-	bp_busy = 1;
-	bp_transfer();
-	if (!bp_count) {
-		end_request(1);
-		bp_busy = 0;
-		return;
-	}
-	sti();
-
-	bp_bufblk = bp_sector / 4;
-        b = bp_bufblk;
-	for(i=0;i<4;i++) { 
-	   rd_cmd[5-i] = b & 0xff;
-	   b = b >> 8;
-	}
-
-	if (bp_command(rd_cmd,2048,"read block")) {
-		bp_bufblk = -1; 
-		bp_busy = 0;
-		cli();
-		bp_req_sense("send read command");
-		end_request(0);
-		return;
-	}
-	bp_timeout = jiffies + BP_TMO;
-	queue_task(&bp_tq,&tq_scheduler); 
-}
-
-static void bp_interrupt( void *data)
-
-{	if (!(read_regr(0xb) & 0x80)) {
-		if (jiffies > bp_timeout) {
-			bp_bufblk = -1;
-			bp_busy = 0;
-			bp_req_sense("interrupt timeout");
-			end_request(0);
-			do_bp_request();
-		}
-		queue_task(&bp_tq,&tq_scheduler); 
-		return;
-	}
-	sti();
-	if (bp_completion("read completion")) {
-		cli();
-		bp_busy = 0;
-		bp_bufblk = -1;
-		bp_req_sense("read completion");
-		end_request(0);
-		do_bp_request();
-	}
-	do_bp_read();
-	do_bp_request();
-}
-	
-/* end of bpcd.c */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov