patch-2.1.67 linux/drivers/sound/pas2_pcm.c

Next file: linux/drivers/sound/pnp.c
Previous file: linux/drivers/sound/pas2_mixer.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.66/linux/drivers/sound/pas2_pcm.c linux/drivers/sound/pas2_pcm.c
@@ -12,8 +12,7 @@
 
 #include "sound_config.h"
 
-#ifdef CONFIG_PAS
-#ifdef CONFIG_AUDIO
+#if defined(MODULE) || ( defined(CONFIG_PAS) && defined(CONFIG_AUDIO) )
 
 #ifndef DEB
 #define DEB(WHAT)
@@ -40,425 +39,418 @@
 static int      open_mode = 0;
 
 static int
-pcm_set_speed (int arg)
+pcm_set_speed(int arg)
 {
-  int             foo, tmp;
-  unsigned long   flags;
+	int             foo, tmp;
+	unsigned long   flags;
 
-  if (arg == 0)
-    return pcm_speed;
+	if (arg == 0)
+		return pcm_speed;
 
-  if (arg > 44100)
-    arg = 44100;
-  if (arg < 5000)
-    arg = 5000;
-
-  if (pcm_channels & 2)
-    {
-      foo = (596590 + (arg / 2)) / arg;
-      arg = (596590 + (foo / 2)) / foo;
-    }
-  else
-    {
-      foo = (1193180 + (arg / 2)) / arg;
-      arg = (1193180 + (foo / 2)) / foo;
-    }
-
-  pcm_speed = arg;
-
-  tmp = pas_read (0x0B8A);
-
-  /*
-     * Set anti-aliasing filters according to sample rate. You really *NEED*
-     * to enable this feature for all normal recording unless you want to
-     * experiment with aliasing effects.
-     * These filters apply to the selected "recording" source.
-     * I (pfw) don't know the encoding of these 5 bits. The values shown
-     * come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
-     *
-     * I cleared bit 5 of these values, since that bit controls the master
-     * mute flag. (Olav Wölfelschneider)
-     *
-   */
+	if (arg > 44100)
+		arg = 44100;
+	if (arg < 5000)
+		arg = 5000;
+
+	if (pcm_channels & 2)
+	  {
+		  foo = (596590 + (arg / 2)) / arg;
+		  arg = (596590 + (foo / 2)) / foo;
+	} else
+	  {
+		  foo = (1193180 + (arg / 2)) / arg;
+		  arg = (1193180 + (foo / 2)) / foo;
+	  }
+
+	pcm_speed = arg;
+
+	tmp = pas_read(0x0B8A);
+
+	/*
+	   * Set anti-aliasing filters according to sample rate. You really *NEED*
+	   * to enable this feature for all normal recording unless you want to
+	   * experiment with aliasing effects.
+	   * These filters apply to the selected "recording" source.
+	   * I (pfw) don't know the encoding of these 5 bits. The values shown
+	   * come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
+	   *
+	   * I cleared bit 5 of these values, since that bit controls the master
+	   * mute flag. (Olav Wölfelschneider)
+	   *
+	 */
 #if !defined NO_AUTO_FILTER_SET
-  tmp &= 0xe0;
-  if (pcm_speed >= 2 * 17897)
-    tmp |= 0x01;
-  else if (pcm_speed >= 2 * 15909)
-    tmp |= 0x02;
-  else if (pcm_speed >= 2 * 11931)
-    tmp |= 0x09;
-  else if (pcm_speed >= 2 * 8948)
-    tmp |= 0x11;
-  else if (pcm_speed >= 2 * 5965)
-    tmp |= 0x19;
-  else if (pcm_speed >= 2 * 2982)
-    tmp |= 0x04;
-  pcm_filter = tmp;
+	tmp &= 0xe0;
+	if (pcm_speed >= 2 * 17897)
+		tmp |= 0x01;
+	else if (pcm_speed >= 2 * 15909)
+		tmp |= 0x02;
+	else if (pcm_speed >= 2 * 11931)
+		tmp |= 0x09;
+	else if (pcm_speed >= 2 * 8948)
+		tmp |= 0x11;
+	else if (pcm_speed >= 2 * 5965)
+		tmp |= 0x19;
+	else if (pcm_speed >= 2 * 2982)
+		tmp |= 0x04;
+	pcm_filter = tmp;
 #endif
 
-  save_flags (flags);
-  cli ();
+	save_flags(flags);
+	cli();
 
-  pas_write (tmp & ~(0x40 | 0x80), 0x0B8A);
-  pas_write (0x00 | 0x30 | 0x04, 0x138B);
-  pas_write (foo & 0xff, 0x1388);
-  pas_write ((foo >> 8) & 0xff, 0x1388);
-  pas_write (tmp, 0x0B8A);
+	pas_write(tmp & ~(0x40 | 0x80), 0x0B8A);
+	pas_write(0x00 | 0x30 | 0x04, 0x138B);
+	pas_write(foo & 0xff, 0x1388);
+	pas_write((foo >> 8) & 0xff, 0x1388);
+	pas_write(tmp, 0x0B8A);
 
-  restore_flags (flags);
+	restore_flags(flags);
 
-  return pcm_speed;
+	return pcm_speed;
 }
 
 static int
