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

📄 mpu401.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
{  int             i, timeout, ok;  int             ret = 0;  unsigned long   flags;  struct mpu_config *devc;  devc = &dev_conf[dev];  if (devc->uart_mode)		/*				 * Not possible in UART mode				 */    {      printk ("MPU-401 commands not possible in the UART mode\n");      return RET_ERROR (EINVAL);    }  /*   * Test for input since pending input seems to block the output.   */  if (input_avail (devc->base))    mpu401_input_loop (devc);  /*   * Sometimes it takes about 30000 loops before the output becomes ready   * (After reset). Normally it takes just about 10 loops.   */  timeout = 30000;retry:  if (timeout-- <= 0)    {      printk ("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd);      return RET_ERROR (EIO);    }  DISABLE_INTR (flags);  if (!output_ready (devc->base))    {      RESTORE_INTR (flags);      goto retry;    }  write_command (devc->base, cmd->cmd);  ok = 0;  for (timeout = 50000; timeout > 0 && !ok; timeout--)    if (input_avail (devc->base))      {	if (mpu_input_scanner (devc, read_data (devc->base)) == MPU_ACK)	  ok = 1;      }  if (!ok)    {      RESTORE_INTR (flags);      /*       printk ("MPU: No ACK to command (0x%x)\n", (int) cmd->cmd); */      return RET_ERROR (EIO);    }  if (cmd->nr_args)    for (i = 0; i < cmd->nr_args; i++)      {	for (timeout = 3000; timeout > 0 && !output_ready (devc->base); timeout--);	if (!mpu401_out (dev, cmd->data[i]))	  {	    RESTORE_INTR (flags);	    printk ("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd);	    return RET_ERROR (EIO);	  }      }  ret = 0;  cmd->data[0] = 0;  if (cmd->nr_returns)    for (i = 0; i < cmd->nr_returns; i++)      {	ok = 0;	for (timeout = 5000; timeout > 0 && !ok; timeout--)	  if (input_avail (devc->base))	    {	      cmd->data[i] = read_data (devc->base);	      ok = 1;	    }	if (!ok)	  {	    RESTORE_INTR (flags);	    /* printk ("MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd); */	    return RET_ERROR (EIO);	  }      }  RESTORE_INTR (flags);  return ret;}static intexec_cmd (int dev, int cmd, int data){  int             ret;  static mpu_command_rec rec;  rec.cmd = cmd & 0xff;  rec.nr_args = ((cmd & 0xf0) == 0xE0);  rec.nr_returns = ((cmd & 0xf0) == 0xA0);  rec.data[0] = data & 0xff;  if ((ret = mpu401_command (dev, &rec)) < 0)    return ret;  return (unsigned char) rec.data[0];}static intmpu401_prefix_cmd (int dev, unsigned char status){  struct mpu_config *devc = &dev_conf[dev];  if (devc->uart_mode)    return 1;  if (status < 0xf0)    {      if (exec_cmd (dev, 0xD0, 0) < 0)	return 0;      return 1;    }  switch (status)    {    case 0xF0:      if (exec_cmd (dev, 0xDF, 0) < 0)	return 0;      return 1;      break;    default:      return 0;    }  return 0;}static intmpu401_start_read (int dev){  return 0;}static intmpu401_end_read (int dev){  return 0;}static intmpu401_ioctl (int dev, unsigned cmd, unsigned arg){  struct mpu_config *devc;  devc = &dev_conf[dev];  switch (cmd)    {    case 1:      IOCTL_FROM_USER ((char *) &init_sequence, (char *) arg, 0, sizeof (init_sequence));      return 0;      break;    case SNDCTL_MIDI_MPUMODE:      if (devc->version == 0)	{	  printk ("MPU-401: Intelligent mode not supported by the HW\n");	  return RET_ERROR (EINVAL);	}      set_uart_mode (dev, devc, !IOCTL_IN (arg));      return 0;      break;    case SNDCTL_MIDI_MPUCMD:      {	int             ret;	mpu_command_rec rec;	IOCTL_FROM_USER ((char *) &rec, (char *) arg, 0, sizeof (rec));	if ((ret = mpu401_command (dev, &rec)) < 0)	  return ret;	IOCTL_TO_USER ((char *) arg, 0, (char *) &rec, sizeof (rec));	return 0;      }      break;    default:      return RET_ERROR (EINVAL);    }}static voidmpu401_kick (int dev){}static intmpu401_buffer_status (int dev){  return 0;			/*				 * No data in buffers				 */}static intmpu_synth_ioctl (int dev,		 unsigned int cmd, unsigned int arg){  int             midi_dev;  struct mpu_config *devc;  midi_dev = synth_devs[dev]->midi_dev;  if (midi_dev < 0 || midi_dev > num_midis)    return RET_ERROR (ENXIO);  devc = &dev_conf[midi_dev];  switch (cmd)    {    case SNDCTL_SYNTH_INFO:      IOCTL_TO_USER ((char *) arg, 0, &mpu_synth_info[midi_dev],		     sizeof (struct synth_info));      return 0;      break;    case SNDCTL_SYNTH_MEMAVL:      return 0x7fffffff;      break;    default:      return RET_ERROR (EINVAL);    }}static intmpu_synth_open (int dev, int mode){  int             midi_dev, err;  struct mpu_config *devc;  midi_dev = synth_devs[dev]->midi_dev;  if (midi_dev < 0 || midi_dev > num_midis)    {      return RET_ERROR (ENXIO);    }  devc = &dev_conf[midi_dev];  /*     *  Verify that the device is really running.     *  Some devices (such as Ensoniq SoundScape don't     *  work before the on board processor (OBP) is initialized     *  by downloadin it's microcode.   */  if (!devc->initialized)    {      if (mpu401_status (devc->base) == 0xff)	/* Bus float */	{	  printk ("MPU-401: Device not initialized properly\n");	  return RET_ERROR (EIO);	}      reset_mpu401 (devc);    }  if (devc->opened)    {      printk ("MPU-401: Midi busy\n");      return RET_ERROR (EBUSY);    }  devc->mode = MODE_SYNTH;  devc->synthno = dev;  devc->inputintr = NULL;  irq2dev[devc->irq] = midi_dev;  if (devc->shared_irq == 0)    if ((err = snd_set_irq_handler (devc->irq, mpuintr, midi_devs[midi_dev]->info.name) < 0))      {	return err;      }  if (midi_devs[midi_dev]->coproc)    if ((err = midi_devs[midi_dev]->coproc->	 open (midi_devs[midi_dev]->coproc->devc, COPR_MIDI)) < 0)      {	if (devc->shared_irq == 0)	  snd_release_irq (devc->irq);	printk ("MPU-401: Can't access coprocessor device\n");	return err;      }  devc->opened = mode;  reset_mpu401 (devc);  if (mode & OPEN_READ)    {      exec_cmd (midi_dev, 0x8B, 0);	/* Enable data in stop mode */      exec_cmd (midi_dev, 0x34, 0);	/* Return timing bytes in stop mode */    }  return 0;}static voidmpu_synth_close (int dev){  int             midi_dev;  struct mpu_config *devc;  midi_dev = synth_devs[dev]->midi_dev;  devc = &dev_conf[midi_dev];  exec_cmd (midi_dev, 0x15, 0);	/* Stop recording, playback and MIDI */  exec_cmd (midi_dev, 0x8a, 0);	/* Disable data in stopped mode */  if (devc->shared_irq == 0)    snd_release_irq (devc->irq);  devc->inputintr = NULL;  if (midi_devs[midi_dev]->coproc)    midi_devs[midi_dev]->coproc->close (midi_devs[midi_dev]->coproc->devc, COPR_MIDI);  devc->opened = 0;  devc->mode = 0;}#define MIDI_SYNTH_NAME	"MPU-401 UART Midi"#define MIDI_SYNTH_CAPS	SYNTH_CAP_INPUT#include <i386/isa/sound/midi_synth.h>static struct synth_operations mpu401_synth_proto ={  NULL,  0,  SYNTH_TYPE_MIDI,  0,  mpu_synth_open,  mpu_synth_close,  mpu_synth_ioctl,  midi_synth_kill_note,  midi_synth_start_note,  midi_synth_set_instr,  midi_synth_reset,  midi_synth_hw_control,  midi_synth_load_patch,  midi_synth_aftertouch,  midi_synth_controller,  midi_synth_panning,  NULL,  midi_synth_patchmgr,  midi_synth_bender,  NULL,				/* alloc */  midi_synth_setup_voice};static struct synth_operations mpu401_synth_operations[MAX_MIDI_DEV];static struct midi_operations mpu401_midi_proto ={  {"MPU-401 Midi", 0, MIDI_CAP_MPU401, SNDCARD_MPU401},  NULL,  {0},  mpu401_open,  mpu401_close,  mpu401_ioctl,  mpu401_out,  mpu401_start_read,  mpu401_end_read,  mpu401_kick,  NULL,  mpu401_buffer_status,  mpu401_prefix_cmd};static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV];static voidmpu401_chk_version (struct mpu_config *devc){  int             tmp;  devc->version = devc->revision = 0;  if ((tmp = exec_cmd (num_midis, 0xAC, 0)) < 0)    return;  if ((tmp & 0xf0) > 0x20)	/* Why it's larger than 2.x ??? */    return;  devc->version = tmp;  if ((tmp = exec_cmd (num_midis, 0xAD, 0)) < 0)    {      devc->version = 0;      return;    }  devc->revision = tmp;}longattach_mpu401 (long mem_start, struct address_info *hw_config){  unsigned long   flags;  char            revision_char;  struct mpu_config *devc;  if (num_midis >= MAX_MIDI_DEV)    {      printk ("MPU-401: Too many midi devices detected\n");      return mem_start;    }  devc = &dev_conf[num_midis];  devc->base = hw_config->io_base;  devc->irq = hw_config->irq;  devc->opened = 0;  devc->uart_mode = 0;  devc->initialized = 0;  devc->version = 0;  devc->revision = 0;  devc->capabilities = 0;  devc->timer_flag = 0;  devc->m_busy = 0;  devc->m_state = ST_INIT;  devc->shared_irq = hw_config->always_detect;  if (!hw_config->always_detect)    {      /* Verify the hardware again */      if (!reset_mpu401 (devc))	return mem_start;      DISABLE_INTR (flags);      mpu401_chk_version (devc);      if (devc->version == 0)	mpu401_chk_version (devc);      RESTORE_INTR (flags);    }  if (devc->version == 0)    {      memcpy ((char *) &mpu401_synth_operations[num_midis],	      (char *) &std_midi_synth,	      sizeof (struct synth_operations));    }  else    {      devc->capabilities |= MPU_CAP_INTLG;	/* Supports intelligent mode */      memcpy ((char *) &mpu401_synth_operations[num_midis],	      (char *) &mpu401_synth_proto,	      sizeof (struct synth_operations));    }  memcpy ((char *) &mpu401_midi_operations[num_midis],	  (char *) &mpu401_midi_proto,	  sizeof (struct midi_operations));  mpu401_midi_operations[num_midis].converter =    &mpu401_synth_operations[num_midis];  memcpy ((char *) &mpu_synth_info[num_midis],	  (char *) &mpu_synth_info_proto,	  sizeof (struct synth_info));  n_mpu_devs++;  if (devc->version == 0x20 && devc->revision >= 0x07)	/* MusicQuest interface */    {      int             ports = (devc->revision & 0x08) ? 32 : 16;      devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE |	MPU_CAP_CLS | MPU_CAP_2PORT;      revision_char = (devc->revision == 0x7f) ? 'M' : ' ';#if defined(__FreeBSD__)      printk ("mpu0: <MQX-%d%c MIDI Interface>",#else      printk (" <MQX-%d%c MIDI Interface>",#endif	      ports,	      revision_char);      sprintf (mpu_synth_info[num_midis].name,	       "MQX-%d%c MIDI Interface #%d",	       ports,	       revision_char,	       n_mpu_devs);    }  else    {      revision_char = devc->revision ? devc->revision + '@' : ' ';      if (devc->revision > ('Z' - '@'))	revision_char = '+';      devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK;#if defined(__FreeBSD__)      printk ("mpu0: <MPU-401 MIDI Interface %d.%d%c>",#else      printk (" <MPU-401 MIDI Interface %d.%d%c>",#endif	      (devc->version & 0xf0) >> 4,	      devc->version & 0x0f,	      revision_char);      sprintf (mpu_synth_info[num_midis].name,	       "MPU-401 %d.%d%c Midi interface #%d",	       (devc->version & 0xf0) >> 4,	       devc->version & 0x0f,	       revision_char,	       n_mpu_devs);    }  strcpy (mpu401_midi_operations[num_midis].info.name,	  mpu_synth_info[num_midis].name);  mpu401_synth_operations[num_midis].midi_dev = devc->devno = num_midis;  mpu401_synth_operations[devc->devno].info =    &mpu_synth_info[devc->devno];  if (devc->capabilities & MPU_CAP_INTLG)	/* Has timer */    mpu_timer_init (num_midis);  irq2dev[devc->irq] = num_midis;  midi_devs[num_midis++] = &mpu401_midi_operations[devc->devno];  return mem_start;}static intreset_mpu401 (struct mpu_config *devc){  unsigned long   flags;  int             ok, timeout, n;  int             timeout_limit;  /*   * Send the RESET command. Try again if no success at the first time.   * (If the device is in the UART mode, it will not ack the reset cmd).   */  ok = 0;  timeout_limit = devc->initialized ? 30000 : 100000;  devc->initialized = 1;  for (n = 0; n < 2 && !ok; n++)    {      for (timeout = timeout_limit; timeout > 0 && !ok; timeout--)	ok = output_ready (devc->base);      write_command (devc->base, MPU_RESET);	/*						 * Send MPU-401 RESET Command						 */      /*       * Wait at least 25 msec. This method is not accurate so let's make the       * loop bit longer. Cannot sleep since this is called during boot.       */      for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--)	{	  DISABLE_INTR (flags);	  if (input_avail (devc->base))	    if (read_data (devc->base) == MPU_ACK)	      ok = 1;	  RESTORE_INTR (flags);	}    }  devc->m_state = ST_INIT;  devc->m_ptr = 0;  devc->m_left = 0;  devc->last_status = 0;

⌨️ 快捷键说明

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