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

📄 sscape.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
      }#endif    }  return 1;}static intdownload_boot_block (void *dev_info, copr_buffer * buf){  if (buf->len <= 0 || buf->len > sizeof (buf->data))    return RET_ERROR (EINVAL);  if (!sscape_download_boot (devc, buf->data, buf->len, buf->flags))    {      printk ("SSCAPE: Unable to load microcode block to the OBP.\n");      return RET_ERROR (EIO);    }  return 0;}static intsscape_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local){  switch (cmd)    {    case SNDCTL_COPR_RESET:      sscape_coproc_reset (dev_info);      return 0;      break;    case SNDCTL_COPR_LOAD:      {	copr_buffer    *buf;	int             err;	buf = (copr_buffer *) KERNEL_MALLOC (sizeof (copr_buffer));	IOCTL_FROM_USER ((char *) buf, (char *) arg, 0, sizeof (*buf));	err = download_boot_block (dev_info, buf);	KERNEL_FREE (buf);	return err;      }      break;    default:      return RET_ERROR (EINVAL);    }  return RET_ERROR (EINVAL);}static coproc_operations sscape_coproc_operations ={  "SoundScape M68K",  sscape_coproc_open,  sscape_coproc_close,  sscape_coproc_ioctl,  sscape_coproc_reset,  &dev_info};static intsscape_audio_open (int dev, int mode){  unsigned long   flags;  sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;  DISABLE_INTR (flags);  if (devc->opened)    {      RESTORE_INTR (flags);      return RET_ERROR (EBUSY);    }  if (devc->dma_allocated == 0)    {      int             err;      if ((err = DMAbuf_open_dma (devc->my_audiodev)) < 0)	{	  RESTORE_INTR (flags);	  return err;	}      devc->dma_allocated = 1;    }  devc->opened = 1;  RESTORE_INTR (flags);#ifdef SSCAPE_DEBUG4  /*     * Temporary debugging aid. Print contents of the registers     * when the device is opened.   */  {    int             i;    for (i = 0; i < 13; i++)      printk ("I%d = %02x\n", i, sscape_read (devc, i));  }#endif  return 0;}static voidsscape_audio_close (int dev){  unsigned long   flags;  sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;  DEB (printk ("sscape_audio_close(void)\n"));  DISABLE_INTR (flags);  if (devc->dma_allocated)    {      sscape_write (devc, GA_DMAA_REG, 0x20);	/* DMA channel disabled */      DMAbuf_close_dma (dev);      devc->dma_allocated = 0;    }  devc->opened = 0;  RESTORE_INTR (flags);}static intset_speed (sscape_info * devc, int arg){  return 8000;}static intset_channels (sscape_info * devc, int arg){  return 1;}static intset_format (sscape_info * devc, int arg){  return AFMT_U8;}static intsscape_audio_ioctl (int dev, unsigned int cmd, unsigned int arg, int local){  sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;  switch (cmd)    {    case SOUND_PCM_WRITE_RATE:      if (local)	return set_speed (devc, arg);      return IOCTL_OUT (arg, set_speed (devc, IOCTL_IN (arg)));    case SOUND_PCM_READ_RATE:      if (local)	return 8000;      return IOCTL_OUT (arg, 8000);    case SNDCTL_DSP_STEREO:      if (local)	return set_channels (devc, arg + 1) - 1;      return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg) + 1) - 1);    case SOUND_PCM_WRITE_CHANNELS:      if (local)	return set_channels (devc, arg);      return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg)));    case SOUND_PCM_READ_CHANNELS:      if (local)	return 1;      return IOCTL_OUT (arg, 1);    case SNDCTL_DSP_SAMPLESIZE:      if (local)	return set_format (devc, arg);      return IOCTL_OUT (arg, set_format (devc, IOCTL_IN (arg)));    case SOUND_PCM_READ_BITS:      if (local)	return 8;      return IOCTL_OUT (arg, 8);    default:;    }  return RET_ERROR (EINVAL);}static voidsscape_audio_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart){}static voidsscape_audio_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart){}static intsscape_audio_prepare_for_input (int dev, int bsize, int bcount){  return 0;}static intsscape_audio_prepare_for_output (int dev, int bsize, int bcount){  return 0;}static voidsscape_audio_halt (int dev){}static voidsscape_audio_reset (int dev){  sscape_audio_halt (dev);}static struct audio_operations sscape_audio_operations ={  "Ensoniq SoundScape channel A",  0,  AFMT_U8 | AFMT_S16_LE,  NULL,  sscape_audio_open,  sscape_audio_close,  sscape_audio_output_block,  sscape_audio_start_input,  sscape_audio_ioctl,  sscape_audio_prepare_for_input,  sscape_audio_prepare_for_output,  sscape_audio_reset,  sscape_audio_halt,  NULL,  NULL};longattach_sscape (long mem_start, struct address_info *hw_config){  int             my_dev;#ifndef SSCAPE_REGS  /*     * Config register values for Spea/V7 Media FX and Ensoniq S-2000.     * These values are card     * dependent. If you have another SoundScape based card, you have to     * find the correct values. Do the following:     *  - Compile this driver with SSCAPE_DEBUG1 defined.     *  - Shut down and power off your machine.     *  - Boot with DOS so that the SSINIT.EXE program is run.     *  - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed     *    when detecting the SoundScape.     *  - Modify the following list to use the values printed during boot.     *    Undefine the SSCAPE_DEBUG1   */#define SSCAPE_REGS { \/* I0 */	0x00, \		0xf0, /* Note! Ignored. Set always to 0xf0 */ \		0x20, /* Note! Ignored. Set always to 0x20 */ \		0x20, /* Note! Ignored. Set always to 0x20 */ \		0xf5, /* Ignored */ \		0x10, \		0x00, \		0x2e, /* I7 MEM config A. Likely to vary between models */ \		0x00, /* I8 MEM config A. Likely to vary between models */ \/* I9 */	0x40 /* Ignored */ \	}#endif  unsigned long   flags;  static unsigned char regs[10] = SSCAPE_REGS;  int             i, irq_bits = 0xff;  if (!probe_sscape (hw_config))    return mem_start;  printk (" <Ensoniq Soundscape>");  for (i = 0; i < sizeof (valid_interrupts); i++)    if (hw_config->irq == valid_interrupts[i])      {	irq_bits = i;	break;      }  if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff))    {      printk ("Invalid IRQ%d\n", hw_config->irq);      return mem_start;    }  DISABLE_INTR (flags);  for (i = 1; i < 10; i++)    switch (i)      {      case 1:			/* Host interrupt enable */	sscape_write (devc, i, 0xf0);	/* All interrupts enabled */	break;      case 2:			/* DMA A status/trigger register */      case 3:			/* DMA B status/trigger register */	sscape_write (devc, i, 0x20);	/* DMA channel disabled */	break;      case 4:			/* Host interrupt config reg */	sscape_write (devc, i, 0xf0 | (irq_bits << 2) | irq_bits);	break;      case 5:			/* Don't destroy CD-ROM DMA config bits (0xc0) */	sscape_write (devc, i, (regs[i] & 0x3f) |		      (sscape_read (devc, i) & 0x0c));	break;      case 6:			/* CD-ROM config. Don't touch. */	break;      case 9:			/* Master control reg. Don't modify CR-ROM bits. Disable SB emul */	sscape_write (devc, i,		      (sscape_read (devc, i) & 0xf0) | 0x00);	break;      default:	sscape_write (devc, i, regs[i]);      }  RESTORE_INTR (flags);#ifdef SSCAPE_DEBUG2  /*     * Temporary debugging aid. Print contents of the registers after     * changing them.   */  {    int             i;    for (i = 0; i < 13; i++)      printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i));  }#endif#if !defined(EXCLUDE_MIDI) && !defined(EXCLUDE_MPU_EMU)  hw_config->always_detect = 1;  if (probe_mpu401 (hw_config))    {      int             prev_devs;      prev_devs = num_midis;      mem_start = attach_mpu401 (mem_start, hw_config);      if (num_midis == (prev_devs + 1))		/* The MPU driver installed itself */	midi_devs[prev_devs]->coproc = &sscape_coproc_operations;    }#endif#ifndef EXCLUDE_NATIVE_PCM  /* Not supported yet */#ifndef EXCLUDE_AUDIO  if (num_audiodevs < MAX_AUDIO_DEV)    {      audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations;      audio_devs[my_dev]->dmachan = hw_config->dma;      audio_devs[my_dev]->buffcount = 1;      audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;      audio_devs[my_dev]->devc = devc;      devc->my_audiodev = my_dev;      devc->opened = 0;      audio_devs[my_dev]->coproc = &sscape_coproc_operations;      if (snd_set_irq_handler (hw_config->irq, sscapeintr, "SoundScape") < 0)	printk ("Error: Can't allocate IRQ for SoundScape\n");      sscape_write (devc, GA_INTENA_REG, 0x80);		/* Master IRQ enable */    }  else    printk ("SoundScape: More than enough audio devices detected\n");#endif#endif  devc->ok = 1;  return mem_start;}intprobe_sscape (struct address_info *hw_config){  unsigned char   save;  devc->base = hw_config->io_base;  devc->irq = hw_config->irq;  devc->dma = hw_config->dma;  /*     * First check that the address register of "ODIE" is     * there and that it has exactly 4 writeable bits.     * First 4 bits   */  if ((save = INB (PORT (ODIE_ADDR))) & 0xf0)    return 0;  OUTB (0x00, PORT (ODIE_ADDR));  if (INB (PORT (ODIE_ADDR)) != 0x00)    return 0;  OUTB (0xff, PORT (ODIE_ADDR));  if (INB (PORT (ODIE_ADDR)) != 0x0f)    return 0;  OUTB (save, PORT (ODIE_ADDR));  /*     * Now verify that some indirect registers return zero on some bits.     * This may break the driver with some future revisions of "ODIE" but...   */  if (sscape_read (devc, 0) & 0x0c)    return 0;  if (sscape_read (devc, 1) & 0x0f)    return 0;  if (sscape_read (devc, 5) & 0x0f)    return 0;#ifdef SSCAPE_DEBUG1  /*     * Temporary debugging aid. Print contents of the registers before     * changing them.   */  {    int             i;    for (i = 0; i < 13; i++)      printk ("I%d = %02x (old value)\n", i, sscape_read (devc, i));  }#endif  return 1;}intprobe_ss_ms_sound (struct address_info *hw_config){  int             i, irq_bits = 0xff;  if (devc->ok == 0)    {      printk ("SoundScape: Invalid initialization order.\n");      return 0;    }  for (i = 0; i < sizeof (valid_interrupts); i++)    if (hw_config->irq == valid_interrupts[i])      {	irq_bits = i;	break;      }#ifdef REVEAL_SPEA  {    int             tmp, status = 0;    int             cc;    if (!((tmp = sscape_read (devc, GA_HMCTL_REG)) & 0xc0))      {	sscape_write (devc, GA_HMCTL_REG, tmp | 0x80);	for (cc = 0; cc < 200000; ++cc)	  INB (devc->base + ODIE_ADDR);      }  }#endif  if (hw_config->irq > 15 || irq_bits == 0xff)    {      printk ("SoundScape: Invalid MSS IRQ%d\n", hw_config->irq);      return 0;    }  return ad1848_detect (hw_config->io_base);}longattach_ss_ms_sound (long mem_start, struct address_info *hw_config){  /*     * This routine configures the SoundScape card for use with the     * Win Sound System driver. The AD1848 codec interface uses the CD-ROM     * config registers of the "ODIE".   */  int             i, irq_bits = 0xff;#ifdef EXCLUDE_NATIVE_PCM  int             prev_devs = num_audiodevs;#endif  /*     * Setup the DMA polarity.   */  sscape_write (devc, GA_DMACFG_REG, 0x50);  /*     * Take the gate-arry off of the DMA channel.   */  sscape_write (devc, GA_DMAB_REG, 0x20);  /*     * Init the AD1848 (CD-ROM) config reg.   */  for (i = 0; i < sizeof (valid_interrupts); i++)    if (hw_config->irq == valid_interrupts[i])      {	irq_bits = i;	break;      }  sscape_write (devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) |		(irq_bits << 1));  if (hw_config->irq == devc->irq)    printk ("SoundScape: Warning! The WSS mode can't share IRQ with MIDI\n");  ad1848_init ("SoundScape", hw_config->io_base,	       hw_config->irq,	       hw_config->dma,	       hw_config->dma);#ifdef EXCLUDE_NATIVE_PCM  if (num_audiodevs == (prev_devs + 1))		/* The AD1848 driver installed itself */    audio_devs[prev_devs]->coproc = &sscape_coproc_operations;#endif#ifdef SSCAPE_DEBUG5  /*     * Temporary debugging aid. Print contents of the registers     * after the AD1848 device has been initialized.   */  {    int             i;    for (i = 0; i < 13; i++)      printk ("I%d = %02x\n", i, sscape_read (devc, i));  }#endif  return mem_start;}#endif

⌨️ 快捷键说明

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