-pcm_set_channels (int arg)
+pcm_set_channels(int arg)
 {
 
-  if ((arg != 1) && (arg != 2))
-    return pcm_channels;
+	if ((arg != 1) && (arg != 2))
+		return pcm_channels;
 
-  if (arg != pcm_channels)
-    {
-      pas_write (pas_read (0xF8A) ^ 0x20, 0xF8A);
+	if (arg != pcm_channels)
+	  {
+		  pas_write(pas_read(0xF8A) ^ 0x20, 0xF8A);
 
-      pcm_channels = arg;
-      pcm_set_speed (pcm_speed);	/* The speed must be reinitialized */
-    }
-
-  return pcm_channels;
+		  pcm_channels = arg;
+		  pcm_set_speed(pcm_speed);	/* The speed must be reinitialized */
+	  }
+	return pcm_channels;
 }
 
 static int
-pcm_set_bits (int arg)
+pcm_set_bits(int arg)
 {
-  if (arg == 0)
-    return pcm_bits;
-
-  if ((arg & pcm_bitsok) != arg)
-    return pcm_bits;
+	if (arg == 0)
+		return pcm_bits;
 
-  if (arg != pcm_bits)
-    {
-      pas_write (pas_read (0x8389) ^ 0x04, 0x8389);
+	if ((arg & pcm_bitsok) != arg)
+		return pcm_bits;
 
-      pcm_bits = arg;
-    }
+	if (arg != pcm_bits)
+	  {
+		  pas_write(pas_read(0x8389) ^ 0x04, 0x8389);
 
-  return pcm_bits;
+		  pcm_bits = arg;
+	  }
+	return pcm_bits;
 }
 
 static int
