⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ad1848.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
{  unsigned char   tmp;  int             i;  ad1848_info    *devc = &dev_info[nr_ad1848_devs];  unsigned char   tmp1 = 0xff, tmp2 = 0xff;  if (nr_ad1848_devs >= MAX_AUDIO_DEV)    {      AUDIO_DDB (printk ("ad1848 detect error - step 0\n"));      return 0;    }  devc->base = io_base;  devc->MCE_bit = 0x40;  devc->irq = 0;  devc->dma_capture = 0;  devc->dma_playback = 0;  devc->opened = 0;  devc->chip_name = "AD1848";  devc->mode = 1;		/* MODE1 = original AD1848 */  /*     * Check that the I/O address is in use.     *     * The bit 0x80 of the base I/O port is known to be 0 after the     * chip has performed it's power on initialization. Just assume     * this has happened before the OS is starting.     *     * If the I/O address is unused, it typically returns 0xff.   */  if ((INB (devc->base) & 0x80) != 0x00)	/* Not a AD1884 */    {      AUDIO_DDB (printk ("ad1848 detect error - step A\n"));      return 0;    }  /*     * Test if it's possible to change contents of the indirect registers.     * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only     * so try to avoid using it.   */  ad_write (devc, 0, 0xaa);  ad_write (devc, 1, 0x45);	/* 0x55 with bit 0x10 clear */  if ((tmp1 = ad_read (devc, 0)) != 0xaa || (tmp2 = ad_read (devc, 1)) != 0x45)    {      AUDIO_DDB (printk ("ad1848 detect error - step B (%x/%x)\n", tmp1, tmp2));      return 0;    }  ad_write (devc, 0, 0x45);  ad_write (devc, 1, 0xaa);  if ((tmp1 = ad_read (devc, 0)) != 0x45 || (tmp2 = ad_read (devc, 1)) != 0xaa)    {      AUDIO_DDB (printk ("ad1848 detect error - step C (%x/%x)\n", tmp1, tmp2));      return 0;    }  /*     * The indirect register I12 has some read only bits. Lets     * try to change them.   */  tmp = ad_read (devc, 12);  ad_write (devc, 12, (~tmp) & 0x0f);  if ((tmp & 0x0f) != ((tmp1 = ad_read (devc, 12)) & 0x0f))    {      AUDIO_DDB (printk ("ad1848 detect error - step D (%x)\n", tmp1));      return 0;    }  /*     * NOTE! Last 4 bits of the reg I12 tell the chip revision.     *   0x01=RevB and 0x0A=RevC.   */  /*     * The original AD1848/CS4248 has just 15 indirect registers. This means     * that I0 and I16 should return the same value (etc.).     * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails     * with CS4231.   */  ad_write (devc, 12, 0);	/* Mode2=disabled */  for (i = 0; i < 16; i++)    if ((tmp1 = ad_read (devc, i)) != (tmp2 = ad_read (devc, i + 16)))      {	AUDIO_DDB (printk ("ad1848 detect error - step F(%d/%x/%x)\n", i, tmp1, tmp2));	return 0;      }  /*     * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit (0x40).     * The bit 0x80 is always 1 in CS4248 and CS4231.   */  ad_write (devc, 12, 0x40);	/* Set mode2, clear 0x80 */  tmp1 = ad_read (devc, 12);  if (tmp1 & 0x80)    devc->chip_name = "CS4248";	/* Our best knowledge just now */  if ((tmp1 & 0xc0) == (0x80 | 0x40))    {      /*         *      CS4231 detected - is it?         *         *      Verify that setting I0 doesn't change I16.       */      ad_write (devc, 16, 0);	/* Set I16 to known value */      ad_write (devc, 0, 0x45);      if ((tmp1 = ad_read (devc, 16)) != 0x45)	/* No change -> CS4231? */	{	  ad_write (devc, 0, 0xaa);	  if ((tmp1 = ad_read (devc, 16)) == 0xaa)	/* Rotten bits? */	    {	      AUDIO_DDB (printk ("ad1848 detect error - step H(%x)\n", tmp1));	      return 0;	    }	  /*	     * Verify that some bits of I25 are read only.	   */	  tmp1 = ad_read (devc, 25);	/* Original bits */	  ad_write (devc, 25, ~tmp1);	/* Invert all bits */	  if ((ad_read (devc, 25) & 0xe7) == (tmp1 & 0xe7))	    {	      /*	         *      It's a CS4231	       */	      devc->chip_name = "CS4231";#ifdef MOZART_PORT	      if (devc->base != MOZART_PORT)#endif		devc->mode = 2;	    }	  ad_write (devc, 25, tmp1);	/* Restore bits */	}    }  return 1;}voidad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture){  /*     * NOTE! If irq < 0, there is another driver which has allocated the IRQ     *   so that this driver doesn't need to allocate/deallocate it.     *   The actually used IRQ is ABS(irq).   */  /*     * Initial values for the indirect registers of CS4248/AD1848.   */  static int      init_values[] =  {    0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x80, 0x80,    0x00, 0x08, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00,  /* Positions 16 to 31 just for CS4231 */    0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  };  int             i, my_dev;  ad1848_info    *devc = &dev_info[nr_ad1848_devs];  if (!ad1848_detect (io_base))    return;  devc->irq = (irq > 0) ? irq : 0;  devc->dma_capture = dma_playback;  devc->dma_playback = dma_capture;  devc->opened = 0;  if (nr_ad1848_devs != 0)    {      memcpy ((char *) &ad1848_pcm_operations[nr_ad1848_devs],	      (char *) &ad1848_pcm_operations[0],	      sizeof (struct audio_operations));    }  for (i = 0; i < 16; i++)    ad_write (devc, i, init_values[i]);  ad_mute (devc);  if (devc->mode == 2)    {      ad_write (devc, 12, ad_read (devc, 12) | 0x40);	/* Mode2 = enabled */      for (i = 16; i < 32; i++)	ad_write (devc, i, init_values[i]);    }  OUTB (0, io_Status (devc));	/* Clear pending interrupts */  if (name[0] != 0)    sprintf (ad1848_pcm_operations[nr_ad1848_devs].name,	     "%s (%s)", name, devc->chip_name);  else    sprintf (ad1848_pcm_operations[nr_ad1848_devs].name,	     "Generic audio codec (%s)", devc->chip_name);#if defined(__FreeBSD__)  if (strcmp(name, "MS Sound System")) /* *sigh* */  	printk ("\ngus0: <%s>", ad1848_pcm_operations[nr_ad1848_devs].name);  else  	printk ("mss0: <%s>", ad1848_pcm_operations[nr_ad1848_devs].name);#else  printk (" <%s>", ad1848_pcm_operations[nr_ad1848_devs].name);#endif  if (num_audiodevs < MAX_AUDIO_DEV)    {      audio_devs[my_dev = num_audiodevs++] = &ad1848_pcm_operations[nr_ad1848_devs];      if (irq > 0)	irq2dev[irq] = my_dev;      else if (irq < 0)	irq2dev[-irq] = my_dev;      audio_devs[my_dev]->dmachan = dma_playback;      audio_devs[my_dev]->buffcount = 1;      audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;      audio_devs[my_dev]->devc = devc;      audio_devs[my_dev]->format_mask = ad_format_mask[devc->mode];      nr_ad1848_devs++;      /*         * Toggle the MCE bit. It completes the initialization phase.       */      ad_enter_MCE (devc);	/* In case the bit was off */      ad_leave_MCE (devc);      if (num_mixers < MAX_MIXER_DEV)	{	  mixer2codec[num_mixers] = my_dev + 1;	  audio_devs[my_dev]->mixer_dev = num_mixers;	  mixer_devs[num_mixers++] = &ad1848_mixer_operations;	  ad1848_mixer_reset (devc);	}    }  else    printk ("AD1848: Too many PCM devices available\n");}voidad1848_interrupt (INT_HANDLER_PARMS (irq, dummy)){  unsigned char   status;  ad1848_info    *devc;  int             dev;  if (irq < 0 || irq > 15)    return;			/* Bogus irq */  dev = irq2dev[irq];  if (dev < 0 || dev >= num_audiodevs)    return;			/* Bogus dev */  devc = (ad1848_info *) audio_devs[dev]->devc;  status = INB (io_Status (devc));  if (status == 0x80)    printk ("ad1848_interrupt: Why?\n");  if (status & 0x01)    {      if (devc->opened && devc->irq_mode == IMODE_OUTPUT)	{	  DMAbuf_outputintr (dev, 1);	}      if (devc->opened && devc->irq_mode == IMODE_INPUT)	DMAbuf_inputintr (dev);    }  OUTB (0, io_Status (devc));	/* Clear interrupt status */  status = INB (io_Status (devc));  if (status == 0x80 || status & 0x01)    {      printk ("ad1848: Problems when clearing interrupt, status=%x\n", status);      OUTB (0, io_Status (devc));	/* Try again */    }}#ifdef MOZART_PORT/* * Experimental initialization sequence for Mozart soundcard * (OAK OTI-601 sound chip). * by Gregor Hoffleit <flight@mathi.uni-heidelberg.de> * Some comments by Hannu Savolainen. */intmozart_init (int io_base){  int             i;  unsigned char   byte;  static int      mozart_detected_here = 0;  /*     * Valid ports are 0x530 and 0xf40. The DOS based software doesn't allow     * other ports. The OTI-601 preliminary specification says that     * 0xe80 and 0x604 are also possible but it's safest to ignore them.   */  if ((io_base != 0x530) && (io_base != 0xf40))    {      printk ("Mozart: invalid io_base(%x)\n", io_base);      return 0;    }  if (mozart_detected_here == io_base)	/* Already detected this card */    return 1;  if (mozart_detected_here != 0)    return 0;			/* Don't allow detecting another Mozart card. */  /*     * The Mozart chip (OAK OTI-601) must be enabled before _each_ write     * by writing a secret password (0xE2) to the password register (0xf8f).     * Any I/O cycle after writing the password closes the gate and disbles     * further access.   */  if (INB (0xf88) != 0)		/* Appears to return 0 while the gate is closed */    {      AUDIO_DDB (printk ("No Mozart signature detected on port 0xf88\n"));      return 0;    }  OUTB (0xe2, 0xf8f);		/* A secret password which opens the gate */  OUTB (0x10, 0xf91);		/* Enable access to codec registers during SB mode */  for (i = 0; i < 100; i++)	/* Delay */    tenmicrosec ();  OUTB (0xe2, 0xf8f);		/* Sesam */  byte = INB (0xf8d);		/* Read MC1 (Mode control register) */  /* Read the same register again but with gate closed at this time. */  if (INB (0xf8d) == 0xff)	/* Bus float. Should be 0 if Mozart present */    {      AUDIO_DDB (printk ("Seems to be no Mozart chip set\n"));      return 0;    }  AUDIO_DDB (printk ("mozart_init: read 0x%x on 0xf8d\n", byte));  byte = byte | 0x80;		/* Switch to WSS mode (disables SB) */  byte = byte & 0xcf;		/* Clear sound base, disable CD, enable joystick */  if (io_base == 0xf40)    byte = byte | 0x20;  for (i = 0; i < 100; i++)    tenmicrosec ();  OUTB (0xe2, 0xf8f);		/* Open the gate again */  OUTB (byte, 0xf8d);		/* Write the modified value back to MC1 */  AUDIO_DDB (printk ("mozart_init: wrote 0x%x on 0xf8d\n", byte));  OUTB (0xe2, 0xf8f);		/* Here we come again */  OUTB (0x20, 0xf91);		/* Protect WSS shadow registers against write */  for (i = 0; i < 1000; i++)    tenmicrosec ();  return 1;}#endif /* MOZART_PORT */#ifdef OPTI_MAD16_PORT#include <i386/isa/sound/mad16.h>#endif/* * Some extra code for the MS Sound System */intprobe_ms_sound (struct address_info *hw_config){#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MSS)  /*     * Initialize Audio Excel DSP 16 to MSS: before any operation     * we must enable MSS I/O ports.   */  InitAEDSP16_MSS (hw_config);#endif  /*     * Check if the IO port returns valid signature. The original MS Sound     * system returns 0x04 while some cards (AudioTriX Pro for example)     * return 0x00.   */#ifdef MOZART_PORT  if (hw_config->io_base == MOZART_PORT)    mozart_init (hw_config->io_base);#endif#ifdef OPTI_MAD16_PORT  if (hw_config->io_base == OPTI_MAD16_PORT)    mad16init (hw_config->io_base);#endif  if ((INB (hw_config->io_base + 3) & 0x3f) != 0x04 &&      (INB (hw_config->io_base + 3) & 0x3f) != 0x00)    {      AUDIO_DDB (printk ("No MSS signature detected on port 0x%x (0x%x)\n",		   hw_config->io_base, INB (hw_config->io_base + 3)));      return 0;    }#ifdef PC98  if (hw_config->irq > 12)#else  if (hw_config->irq > 11)#endif    {      printk ("MSS: Bad IRQ %d\n", hw_config->irq);      return 0;    }  if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)    {      printk ("MSS: Bad DMA %d\n", hw_config->dma);      return 0;    }  /*     * Check that DMA0 is not in use with a 8 bit board.   */  if (hw_config->dma == 0 && INB (hw_config->io_base + 3) & 0x80)    {      printk ("MSS: Can't use DMA0 with a 8 bit card/slot\n");      return 0;    }  if (hw_config->irq > 7 && hw_config->irq != 9 && INB (hw_config->io_base + 3) & 0x80)    {      printk ("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);      return 0;    }  return ad1848_detect (hw_config->io_base + 4);}longattach_ms_sound (long mem_start, struct address_info *hw_config){#ifdef PC98  static char     interrupt_bits[13] =  {    -1, -1, -1, 0x08, -1, 0x10, -1, -1, -1, -1, 0x18, -1, 0x20  };#else  static char     interrupt_bits[12] =  {    -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20  };#endif  char            bits;  static char     dma_bits[4] =  {    1, 2, 0, 3  };  int             config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;  if (!ad1848_detect (hw_config->io_base + 4))    return mem_start;  /*     * Set the IRQ and DMA addresses.   */  bits = interrupt_bits[hw_config->irq];  if (bits == -1)    return mem_start;  OUTB (bits | 0x40, config_port);  if ((INB (version_port) & 0x40) == 0)    printk ("[IRQ Conflict?]");  OUTB (bits | dma_bits[hw_config->dma], config_port);	/* Write IRQ+DMA setup */  ad1848_init ("MS Sound System", hw_config->io_base + 4,	       hw_config->irq,	       hw_config->dma,	       hw_config->dma);  return mem_start;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -