Пример #1
0
/* Send a data block via Ethernet. */
static int ax88180_send(struct eth_device *dev, void *packet, int length)
{
	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
	unsigned short TXDES_addr;
	unsigned short txcmd_txdp, txbs_txdp;
	unsigned short tmp_data;
	int i;
#if defined (CONFIG_DRIVER_AX88180_16BIT)
	volatile unsigned short *txdata = (volatile unsigned short *)packet;
#else
	volatile unsigned long *txdata = (volatile unsigned long *)packet;
#endif
	unsigned short count;

	if (priv->LinkState != INS_LINK_UP) {
		return 0;
	}

	priv->FirstTxDesc = priv->NextTxDesc;
	txbs_txdp = 1 << priv->FirstTxDesc;

	debug ("ax88180: TXDP%d is available\n", priv->FirstTxDesc);

	txcmd_txdp = priv->FirstTxDesc << 13;
	TXDES_addr = TXDES0 + (priv->FirstTxDesc << 2);

	OUTW (dev, (txcmd_txdp | length | TX_START_WRITE), TXCMD);

	/* Comput access times */
	count = (length + priv->PadSize) >> priv->BusWidth;

	for (i = 0; i < count; i++) {
		WRITE_TXBUF (dev, *(txdata + i));
	}

	OUTW (dev, txcmd_txdp | length, TXCMD);
	OUTW (dev, txbs_txdp, TXBS);
	OUTW (dev, (TXDPx_ENABLE | length), TXDES_addr);

	priv->NextTxDesc = (priv->NextTxDesc + 1) & TXDP_MASK;

	/*
	 * Check the available transmit descriptor, if we had exhausted all
	 * transmit descriptor ,then we have to wait for at least one free
	 * descriptor
	 */
	txbs_txdp = 1 << priv->NextTxDesc;
	tmp_data = INW (dev, TXBS);

	if (tmp_data & txbs_txdp) {
		if (ax88180_poll_tx_complete (dev) < 0) {
			ax88180_mac_reset (dev);
			priv->FirstTxDesc = TXDP0;
			priv->NextTxDesc = TXDP0;
			printf ("ax88180: Transmit time out occurred!\n");
		}
	}

	return 0;
}
/*ARGSUSED*/
static int
fm801_audio_prepare_for_output (int dev, int bsize, int bcount)
{
  fm801_devc *devc = audio_engines[dev]->devc;
  fm801_portc *portc = audio_engines[dev]->portc;
  dmap_t *dmap = audio_engines[dev]->dmap_out;
  unsigned short value;
  unsigned char frequency;
  oss_native_word flags;
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
  value = 0x0000;
  if (portc->channels > 1)
    value |= 0x8000;
  if (portc->bits == 16)
    value |= 0x4000;
  frequency = sampling_rate (portc->speed);
  value |= (frequency << 8);
  if (portc->channels == 4)
    value |= (1 << 12);		/* 4channel output */
  if (portc->channels == 6)
    value |= (1 << 13);		/* 6channel output */
  OUTW (devc->osdev, value, devc->base + PLAY_CONTROL);
  OUTW (devc->osdev, dmap->fragment_size - 1, devc->base + PLAY_SIZE);
  OUTL (devc->osdev, dmap->dmabuf_phys, devc->base + PLAY_BUF1_ADDR);
  OUTL (devc->osdev, dmap->dmabuf_phys + dmap->fragment_size,
	devc->base + PLAY_BUF2_ADDR);
  devc->play_flag = 1;
  devc->play_count = 1;
  portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
  portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
  return 0;
}
Пример #3
0
static void ax88180_mac_reset (struct eth_device *dev)
{
	unsigned long tmpval;
	unsigned char i;

	struct {
		unsigned short offset, value;
	} program_seq[] = {
		{
		MISC, MISC_NORMAL}, {
		RXINDICATOR, DEFAULT_RXINDICATOR}, {
		TXCMD, DEFAULT_TXCMD}, {
		TXBS, DEFAULT_TXBS}, {
		TXDES0, DEFAULT_TXDES0}, {
		TXDES1, DEFAULT_TXDES1}, {
		TXDES2, DEFAULT_TXDES2}, {
		TXDES3, DEFAULT_TXDES3}, {
		TXCFG, DEFAULT_TXCFG}, {
		MACCFG2, DEFAULT_MACCFG2}, {
		MACCFG3, DEFAULT_MACCFG3}, {
		TXLEN, DEFAULT_TXLEN}, {
		RXBTHD0, DEFAULT_RXBTHD0}, {
		RXBTHD1, DEFAULT_RXBTHD1}, {
		RXFULTHD, DEFAULT_RXFULTHD}, {
		DOGTHD0, DEFAULT_DOGTHD0}, {
	DOGTHD1, DEFAULT_DOGTHD1},};

	OUTW (dev, MISC_RESET_MAC, MISC);
	tmpval = INW (dev, MISC);

	for (i = 0; i < ARRAY_SIZE(program_seq); i++)
		OUTW (dev, program_seq[i].value, program_seq[i].offset);
}
Пример #4
0
static void
ax88180_mdio_write (struct eth_device *dev, unsigned long regaddr,
		    unsigned short regdata)
{
	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;

	OUTW (dev, regdata, MDIODP);

	OUTW (dev, (WRITE_PHY | (regaddr << 8) | priv->PhyAddr), MDIOCTRL);

	if (!ax88180_mdio_check_complete (dev))
		printf ("Failed to write PHY register!\n");
}
Пример #5
0
/* Get a data block via Ethernet */
static int ax88180_recv (struct eth_device *dev)
{
	unsigned short ISR_Status;
	unsigned short tmp_regval;

	/* Read and check interrupt status here. */
	ISR_Status = INW (dev, ISR);

	while (ISR_Status) {
		/* Clear the interrupt status */
		OUTW (dev, ISR_Status, ISR);

		debug ("\nax88180: The interrupt status = 0x%04x\n",
		       ISR_Status);

		if (ISR_Status & ISR_PHY) {
			/* Read ISR register once to clear PHY interrupt bit */
			tmp_regval = ax88180_mdio_read (dev, M88_ISR);
			ax88180_media_config (dev);
		}

		if ((ISR_Status & ISR_RX) || (ISR_Status & ISR_RXBUFFOVR)) {
			ax88180_rx_handler (dev);
		}

		/* Read and check interrupt status again */
		ISR_Status = INW (dev, ISR);
	}

	return 0;
}
Пример #6
0
static void ax88180_read_mac_addr (struct eth_device *dev)
{
	unsigned short macid0_val, macid1_val, macid2_val;
	unsigned short tmp_regval;
	unsigned short i;

	/* Reload MAC address from EEPROM */
	OUTW (dev, RELOAD_EEPROM, PROMCTRL);

	/* Waiting for reload eeprom completion */
	for (i = 0; i < 500; i++) {
		tmp_regval = INW (dev, PROMCTRL);
		if ((tmp_regval & RELOAD_EEPROM) == 0)
			break;
		udelay (1000);
	}

	/* Get MAC addresses */
	macid0_val = INW (dev, MACID0);
	macid1_val = INW (dev, MACID1);
	macid2_val = INW (dev, MACID2);

	if (((macid0_val | macid1_val | macid2_val) != 0) &&
	    ((macid0_val & 0x01) == 0)) {
		dev->enetaddr[0] = (unsigned char)macid0_val;
		dev->enetaddr[1] = (unsigned char)(macid0_val >> 8);
		dev->enetaddr[2] = (unsigned char)macid1_val;
		dev->enetaddr[3] = (unsigned char)(macid1_val >> 8);
		dev->enetaddr[4] = (unsigned char)macid2_val;
		dev->enetaddr[5] = (unsigned char)(macid2_val >> 8);
	}
Пример #7
0
void
cons_init(void)
{
	int rate;

	OUTW(SSCOM_UCON, 0);
	OUTB(SSCOM_UFCON, UFCON_TXTRIGGER_8 | UFCON_RXTRIGGER_8 |
	    UFCON_TXFIFO_RESET | UFCON_RXFIFO_RESET |
	    UFCON_FIFO_ENABLE);

	rate = sscomspeed(CONSPEED);
	OUTW(SSCOM_UBRDIV, rate);
	OUTW(SSCOM_ULCON, ULCON_PARITY_NONE|ULCON_LENGTH_8);

	/* enable UART */
	OUTW(SSCOM_UCON, UCON_TXMODE_INT|UCON_RXMODE_INT);
	OUTW(SSCOM_UMCON, UMCON_RTS);
}
static int
ac97_write2 (void *devc_, int index, int data)
{
  fm801_devc *devc = devc_;
  int idx;
  oss_native_word flags;
  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
  /*
   * Wait until the codec interface is ready..
   */
  for (idx = 0; idx < 10000; idx++)
    {
      if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)))
	break;
      oss_udelay (10);
    }
  if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))
    {
      DDB (cmn_err (CE_WARN, "Secondary AC97 busy\n"));
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
      return OSS_EIO;
    }
  /* write data and address */
  OUTW (devc->osdev, data, devc->base + AC97_DATA);
  OUTW (devc->osdev, index | (0x1 << 10), devc->base + AC97_CMD);
  /*
   * Wait until the write command is completed..
   */
  for (idx = 0; idx < 1000; idx++)
    {
      if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)))
	break;
      oss_udelay (10);
    }
  if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))
    {
      DDB (cmn_err (CE_WARN, "Secondary AC97 busy (1)\n"));
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
      return OSS_EIO;
    }
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
  return 0;
}
static int
ac97_read2 (void *devc_, int index)
{
  fm801_devc *devc = devc_;
  int idx;
  oss_native_word flags;
  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
  /*
   * Wait until the codec interface is not ready..
   */
  for (idx = 0; idx < 10000; idx++)
    {
      if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)))
	break;
      oss_udelay (10);
    }
  if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))
    {
      DDB (cmn_err (CE_WARN, "Secondary AC97 (read) not ready (1)\n"));
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
      return 0;
    }
  /* read command */
  OUTW (devc->osdev, index | (0x1 << 10) | (1 << 7), devc->base + AC97_CMD);
  for (idx = 0; idx < 10000; idx++)
    {
      if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)))
	break;
      oss_udelay (10);
    }
  /*
   * Wait until the codec interface is not ready..
   */
  if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))
    {
      DDB (cmn_err (CE_WARN, "Secondary AC97 (read) not ready(2)\n"));
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
      return 0;
    }
  for (idx = 0; idx < 10000; idx++)
    {
      if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 8))
	break;
      oss_udelay (10);
    }
  if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 8)))
    {
      cmn_err (CE_WARN, "Secondary AC97 (read) data not valid (2)\n");
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
      return 0;
    }
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
  return INW (devc->osdev, devc->base + AC97_DATA);
}
Пример #10
0
static void
ns8382x_init_rxfilter(struct eth_device *dev)
{
	int i;

	for (i = 0; i < ETH_ALEN; i += 2) {
		OUTL(dev, i, RxFilterAddr);
		OUTW(dev, dev->enetaddr[i] + (dev->enetaddr[i + 1] << 8),
		     RxFilterData);
	}
}
static void
uninit_audio (fm801_devc * devc)
{
  unsigned int irqmask;
  devc->audio_initialized = 0;
#ifndef _TRU64_UNIX
  /* interrupt setup - mask MPU, PLAYBACK & CAPTURE */
  irqmask = INW (devc->osdev, devc->base + IRQ_MASK);
  irqmask |= 0x00C3;
  OUTW (devc->osdev, irqmask, devc->base + IRQ_MASK);
  pci_write_config_word (devc->osdev, 0x40, 0x807F);
#endif
}
Пример #12
0
Файл: sonypi.c Проект: emon/emon
/* disable the SPIC - this comes from the AML code in the ACPI bios */
static void spic_dis(void)
{
	u8 v1;
	u16 v;

	pci_config_read_u8(spic_fd, SPI_G10L, &v1);
	pci_config_write_u8(spic_fd, SPI_G10L, v1 & 0x3F);

	v = inw(SPI_IRQ_PORT);
	v |= (0x3 << SPI_IRQ_SHIFT);
	OUTW(v, SPI_IRQ_PORT);
	close(spic_fd);
}
Пример #13
0
int sb700_acpi_init(void)
{
	unsigned int temp32;
	int loop;
	unsigned int PM_IO_BASE;
	device_t acpi_tag;
	acpi_tag = _pci_make_tag(0, 20, 0);
	PM_IO_BASE = _pci_conf_read(acpi_tag, 0x9c);
	/* pm1 base */
	pm_iowrite(0x22, ACPI_PM1_CNT_BLK & 0xff);
	pm_iowrite(0x23, ACPI_PM1_CNT_BLK >> 8);

	/* gpm base */
	pm_iowrite(0x28, ACPI_GPE0_BLK & 0xFF);
	pm_iowrite(0x29, ACPI_GPE0_BLK >> 8);

	/* gpm base */
	pm_iowrite(0x2e, ACPI_END & 0xFF);
	pm_iowrite(0x2f, ACPI_END >> 8);

	/* io decode */
	pm_iowrite(0x0E, 1<<3 | 0<<2); /* AcpiDecodeEnable, When set, SB uses
									* the contents of the PM registers at
									* index 20-2B to decode ACPI I/O address.
									* AcpiSmiEn & SmiCmdEn
									*/
	/* SLP_SMI_EN */
	pmio_enable_bits(0x04,0x1<<7,0x00);
	/* SlpS3ToLdtPwrGdEn */
	pmio_enable_bits(0x41,0x1<<3,0x1<<3);
	/* LongSlpS3 */
	pmio_enable_bits(0x8d,0x1<<5,0x1<<5);

	/* SCI_EN set P225 */
	OUTW(1, ACPI_PM1_CNT_BLK);
	OUTW(5<<10,ACPI_PM1_CNT_BLK);
	OUTW(1<<13,ACPI_PM1_CNT_BLK);
}
static int
ac97_write (void *devc_, int addr, int data)
{
  oss_native_word flags;
  allegro_devc *devc = devc_;
#if 0
  int i;

  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
  for (i = 0; i < 1000; i++)
    if (!(INB (devc->osdev, devc->base + 0x30) & 0x01))
      break;
  OUTW (devc->osdev, data & 0xffff, devc->base + 0x32);
  oss_udelay (100);
  OUTW (devc->osdev, (addr & 0x7f) & ~0x80, devc->base + 0x30);
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
#else
  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
  HWMGR_WriteCodecData (devc, (UCHAR) addr, data);
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
#endif
  return 0;
}
Пример #15
0
static unsigned short
ax88180_mdio_read (struct eth_device *dev, unsigned long regaddr)
{
	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
	unsigned long tmpval = 0;

	OUTW (dev, (READ_PHY | (regaddr << 8) | priv->PhyAddr), MDIOCTRL);

	if (ax88180_mdio_check_complete (dev))
		tmpval = INW (dev, MDIODP);
	else
		printf ("Failed to read PHY register!\n");

	return (unsigned short)(tmpval & 0xFFFF);
}
Пример #16
0
static int ax88180_init (struct eth_device *dev, bd_t * bd)
{
	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
	unsigned short tmp_regval;

	ax88180_mac_reset (dev);

	/* Disable interrupt */
	OUTW (dev, CLEAR_IMR, IMR);

	/* Disable AX88180 TX/RX functions */
	OUTW (dev, WAKEMOD, CMD);

	/* Fill the MAC address */
	tmp_regval =
	    dev->enetaddr[0] | (((unsigned short)dev->enetaddr[1]) << 8);
	OUTW (dev, tmp_regval, MACID0);

	tmp_regval =
	    dev->enetaddr[2] | (((unsigned short)dev->enetaddr[3]) << 8);
	OUTW (dev, tmp_regval, MACID1);

	tmp_regval =
	    dev->enetaddr[4] | (((unsigned short)dev->enetaddr[5]) << 8);
	OUTW (dev, tmp_regval, MACID2);

	ax88180_media_config (dev);

	OUTW (dev, DEFAULT_RXFILTER, RXFILTER);

	/* Initial variables here */
	priv->FirstTxDesc = TXDP0;
	priv->NextTxDesc = TXDP0;

	/* Check if there is any invalid interrupt status and clear it. */
	OUTW (dev, INW (dev, ISR), ISR);

	/* Start AX88180 TX/RX functions */
	OUTW (dev, (RXEN | TXEN | WAKEMOD), CMD);

	return 0;
}
Пример #17
0
Файл: sonypi.c Проект: emon/emon
/* initialise the SPIC - this comes from the AML code in the ACPI bios */
static void spic_srs(int fd, u16 port1, u16 port2, u8 irq)
{
	u8 v;
	u16 v2;

	pci_config_write_u16(fd, SPI_G10A, port1);
	pci_config_read_u8(fd, SPI_G10L, &v);
	v = (v & 0xF0) | (port1 ^ port2);
	pci_config_write_u8(fd, SPI_G10L, v);

	v2 = inw(SPI_IRQ_PORT);
	v2 &= ~(0x3 << SPI_IRQ_SHIFT);
	v2 |= (irq << SPI_IRQ_SHIFT);
	OUTW(v2, SPI_IRQ_PORT);

	pci_config_read_u8(fd, SPI_G10L, &v);
	v = (v & 0x1F) | 0xC0;
	pci_config_write_u8(fd, SPI_G10L, v);
}
static int
ac97_read (void *devc_, int addr)
{
  allegro_devc *devc = devc_;
  oss_native_word flags;
  unsigned short data;
#if 0
  int i;
  int sanity = 10000;

  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
  for (i = 0; i < 100000; i++)
    if (!(INB (devc->osdev, devc->base + 0x30) & 0x01))
      break;
  OUTW (devc->osdev, addr | 0x80, devc->base + 0x30);

  while (INB (devc->osdev, devc->base + 0x30) & 1)
    {
      sanity--;
      if (!sanity)
	{
	  cmn_err (CE_WARN, "ac97 codec timeout - 0x%x.\n", addr);
	  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
	  return 0;
	}
    }

  data = INW (devc->osdev, devc->base + 0x32);
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
#else
  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
  HWMGR_ReadCodecData (devc, (UCHAR) addr, &data);
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
#endif
  return data;
}
static void
fm801_audio_trigger (int dev, int state)
{
  fm801_portc *portc = audio_engines[dev]->portc;
  fm801_devc *devc = audio_engines[dev]->devc;
  oss_native_word flags;
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
  if (portc->open_mode & OPEN_WRITE)
    {
      if (state & PCM_ENABLE_OUTPUT)
	{
	  if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
	      !(portc->trigger_bits & PCM_ENABLE_OUTPUT))
	    {
	      OUTW (devc->osdev,
		    INW (devc->osdev,
			 devc->base +
			 PLAY_CONTROL) | FM801_START | FM801_IMMED_STOP,
		    devc->base + PLAY_CONTROL);
	      portc->trigger_bits |= PCM_ENABLE_OUTPUT;
	    }
	}
      else
	{
	  if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
	      (portc->trigger_bits & PCM_ENABLE_OUTPUT))
	    {
	      portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
	      portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
	      OUTW (devc->osdev,
		    (INW (devc->osdev, devc->base + PLAY_CONTROL) &
		     (~FM801_START | FM801_IMMED_STOP)) | (FM801_BUF1_LAST |
							   FM801_BUF2_LAST),
		    devc->base + PLAY_CONTROL);
	    }
	}
    }
  if (portc->open_mode & OPEN_READ)
    {
      if (state & PCM_ENABLE_INPUT)
	{
	  if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
	      !(portc->trigger_bits & PCM_ENABLE_INPUT))
	    {
	      OUTW (devc->osdev, INW (devc->osdev, devc->base + REC_CONTROL) |
		    FM801_START | FM801_IMMED_STOP, devc->base + REC_CONTROL);
	      portc->trigger_bits |= PCM_ENABLE_INPUT;
	    }
	}
      else
	{
	  if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
	      (portc->trigger_bits & PCM_ENABLE_INPUT))
	    {
	      portc->audio_enabled &= ~PCM_ENABLE_INPUT;
	      portc->trigger_bits &= ~PCM_ENABLE_INPUT;
	      OUTW (devc->osdev,
		    (INW (devc->osdev, devc->base + REC_CONTROL) &
		     (~FM801_START | FM801_IMMED_STOP)) | (FM801_BUF1_LAST |
							   FM801_BUF2_LAST),
		    devc->base + REC_CONTROL);
	    }
	}
    }
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
}
Пример #20
0
Файл: sonypi.c Проект: emon/emon
void spic_setup_vga(void)
{
/* :about to start capture again
 */
OUTB(0x09, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000026 */
OUTW(0x2609, 0x03CE); usleep(10);
OUTB(0x0A, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000021 */
OUTW(0x210A, 0x03CE); usleep(10);
OUTB(0x08, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 00000020 */
OUTB(0x09, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 000000F3 */
OUTW(0x2008, 0x03C4); usleep(10);
OUTW(0xF309, 0x03C4); usleep(10);
OUTW(0x2609, 0x03CE); usleep(10);
OUTW(0x210A, 0x03CE); usleep(10);
OUTB(0x09, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000026 */
OUTW(0x2609, 0x03CE); usleep(10);
OUTB(0x0A, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000021 */
OUTW(0x210A, 0x03CE); usleep(10);
OUTB(0x08, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 00000020 */
OUTB(0x09, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 000000F3 */
OUTW(0xF109, 0x03C4); usleep(10);
OUTW(0x2609, 0x03CE); usleep(10);
OUTW(0x210A, 0x03CE); usleep(10);
OUTB(0x09, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000026 */
OUTW(0x2609, 0x03CE); usleep(10);
OUTB(0x0A, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000021 */
OUTW(0x210A, 0x03CE); usleep(10);
OUTB(0x08, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 00000020 */
OUTB(0x09, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 0000001F */
OUTW(0x1D09, 0x03C4); usleep(10);
OUTW(0x2609, 0x03CE); usleep(10);
OUTW(0x210A, 0x03CE); usleep(10);
OUTB(0x08, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 00002621 */
OUTB(0x09, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 000026E9 */
OUTB(0x08, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 00002621 */
OUTB(0x09, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 000026F9 */
OUTB(0x09, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000026 */
OUTB(0x09, 0x03CE); usleep(10);
OUTB(0x26, 0x03CF); usleep(10);
OUTB(0x0A, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000021 */
OUTB(0x0A, 0x03CE); usleep(10);
OUTB(0x21, 0x03CF); usleep(10);
OUTB(0x0F, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 00000001 */
OUTB(0x0F, 0x03C4); usleep(10);
OUTB(0x01, 0x03C5); usleep(10);
OUTB(0x0F, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 00000001 */
OUTB(0x0A, 0x03CE); usleep(10);
OUTB(0x21, 0x03CF); usleep(10);
OUTB(0x09, 0x03CE); usleep(10);
OUTB(0x26, 0x03CF); usleep(10);
OUTB(0x09, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000026 */
OUTW(0x2609, 0x03CE); usleep(10);
OUTB(0xBF, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000000 */
OUTB(0xA3, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 0000000C */
OUTW(0xBF, 0x03CE); usleep(10);
OUTW(0x0CA3, 0x03CE); usleep(10);
OUTB(0x09, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000026 */
OUTW(0x2609, 0x03CE); usleep(10);
OUTB(0x0A, 0x03CE); usleep(10);
inb(0x03CF); usleep(10); /* -> 00000021 */
OUTW(0x210A, 0x03CE); usleep(10);
OUTB(0x08, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 00000021 */
OUTB(0x09, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 000000F9 */
OUTW(0x2609, 0x03CE); usleep(10);
OUTW(0x210A, 0x03CE); usleep(10);
OUTB(0x08, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 00002621 */
OUTB(0x09, 0x03C4); usleep(10);
inb(0x03C5); usleep(10); /* -> 000026F9 */
Пример #21
0
void
atge_l1e_program_dma(atge_t *atgep)
{
	atge_l1e_data_t *l1e;
	uint64_t paddr;
	uint32_t reg;

	l1e = (atge_l1e_data_t *)atgep->atge_private_data;

	/*
	 * Clear WOL status and disable all WOL feature as WOL
	 * would interfere Rx operation under normal environments.
	 */
	(void) INL(atgep, ATGE_WOL_CFG);
	OUTL(atgep, ATGE_WOL_CFG, 0);

	/*
	 * Set Tx descriptor/RXF0/CMB base addresses. They share
	 * the same high address part of DMAable region.
	 */
	paddr = atgep->atge_tx_ring->r_desc_ring->cookie.dmac_laddress;
	OUTL(atgep, ATGE_DESC_ADDR_HI, ATGE_ADDR_HI(paddr));
	OUTL(atgep, ATGE_DESC_TPD_ADDR_LO, ATGE_ADDR_LO(paddr));
	OUTL(atgep, ATGE_DESC_TPD_CNT,
	    (L1E_TX_RING_CNT << DESC_TPD_CNT_SHIFT) & DESC_TPD_CNT_MASK);

	/* Set Rx page base address, note we use single queue. */
	paddr = l1e->atge_l1e_rx_page[0]->cookie.dmac_laddress;
	OUTL(atgep, L1E_RXF0_PAGE0_ADDR_LO, ATGE_ADDR_LO(paddr));
	paddr = l1e->atge_l1e_rx_page[1]->cookie.dmac_laddress;
	OUTL(atgep, L1E_RXF0_PAGE1_ADDR_LO, ATGE_ADDR_LO(paddr));

	/* Set Tx/Rx CMB addresses. */
	paddr = l1e->atge_l1e_rx_cmb->cookie.dmac_laddress;
	OUTL(atgep, L1E_RXF0_CMB0_ADDR_LO, ATGE_ADDR_LO(paddr));
	paddr = l1e->atge_l1e_rx_cmb->cookie.dmac_laddress + sizeof (uint32_t);
	OUTL(atgep, L1E_RXF0_CMB1_ADDR_LO, ATGE_ADDR_LO(paddr));

	/* Mark RXF0 valid. */
	OUTB(atgep, L1E_RXF0_PAGE0, RXF_VALID);	/* 0 */
	OUTB(atgep, L1E_RXF0_PAGE1, RXF_VALID);	/* 1 */
	OUTB(atgep, L1E_RXF0_PAGE0 + 2, 0);
	OUTB(atgep, L1E_RXF0_PAGE0 + 3, 0);
	OUTB(atgep, L1E_RXF0_PAGE0 + 4, 0);
	OUTB(atgep, L1E_RXF0_PAGE0 + 5, 0);
	OUTB(atgep, L1E_RXF0_PAGE0 + 6, 0);
	OUTB(atgep, L1E_RXF0_PAGE0 + 6, 0);

	/* Set Rx page size, excluding guard frame size. */
	OUTL(atgep, L1E_RXF_PAGE_SIZE, L1E_RX_PAGE_SZ);

	/* Tell hardware that we're ready to load DMA blocks. */
	OUTL(atgep, ATGE_DMA_BLOCK, DMA_BLOCK_LOAD);

	/* Set Rx/Tx interrupt trigger threshold. */
	OUTL(atgep, L1E_INT_TRIG_THRESH, (1 << INT_TRIG_RX_THRESH_SHIFT) |
	    (4 << INT_TRIG_TX_THRESH_SHIFT));

	/*
	 * Set interrupt trigger timer, its purpose and relation
	 * with interrupt moderation mechanism is not clear yet.
	 */
	OUTL(atgep, L1E_INT_TRIG_TIMER,
	    ((ATGE_USECS(10) << INT_TRIG_RX_TIMER_SHIFT) |
	    (ATGE_USECS(1000) << INT_TRIG_TX_TIMER_SHIFT)));

	reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT;
	reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) << IM_TIMER_TX_SHIFT;
	OUTL(atgep, ATGE_IM_TIMER, reg);

	reg = INL(atgep, ATGE_MASTER_CFG);
	reg &= ~(MASTER_CHIP_REV_MASK | MASTER_CHIP_ID_MASK);
	reg &= ~(MASTER_IM_RX_TIMER_ENB | MASTER_IM_TX_TIMER_ENB);
	reg |= MASTER_IM_RX_TIMER_ENB;
	reg |= MASTER_IM_TX_TIMER_ENB;
	OUTL(atgep, ATGE_MASTER_CFG, reg);

	OUTW(atgep, RX_COALSC_PKT_1e, 0);
	OUTW(atgep, RX_COALSC_TO_1e, 0);
	OUTW(atgep, TX_COALSC_PKT_1e, 1);
	OUTW(atgep, TX_COALSC_TO_1e, 4000/2);		/* 4mS */
}
Пример #22
0
void
main(void)
{
	char tmpbuf[256];
	int i, f, fpos = 0, block, cur, got, vol = 0xfff;
	char *buf = (void *) 0x80080000;

	fnames = malloc(MAX_FNAMES * 256);

	tmpbuf[0] = 'd';
	tmpbuf[1] = ':';
	tmpbuf[2] = 0;
	f = open(tmpbuf, O_RDONLY);
	if (f > 0)
		close(f);
	scan_files(tmpbuf);
	lcd_init();

next_file:
	f = open(fnames[fpos], O_RDONLY);
	if (f < 0) {
		printf("Open failed\n");
		exit (1);
	}
	printf("Playing %s, vol %d\n", fnames[fpos], vol);
	lcd_pos(0, 0);
	lcd_puts(&fnames[fpos][3]);
	lcd_puts("          ");

	block = 0;
	got = read(f, buf, 0x8000);
	OUTW(IO_PCM_FIRST, buf);
	OUTW(IO_PCM_LAST, buf + 0x7ffe);
	OUTW(IO_PCM_FREQ, 9108); /* 44.1 kHz sample rate */
	OUTW(IO_PCM_VOLUME, vol + (vol << 16));

	while (got > 0) {
		INW(cur, IO_PCM_CUR);
		if ((cur & 0x4000) != block) {
			got = read(f, buf + block, 0x4000);
			block = cur & 0x4000;
			INB(i, IO_PUSHBTN);
			if ((i & BTN_UP) && vol < 0xffff)
				vol = (vol << 1) + 1;
			if ((i & BTN_DOWN) && vol > 0)
				vol = vol >> 1;
			if ((i & (BTN_UP|BTN_DOWN)))
				printf("Playing %s, vol %d\n",
				    fnames[fpos], vol);
			lcd_pos(0, 1);
			sprintf(tmpbuf, "volume %d ", vol);
			lcd_puts(tmpbuf);
			OUTW(IO_PCM_VOLUME, vol + (vol << 16));
			if ((i & BTN_LEFT)) {
				close(f);
				if (fpos == 0)
					fpos = fcnt;
				fpos--;
				goto next_file;
			}
			if ((i & BTN_RIGHT))
				break;
		}
#ifdef __mips__
		/* Wait for an interrupt, but which one? - XXX REVISIT!!! */
		__asm __volatile__("wait");
#endif
	}
static int
allegrointr (oss_device_t * osdev)
{
  allegro_devc *devc = (allegro_devc *) osdev->devc;
  unsigned char bIntStatus;
  unsigned char bIntTimer = FALSE;
  unsigned int currdac, curradc, n, i;
  int serviced = 0;

  bIntStatus = INB (devc->osdev, devc->base + 0x1A);

  if (bIntStatus == 0xff)
    return 0;
  OUTW (devc->osdev, bIntStatus, devc->base + 0x1A);
  if (bIntStatus & ASSP_INT_PENDING)
    {
      unsigned char status;
      serviced = 1;

      status = INB (devc->osdev, (devc->base + ASSP_CONTROL_B));
      if ((status & STOP_ASSP_CLOCK) == 0)
	{
	  status = INB (devc->osdev, (devc->base + ASSP_HOST_INT_STATUS));

	  /* acknowledge other interrupts */
	  if (status & DSP2HOST_REQ_TIMER)
	    {
	      OUTB (devc->osdev, DSP2HOST_REQ_TIMER,
		    (devc->base + ASSP_HOST_INT_STATUS));
	      bIntTimer = TRUE;
	    }
	}
    }

  if (bIntStatus & 0x40)
    {
      serviced = 1;
      OUTB (devc->osdev, 0x40, devc->base + 0x1A);
    }

  if (bIntStatus & MPU401_INT_PENDING)
    {
      serviced = 1;
      uart401_irq (&devc->uart401devc);
    }

  if (!bIntTimer)
    return serviced;

  for (i = 0; i < MAX_PORTC; i++)
    {
      allegro_portc *portc = &devc->portc[i];
      if (portc->trigger_bits & PCM_ENABLE_OUTPUT)
	{
	  dmap_t *dmapout = audio_engines[portc->audiodev]->dmap_out;
	  currdac = GetPosition (devc, 1);
	  currdac /= dmapout->fragment_size;
	  n = 0;
	  while (dmap_get_qhead (dmapout) != currdac && n++ < dmapout->nfrags)
	    oss_audio_outputintr (portc->audiodev, 1);
	}
      if (portc->trigger_bits & PCM_ENABLE_INPUT)
	{
	  dmap_t *dmapin = audio_engines[portc->audiodev]->dmap_in;
	  curradc = GetPosition (devc, 0);
	  curradc /= dmapin->fragment_size;

	  n = 0;
	  while (dmap_get_qtail (dmapin) != curradc && n++ < dmapin->nfrags)
	    oss_audio_inputintr (portc->audiodev, 0);
	}
    }

  return serviced;
}
Пример #24
0
static void ax88180_halt (struct eth_device *dev)
{
	/* Disable AX88180 TX/RX functions */
	OUTW (dev, WAKEMOD, CMD);
}
Пример #25
0
static void ax88180_media_config (struct eth_device *dev)
{
	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
	unsigned long bmcr_val, bmsr_val;
	unsigned long rxcfg_val, maccfg0_val, maccfg1_val;
	unsigned long RealMediaMode;
	int i;

	/* Waiting 2 seconds for PHY link stable */
	for (i = 0; i < 20000; i++) {
		bmsr_val = ax88180_mdio_read (dev, MII_BMSR);
		if (bmsr_val & BMSR_LSTATUS) {
			break;
		}
		udelay (100);
	}

	bmsr_val = ax88180_mdio_read (dev, MII_BMSR);
	debug ("ax88180: BMSR=0x%04x\n", (unsigned int)bmsr_val);

	if (bmsr_val & BMSR_LSTATUS) {
		bmcr_val = ax88180_mdio_read (dev, MII_BMCR);

		if (bmcr_val & BMCR_ANENABLE) {

			/*
			 * Waiting for Auto-negotiation completion, this may
			 * take up to 5 seconds.
			 */
			debug ("ax88180: Auto-negotiation is "
			       "enabled. Waiting for NWay completion..\n");
			for (i = 0; i < 50000; i++) {
				bmsr_val = ax88180_mdio_read (dev, MII_BMSR);
				if (bmsr_val & BMSR_ANEGCOMPLETE) {
					break;
				}
				udelay (100);
			}
		} else
			debug ("ax88180: Auto-negotiation is disabled.\n");

		debug ("ax88180: BMCR=0x%04x, BMSR=0x%04x\n",
		       (unsigned int)bmcr_val, (unsigned int)bmsr_val);

		/* Get real media mode here */
		switch (priv->PhyID0) {
		case MARVELL_ALASKA_PHYSID0:
			RealMediaMode = get_MarvellPHY_media_mode(dev);
			break;
		case CICADA_CIS8201_PHYSID0:
			RealMediaMode = get_CicadaPHY_media_mode(dev);
			break;
		default:
			RealMediaMode = MEDIA_1000FULL;
			break;
		}

		priv->LinkState = INS_LINK_UP;

		switch (RealMediaMode) {
		case MEDIA_1000FULL:
			debug ("ax88180: 1000Mbps Full-duplex mode.\n");
			rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG;
			maccfg0_val = TXFLOW_ENABLE | DEFAULT_MACCFG0;
			maccfg1_val = GIGA_MODE_EN | RXFLOW_EN |
			    FULLDUPLEX | DEFAULT_MACCFG1;
			break;

		case MEDIA_1000HALF:
			debug ("ax88180: 1000Mbps Half-duplex mode.\n");
			rxcfg_val = DEFAULT_RXCFG;
			maccfg0_val = DEFAULT_MACCFG0;
			maccfg1_val = GIGA_MODE_EN | DEFAULT_MACCFG1;
			break;

		case MEDIA_100FULL:
			debug ("ax88180: 100Mbps Full-duplex mode.\n");
			rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG;
			maccfg0_val = SPEED100 | TXFLOW_ENABLE
			    | DEFAULT_MACCFG0;
			maccfg1_val = RXFLOW_EN | FULLDUPLEX | DEFAULT_MACCFG1;
			break;

		case MEDIA_100HALF:
			debug ("ax88180: 100Mbps Half-duplex mode.\n");
			rxcfg_val = DEFAULT_RXCFG;
			maccfg0_val = SPEED100 | DEFAULT_MACCFG0;
			maccfg1_val = DEFAULT_MACCFG1;
			break;

		case MEDIA_10FULL:
			debug ("ax88180: 10Mbps Full-duplex mode.\n");
			rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG;
			maccfg0_val = TXFLOW_ENABLE | DEFAULT_MACCFG0;
			maccfg1_val = RXFLOW_EN | FULLDUPLEX | DEFAULT_MACCFG1;
			break;

		case MEDIA_10HALF:
			debug ("ax88180: 10Mbps Half-duplex mode.\n");
			rxcfg_val = DEFAULT_RXCFG;
			maccfg0_val = DEFAULT_MACCFG0;
			maccfg1_val = DEFAULT_MACCFG1;
			break;
		default:
			debug ("ax88180: Unknow media mode.\n");
			rxcfg_val = DEFAULT_RXCFG;
			maccfg0_val = DEFAULT_MACCFG0;
			maccfg1_val = DEFAULT_MACCFG1;

			priv->LinkState = INS_LINK_DOWN;
			break;
		}

	} else {
		rxcfg_val = DEFAULT_RXCFG;
		maccfg0_val = DEFAULT_MACCFG0;
		maccfg1_val = DEFAULT_MACCFG1;

		priv->LinkState = INS_LINK_DOWN;
	}

	OUTW (dev, rxcfg_val, RXCFG);
	OUTW (dev, maccfg0_val, MACCFG0);
	OUTW (dev, maccfg1_val, MACCFG1);

	return;
}
Пример #26
0
static void ax88180_rx_handler (struct eth_device *dev)
{
	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
	unsigned long data_size;
	unsigned short rxcurt_ptr, rxbound_ptr, next_ptr;
	int i;
#if defined (CONFIG_DRIVER_AX88180_16BIT)
	unsigned short *rxdata = (unsigned short *)net_rx_packets[0];
#else
	unsigned long *rxdata = (unsigned long *)net_rx_packets[0];
#endif
	unsigned short count;

	rxcurt_ptr = INW (dev, RXCURT);
	rxbound_ptr = INW (dev, RXBOUND);
	next_ptr = (rxbound_ptr + 1) & RX_PAGE_NUM_MASK;

	debug ("ax88180: RX original RXBOUND=0x%04x,"
	       " RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);

	while (next_ptr != rxcurt_ptr) {

		OUTW (dev, RX_START_READ, RXINDICATOR);

		data_size = READ_RXBUF (dev) & 0xFFFF;

		if ((data_size == 0) || (data_size > MAX_RX_SIZE)) {

			OUTW (dev, RX_STOP_READ, RXINDICATOR);

			ax88180_mac_reset (dev);
			printf ("ax88180: Invalid Rx packet length!"
				" (len=0x%04lx)\n", data_size);

			debug ("ax88180: RX RXBOUND=0x%04x,"
			       "RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);
			return;
		}

		rxbound_ptr += (((data_size + 0xF) & 0xFFF0) >> 4) + 1;
		rxbound_ptr &= RX_PAGE_NUM_MASK;

		/* Comput access times */
		count = (data_size + priv->PadSize) >> priv->BusWidth;

		for (i = 0; i < count; i++) {
			*(rxdata + i) = READ_RXBUF (dev);
		}

		OUTW (dev, RX_STOP_READ, RXINDICATOR);

		/* Pass the packet up to the protocol layers. */
		net_process_received_packet(net_rx_packets[0], data_size);

		OUTW (dev, rxbound_ptr, RXBOUND);

		rxcurt_ptr = INW (dev, RXCURT);
		rxbound_ptr = INW (dev, RXBOUND);
		next_ptr = (rxbound_ptr + 1) & RX_PAGE_NUM_MASK;

		debug ("ax88180: RX updated RXBOUND=0x%04x,"
		       "RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);
	}

	return;
}
static int
init_fm801 (fm801_devc * devc)
{
  int my_mixer, my_mixer2;
  int legacy;
  int irqmask;
  int adev;
  int first_dev = 0;
  int i;

  devc->mpu_attached = devc->fm_attached = 0;

  legacy = 0;

#if !defined(__hpux) && !defined(sparc) && !defined(_TRU64)
  /* Enable Legacy FM, MPU and Joystick ports */
  legacy = 0x001E;
  switch (fmedia_mpu_irq)
    {
    case 5:
      legacy |= 0x0000;
      break;
    case 7:
      legacy |= 0x0800;
      break;
    case 9:
      legacy |= 0x1000;
      break;
    case 10:
      legacy |= 0x1800;
      break;
    case 11:
      legacy |= 0x2000;
      break;
    }
#endif

  pci_write_config_word (devc->osdev, 0x40, legacy);

  /* codec cold reset + AC'97 warm reset */
  OUTW (devc->osdev, (1 << 5) | (1 << 6), devc->base + CODEC_CONTROL);
  oss_udelay (10);
  OUTW (devc->osdev, 0, devc->base + CODEC_CONTROL);

  if (devc->model == MDL_FM801AU)
    {
      OUTW (devc->osdev, (1 << 7), devc->base + CODEC_CONTROL);
      oss_udelay (10);
    }

  /* init volume */
  OUTW (devc->osdev, 0x0808, devc->base + PCM_VOL);
  OUTW (devc->osdev, 0x0808, devc->base + FM_VOL);
  OUTW (devc->osdev, 0x0808, devc->base + I2S_VOL);
  /* interrupt setup - unmask MPU, PLAYBACK & CAPTURE */
  irqmask = INW (devc->osdev, devc->base + IRQ_MASK);
  irqmask &= ~0x0083;
  OUTW (devc->osdev, irqmask, devc->base + IRQ_MASK);
  OUTW (devc->osdev, 0x280C, devc->base + GENERAL_CONTROL);
  OUTW (devc->osdev, 0x0, devc->base + I2S_MODE);
#if !defined(__hpux) && !defined(sparc) && !defined(_TRU64_UNIX)
  /* interrupt clear */
  /*
   * TODO: Check this. Unaligned I/O access causes a crash onder non-x86
   */
  OUTW (devc->osdev, IRQ_PLAY | IRQ_REC | IRQ_MPU, devc->base + IRQ_STATUS);
#endif
  /*
   * Enable BusMasterMode and IOSpace Access
   */
#ifdef OBSOLETED_STUFF
  attach_fm (devc);
  attach_mpu (devc);
#endif
  my_mixer = ac97_install (&devc->ac97devc, "FM801 AC97 Mixer",
			   ac97_read, ac97_write, devc, devc->osdev);

  if (my_mixer >= 0)
    {
      devc->mixer_dev = my_mixer;
      if (devc->model == MDL_FM801AU)
	{
	  my_mixer2 = ac97_install (&devc->ac97devc2, "FM801 AC97 Secondary",
				    ac97_read2, ac97_write2, devc,
				    devc->osdev);
	  if (my_mixer2 >= 0)
	    devc->mixer2_dev = my_mixer2;
	}
    }
  else
    return 0;

  for (i = 0; i < MAX_PORTC; i++)
    {
      char tmp_name[100];
      fm801_portc *portc = &devc->portc[i];
      int caps = ADEV_AUTOMODE;
      if (i == 0)
	{
	  strcpy (tmp_name, devc->chip_name);
	  caps |= ADEV_DUPLEX;
	}
      else
	{
	  strcpy (tmp_name, devc->chip_name);
	  caps |= ADEV_DUPLEX | ADEV_SHADOW;
	}
      if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION,
					devc->osdev,
					devc->osdev,
					tmp_name,
					&fm801_audio_driver,
					sizeof (audiodrv_t),
					caps,
					AFMT_U8 | AFMT_S16_LE, devc, -1)) < 0)
	{
	  adev = -1;
	  return 1;
	}
      else
	{
	  if (i == 0)
	    first_dev = adev;
	  audio_engines[adev]->portc = portc;
	  audio_engines[adev]->rate_source = first_dev;
	  audio_engines[adev]->mixer_dev = my_mixer;
	  audio_engines[adev]->min_rate = 5000;
	  audio_engines[adev]->max_rate = 48000;
	  audio_engines[adev]->caps |= PCM_CAP_FREERATE;
	  audio_engines[adev]->min_channels = 2;
	  audio_engines[adev]->max_channels = 6;
	  portc->open_mode = 0;
	  portc->audiodev = adev;
	  portc->audio_enabled = 0;
#ifdef CONFIG_OSS_VMIX
	  if (i == 0)
	     vmix_attach_audiodev(devc->osdev, adev, -1, 0);
#endif
	}
      init_audio (devc);
    }
  return 1;
}