-pas_audio_ioctl (int dev, unsigned int cmd, caddr_t arg)
+pas_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
 {
-  int             val;
+	int             val;
 
-  DEB (printk ("pas2_pcm.c: static int pas_audio_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
+	DEB(printk("pas2_pcm.c: static int pas_audio_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
 
-  switch (cmd)
-    {
-    case SOUND_PCM_WRITE_RATE:
-      val = *(int *) arg;
-      return (*(int *) arg = pcm_set_speed (val));
-      break;
-
-    case SOUND_PCM_READ_RATE:
-      return (*(int *) arg = pcm_speed);
-      break;
-
-    case SNDCTL_DSP_STEREO:
-      val = *(int *) arg;
-      return (*(int *) arg = pcm_set_channels (val + 1) - 1);
-      break;
-
-    case SOUND_PCM_WRITE_CHANNELS:
-      val = *(int *) arg;
-      return (*(int *) arg = pcm_set_channels (val));
-      break;
-
-    case SOUND_PCM_READ_CHANNELS:
-      return (*(int *) arg = pcm_channels);
-      break;
-
-    case SNDCTL_DSP_SETFMT:
-      val = *(int *) arg;
-      return (*(int *) arg = pcm_set_bits (val));
-      break;
-
-    case SOUND_PCM_READ_BITS:
-      return (*(int *) arg = pcm_bits);
-
-    default:
-      return -EINVAL;
-    }
+	switch (cmd)
+	  {
+	  case SOUND_PCM_WRITE_RATE:
+		  val = *(int *) arg;
+		  return (*(int *) arg = pcm_set_speed(val));
+		  break;
+
+	  case SOUND_PCM_READ_RATE:
+		  return (*(int *) arg = pcm_speed);
+		  break;
+
+	  case SNDCTL_DSP_STEREO:
+		  val = *(int *) arg;
+		  return (*(int *) arg = pcm_set_channels(val + 1) - 1);
+		  break;
+
+	  case SOUND_PCM_WRITE_CHANNELS:
+		  val = *(int *) arg;
+		  return (*(int *) arg = pcm_set_channels(val));
+		  break;
+
+	  case SOUND_PCM_READ_CHANNELS:
+		  return (*(int *) arg = pcm_channels);
+		  break;
+
+	  case SNDCTL_DSP_SETFMT:
+		  val = *(int *) arg;
+		  return (*(int *) arg = pcm_set_bits(val));
+		  break;
+
+	  case SOUND_PCM_READ_BITS:
+		  return (*(int *) arg = pcm_bits);
+
+	  default:
+		  return -EINVAL;
+	  }
 
-  return -EINVAL;
+	return -EINVAL;
 }
 
 static void
-pas_audio_reset (int dev)
+pas_audio_reset(int dev)
 {
-  DEB (printk ("pas2_pcm.c: static void pas_audio_reset(void)\n"));
+	DEB(printk("pas2_pcm.c: static void pas_audio_reset(void)\n"));
 
-  pas_write (pas_read (0xF8A) & ~0x40, 0xF8A);	/* Disable PCM */
+	pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);	/* Disable PCM */
 }
 
 static int
-pas_audio_open (int dev, int mode)
+pas_audio_open(int dev, int mode)
 {
-  int             err;
-  unsigned long   flags;
-
-  DEB (printk ("pas2_pcm.c: static int pas_audio_open(int mode = %X)\n", mode));
+	int             err;
+	unsigned long   flags;
 
-  save_flags (flags);
-  cli ();
-  if (pcm_busy)
-    {
-      restore_flags (flags);
-      return -EBUSY;
-    }
+	DEB(printk("pas2_pcm.c: static int pas_audio_open(int mode = %X)\n", mode));
 
-  pcm_busy = 1;
-  restore_flags (flags);
+	save_flags(flags);
+	cli();
+	if (pcm_busy)
+	  {
+		  restore_flags(flags);
+		  return -EBUSY;
+	  }
+	pcm_busy = 1;
+	restore_flags(flags);
 
-  if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0)
-    return err;
+	if ((err = pas_set_intr(PAS_PCM_INTRBITS)) < 0)
+		return err;
 
 
-  pcm_count = 0;
-  open_mode = mode;
+	pcm_count = 0;
+	open_mode = mode;
 
-  return 0;
+	return 0;
 }
 
 static void
-pas_audio_close (int dev)
+pas_audio_close(int dev)
 {
-  unsigned long   flags;
+	unsigned long   flags;
 
-  DEB (printk ("pas2_pcm.c: static void pas_audio_close(void)\n"));
+	DEB(printk("pas2_pcm.c: static void pas_audio_close(void)\n"));
 
-  save_flags (flags);
-  cli ();
+	save_flags(flags);
+	cli();
 
-  pas_audio_reset (dev);
-  pas_remove_intr (PAS_PCM_INTRBITS);
-  pcm_mode = PCM_NON;
+	pas_audio_reset(dev);
+	pas_remove_intr(PAS_PCM_INTRBITS);
+	pcm_mode = PCM_NON;
 
-  pcm_busy = 0;
-  restore_flags (flags);
+	pcm_busy = 0;
+	restore_flags(flags);
 }
 
 static void
-pas_audio_output_block (int dev, unsigned long buf, int count,
-			int intrflag)
+pas_audio_output_block(int dev, unsigned long buf, int count,
+		       int intrflag)
 {
-  unsigned long   flags, cnt;
+	unsigned long   flags, cnt;
 
-  DEB (printk ("pas2_pcm.c: static void pas_audio_output_block(char *buf = %P, int count = %X)\n", buf, count));
+	DEB(printk("pas2_pcm.c: static void pas_audio_output_block(char *buf = %P, int count = %X)\n", buf, count));
 
-  cnt = count;
-  if (audio_devs[dev]->dmap_out->dma > 3)
-    cnt >>= 1;
+	cnt = count;
+	if (audio_devs[dev]->dmap_out->dma > 3)
+		cnt >>= 1;
 
-  if (audio_devs[dev]->flags & DMA_AUTOMODE &&
-      intrflag &&
-      cnt == pcm_count)
-    return;
+	if (audio_devs[dev]->flags & DMA_AUTOMODE &&
+	    intrflag &&
+	    cnt == pcm_count)
+		return;
 
-  save_flags (flags);
-  cli ();
+	save_flags(flags);
+	cli();
 
-  pas_write (pas_read (0xF8A) & ~0x40,
-	     0xF8A);
+	pas_write(pas_read(0xF8A) & ~0x40,
+		  0xF8A);
 
-  /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
+	/* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
 
-  if (audio_devs[dev]->dmap_out->dma > 3)
-    count >>= 1;
+	if (audio_devs[dev]->dmap_out->dma > 3)
+		count >>= 1;
 
-  if (count != pcm_count)
-    {
-      pas_write (pas_read (0x0B8A) & ~0x80, 0x0B8A);
-      pas_write (0x40 | 0x30 | 0x04, 0x138B);
-      pas_write (count & 0xff, 0x1389);
-      pas_write ((count >> 8) & 0xff, 0x1389);
-      pas_write (pas_read (0x0B8A) | 0x80, 0x0B8A);
+	if (count != pcm_count)
+	  {
+		  pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
+		  pas_write(0x40 | 0x30 | 0x04, 0x138B);
+		  pas_write(count & 0xff, 0x1389);
+		  pas_write((count >> 8) & 0xff, 0x1389);
+		  pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
 
-      pcm_count = count;
-    }
-  pas_write (pas_read (0x0B8A) | 0x80 | 0x40, 0x0B8A);
+		  pcm_count = count;
+	  }
+	pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
 #ifdef NO_TRIGGER
-  pas_write (pas_read (0xF8A) | 0x40 | 0x10, 0xF8A);
+	pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
 #endif
 
-  pcm_mode = PCM_DAC;
+	pcm_mode = PCM_DAC;
 
-  restore_flags (flags);
+	restore_flags(flags);
 }
 
 static void
-pas_audio_start_input (int dev, unsigned long buf, int count,
-		       int intrflag)
+pas_audio_start_input(int dev, unsigned long buf, int count,
+		      int intrflag)
 {
-  unsigned long   flags;
-  int             cnt;
+	unsigned long   flags;
+	int             cnt;
 
-  DEB (printk ("pas2_pcm.c: static void pas_audio_start_input(char *buf = %P, int count = %X)\n", buf, count));
+	DEB(printk("pas2_pcm.c: static void pas_audio_start_input(char *buf = %P, int count = %X)\n", buf, count));
 
-  cnt = count;
-  if (audio_devs[dev]->dmap_out->dma > 3)
-    cnt >>= 1;
-
-  if (audio_devs[pas_audiodev]->flags & DMA_AUTOMODE &&
-      intrflag &&
-      cnt == pcm_count)
-    return;
-
-  save_flags (flags);
-  cli ();
-
-  /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
-
-  if (audio_devs[dev]->dmap_out->dma > 3)
-    count >>= 1;
-
-  if (count != pcm_count)
-    {
-      pas_write (pas_read (0x0B8A) & ~0x80, 0x0B8A);
-      pas_write (0x40 | 0x30 | 0x04, 0x138B);
-      pas_write (count & 0xff, 0x1389);
-      pas_write ((count >> 8) & 0xff, 0x1389);
-      pas_write (pas_read (0x0B8A) | 0x80, 0x0B8A);
-
-      pcm_count = count;
-    }
-  pas_write (pas_read (0x0B8A) | 0x80 | 0x40, 0x0B8A);
+	cnt = count;
+	if (audio_devs[dev]->dmap_out->dma > 3)
+		cnt >>= 1;
+
+	if (audio_devs[pas_audiodev]->flags & DMA_AUTOMODE &&
+	    intrflag &&
+	    cnt == pcm_count)
+		return;
+
+	save_flags(flags);
+	cli();
+
+	/* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
+
+	if (audio_devs[dev]->dmap_out->dma > 3)
+		count >>= 1;
+
+	if (count != pcm_count)
+	  {
+		  pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
+		  pas_write(0x40 | 0x30 | 0x04, 0x138B);
+		  pas_write(count & 0xff, 0x1389);
+		  pas_write((count >> 8) & 0xff, 0x1389);
+		  pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
+
+		  pcm_count = count;
+	  }
+	pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
 #ifdef NO_TRIGGER
-  pas_write ((pas_read (0xF8A) | 0x40) & ~0x10, 0xF8A);
+	pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
 #endif
 
-  pcm_mode = PCM_ADC;
+	pcm_mode = PCM_ADC;
 
-  restore_flags (flags);
+	restore_flags(flags);
 }
 
 #ifndef NO_TRIGGER
 static void
-pas_audio_trigger (int dev, int state)
+pas_audio_trigger(int dev, int state)
 {
-  unsigned long   flags;
+	unsigned long   flags;
 
-  save_flags (flags);
-  cli ();
-  state &= open_mode;
-
-  if (state & PCM_ENABLE_OUTPUT)
-    pas_write (pas_read (0xF8A) | 0x40 | 0x10, 0xF8A);
-  else if (state & PCM_ENABLE_INPUT)
-    pas_write ((pas_read (0xF8A) | 0x40) & ~0x10, 0xF8A);
-  else
-    pas_write (pas_read (0xF8A) & ~0x40, 0xF8A);
+	save_flags(flags);
+	cli();
+	state &= open_mode;
+
+	if (state & PCM_ENABLE_OUTPUT)
+		pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
+	else if (state & PCM_ENABLE_INPUT)
+		pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
+	else
+		pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
 
-  restore_flags (flags);
+	restore_flags(flags);
 }
 #endif
 
 static int
-pas_audio_prepare_for_input (int dev, int bsize, int bcount)
+pas_audio_prepare_for_input(int dev, int bsize, int bcount)
 {
-  pas_audio_reset (dev);
-  return 0;
+	pas_audio_reset(dev);
+	return 0;
 }
 
 static int
-pas_audio_prepare_for_output (int dev, int bsize, int bcount)
+pas_audio_prepare_for_output(int dev, int bsize, int bcount)
 {
-  pas_audio_reset (dev);
-  return 0;
+	pas_audio_reset(dev);
+	return 0;
 }
 
 static struct audio_driver pas_audio_driver =
 {
-  pas_audio_open,
-  pas_audio_close,
-  pas_audio_output_block,
-  pas_audio_start_input,
-  pas_audio_ioctl,
-  pas_audio_prepare_for_input,
-  pas_audio_prepare_for_output,
-  pas_audio_reset,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  pas_audio_trigger
+	pas_audio_open,
+	pas_audio_close,
+	pas_audio_output_block,
+	pas_audio_start_input,
+	pas_audio_ioctl,
+	pas_audio_prepare_for_input,
+	pas_audio_prepare_for_output,
+	pas_audio_reset,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	pas_audio_trigger
 };
 
 void
-pas_pcm_init (struct address_info *hw_config)
+pas_pcm_init(struct address_info *hw_config)
 {
-  DEB (printk ("pas2_pcm.c: long pas_pcm_init()\n"));
+	DEB(printk("pas2_pcm.c: long pas_pcm_init()\n"));
 
-  pcm_bitsok = 8;
-  if (pas_read (0xEF8B) & 0x08)
-    pcm_bitsok |= 16;
-
-  pcm_set_speed (DSP_DEFAULT_SPEED);
-
-  if (num_audiodevs < MAX_AUDIO_DEV)
-    {
-
-      if ((pas_audiodev = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
-						  "Pro Audio Spectrum",
-						  &pas_audio_driver,
-					       sizeof (struct audio_driver),
-						  DMA_AUTOMODE,
-						  AFMT_U8 | AFMT_S16_LE,
-						  NULL,
-						  hw_config->dma,
-						  hw_config->dma)) < 0)
-	{
-	  return;
-	}
-    }
-  else
-    printk ("PAS16: Too many PCM devices available\n");
+	pcm_bitsok = 8;
+	if (pas_read(0xEF8B) & 0x08)
+		pcm_bitsok |= 16;
+
+	pcm_set_speed(DSP_DEFAULT_SPEED);
+
+	if ((pas_audiodev = sound_alloc_audiodev()) != -1)
+	  {
+
+		  if ((pas_audiodev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
+						    "Pro Audio Spectrum",
+						       &pas_audio_driver,
+					     sizeof(struct audio_driver),
+							     DMA_AUTOMODE,
+						   AFMT_U8 | AFMT_S16_LE,
+							     NULL,
+							  hw_config->dma,
+						    hw_config->dma)) < 0)
+		    {
+			    return;
+		    }
+	} else
+		printk(KERN_WARNING "PAS16: Too many PCM devices available\n");
 }
 
 void
-pas_pcm_interrupt (unsigned char status, int cause)
+pas_pcm_interrupt(unsigned char status, int cause)
 {
-  if (cause == 1)
-    {
-      /*
-       * Halt the PCM first. Otherwise we don't have time to start a new
-       * block before the PCM chip proceeds to the next sample
-       */
-
-      if (!(audio_devs[pas_audiodev]->flags & DMA_AUTOMODE))
-	{
-	  pas_write (pas_read (0xF8A) & ~0x40,
-		     0xF8A);
-	}
-
-      switch (pcm_mode)
-	{
-
-	case PCM_DAC:
-	  DMAbuf_outputintr (pas_audiodev, 1);
-	  break;
-
-	case PCM_ADC:
-	  DMAbuf_inputintr (pas_audiodev);
-	  break;
-
-	default:
-	  printk ("PAS: Unexpected PCM interrupt\n");
-	}
-    }
+	if (cause == 1)
+	  {
+		  /*
+		   * Halt the PCM first. Otherwise we don't have time to start a new
+		   * block before the PCM chip proceeds to the next sample
+		   */
+
+		  if (!(audio_devs[pas_audiodev]->flags & DMA_AUTOMODE))
+		    {
+			    pas_write(pas_read(0xF8A) & ~0x40,
+				      0xF8A);
+		    }
+		  switch (pcm_mode)
+		    {
+
+		    case PCM_DAC:
+			    DMAbuf_outputintr(pas_audiodev, 1);
+			    break;
+
+		    case PCM_ADC:
+			    DMAbuf_inputintr(pas_audiodev);
+			    break;
+
+		    default:
+			    printk("PAS: Unexpected PCM interrupt\n");
+		    }
+	  }
 }
 
-#endif
 #endif

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