Example #1
0
int
pmgr_inform (int dev, int event, unsigned long p1, unsigned long p2,
	     unsigned long p3, unsigned long p4)
{
  unsigned long   flags;
  int             err = 0;

  struct patmgr_info *tmp_mbox;

  if (!pmgr_opened[dev])
    return 0;

  tmp_mbox = (struct patmgr_info *) vmalloc (sizeof (struct patmgr_info));

  if (tmp_mbox == NULL)
    {
      printk ("pmgr: Couldn't allocate memory for a message\n");
      return 0;
    }

  save_flags (flags);
  cli ();

  if (mbox[dev])
    printk ("  PATMGR: Server %d mbox full. Why?\n", dev);
  else
    {

      mbox[dev] = tmp_mbox;
      mbox[dev]->key = PM_K_EVENT;
      mbox[dev]->command = event;
      mbox[dev]->parm1 = p1;
      mbox[dev]->parm2 = p2;
      mbox[dev]->parm3 = p3;
      msg_direction[dev] = A_TO_S;

      if ((server_wait_flag[dev].flags & WK_SLEEP))
	{
	  {
	    server_wait_flag[dev].flags = WK_WAKEUP;
	    module_wake_up (&server_procs[dev]);
	  };
	}


      appl_wait_flag.flags = WK_SLEEP;
      module_interruptible_sleep_on (&appl_proc);
      appl_wait_flag.flags &= ~WK_SLEEP;;
      mbox[dev] = NULL;
      msg_direction[dev] = 0;
    }

  restore_flags (flags);
  vfree (tmp_mbox);

  return err;
}
Example #2
0
int
pmgr_write (int dev, struct fileinfo *file, const char *buf, int count)
{
  unsigned long   flags;

  if (count < 4)
    {
      printk ("PATMGR%d: Write count < 4\n", dev);
      return -(EIO);
    }

  memcpy_fromfs ((char *) mbox[dev], &(buf)[0], 4);

  if (*(unsigned char *) mbox[dev] == SEQ_FULLSIZE)
    {
      int             tmp_dev;

      tmp_dev = ((unsigned short *) mbox[dev])[2];
      if (tmp_dev != dev)
	return -(ENXIO);

      return synth_devs[dev]->load_patch (dev, *(unsigned short *) mbox[dev],
					  buf, 4, count, 1);
    }

  if (count != sizeof (struct patmgr_info))
    {
      printk ("PATMGR%d: Invalid write count\n", dev);
      return -(EIO);
    }

  /*
   * If everything went OK, there should be a preallocated buffer in the
   * mailbox and a client waiting.
   */

  save_flags (flags);
  cli ();

  if (mbox[dev] && !msg_direction[dev])
    {
      memcpy_fromfs (&((char *) mbox[dev])[4], &(buf)[4], count - 4);
      msg_direction[dev] = S_TO_A;

      if ((appl_wait_flag.flags & WK_SLEEP))
	{
	  {
	    appl_wait_flag.flags = WK_WAKEUP;
	    module_wake_up (&appl_proc);
	  };
	}
    }

  restore_flags (flags);

  return count;
}
Example #3
0
int
pmgr_access (int dev, struct patmgr_info *rec)
{
  unsigned long   flags;
  int             err = 0;

  save_flags (flags);
  cli ();

  if (mbox[dev])
    printk ("  PATMGR: Server %d mbox full. Why?\n", dev);
  else
    {
      rec->key = PM_K_COMMAND;
      mbox[dev] = rec;
      msg_direction[dev] = A_TO_S;

      if ((server_wait_flag[dev].flags & WK_SLEEP))
	{
	  {
	    server_wait_flag[dev].flags = WK_WAKEUP;
	    module_wake_up (&server_procs[dev]);
	  };
	}


      appl_wait_flag.flags = WK_SLEEP;
      module_interruptible_sleep_on (&appl_proc);
      appl_wait_flag.flags &= ~WK_SLEEP;;

      if (msg_direction[dev] != S_TO_A)
	{
	  rec->key = PM_ERROR;
	  rec->parm1 = -(EIO);
	}
      else if (rec->key == PM_ERROR)
	{
	  err = rec->parm1;
	  if (err > 0)
	    err = -err;
	}

      mbox[dev] = NULL;
      msg_direction[dev] = 0;
    }

  restore_flags (flags);

  return err;
}
Example #4
0
void
pmgr_release (int dev)
{

  if (mbox[dev])		/*
				 * Killed in action. Inform the client
				 */
    {

      mbox[dev]->key = PM_ERROR;
      mbox[dev]->parm1 = -(EIO);

      if ((appl_wait_flag.flags & WK_SLEEP))
	{
	  appl_wait_flag.flags = WK_WAKEUP;
	  module_wake_up (&appl_proc);
	};
    }

  pmgr_opened[dev] = 0;
}
Example #5
0
void
sscapeintr (int irq, void *dev_id, struct pt_regs *dummy)
{
  unsigned char   bits, tmp;
  static int      debug = 0;

  bits = sscape_read (devc, GA_INTSTAT_REG);
  if ((sscape_sleep_flag.flags & WK_SLEEP))
    {
      {
	sscape_sleep_flag.flags = WK_WAKEUP;
	module_wake_up (&sscape_sleeper);
      };
    }

  if (bits & 0x02)		/* Host interface interrupt */
    {
      printk ("SSCAPE: Host interrupt, data=%02x\n", host_read (devc));
    }

#if defined(CONFIG_MPU_EMU) && defined(CONFIG_MIDI)
  if (bits & 0x01)
    {
      mpuintr (irq, NULL, NULL);
      if (debug++ > 10)		/* Temporary debugging hack */
	{
	  sscape_write (devc, GA_INTENA_REG, 0x00);	/* Disable all interrupts */
	}
    }
#endif

  /*
     * Acknowledge interrupts (toggle the interrupt bits)
   */

  tmp = sscape_read (devc, GA_INTENA_REG);
  sscape_write (devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1));

}
Example #6
0
/* Llamado cuando el fichero /proc se abre */
static int module_open(struct inode *inode,
                       struct file *file)
{
  /* Si las banderas del fichero incluyen O_NONBLOCK, esto
   * significa que el proceso no quiere esperar al fichero.
   * En este caso, si el fichero ya está abierto, deberemos
   * fallar con -EAGAIN, significando que "tienes que intentarlo
   * otra vez", en vez de bloquear un proceso que tendría que
   * estar despierto. */
  if ((file->f_flags & O_NONBLOCK) && Already_Open) 
    return -EAGAIN;

  /* Este es el sitio correcto para MOD_INC_USE_COUNT
   * porque si un proceso está en el bucle, que
   * está dentro del módulo, el módulo del núcleo no
   * debería ser quitado. */
  MOD_INC_USE_COUNT;

  /* Si el fichero ya está abierto, espera hasta que no lo esté */
  while (Already_Open) 
  {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
    int i, is_sig=0;
#endif

    /* Esta función pone el proceso actual, 
     * incluyendo algunas llamada al sistema, como nosotros, 
     * a dormir. La ejecución será retomada correctamente después
     * de la llamada a la función, o porque alguien
     * llamó a wake_up(&WaitQ) (sólo module_close hace esto,
     * cuando el fichero se cierra) o cuando una señal, como
     * Ctrl-C, es enviada al proceso */
    module_interruptible_sleep_on(&WaitQ);
 
    /* Si despertamos porque tenemos una señal no estamos
     * bloqueando, retornamos -EINTR (falla la llamada al
     * sistema). Esto permite a los procesos ser matados o
     * parados. */


/*
 * Emmanuel Papirakis:
 *
 * Esta es una pequeña actualización para trabajar con 2.2.*. Las
 * señales son ahora contenidas en dos palabras (64 bits) y son
 * almacenadas en una estructura que contiene un array de dos
 * unsigned longs. Ahora tenemos que realizar 2 chequeos en nuestro if.
 *
 * Ori Pomerantz:
 *
 * Nadie me prometió que no usarían nunca más de 64 bits, o
 * que este libro no sería usado para una versión de Linux
 * con un tamaño de palabra de 16 bits. En cualquier caso este 
 * código debería de funcionar.
 */	  
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

    for(i=0; i<_NSIG_WORDS && !is_sig; i++)
      is_sig = current->signal.sig[i] & 
        ~current->blocked.sig[i];
    if (is_sig) {
#else
    if (current->signal & ~current->blocked) {
#endif
      /* Es importante poner MOD_DEC_USE_COUNT aquí.
       * porque los procesos dónde open es interrumpido
       * no tendrán nunca un close correspondiente. Si
       * no decrementamos el contador de uso aquí, lo dejaremos
       * con un valor positivo el cual no nos dará
       * la oportunidad de llegar hasta 0, dándonos un módulo inmortal,
       * que sólo se puede matar reiniciando la máquina. */
      MOD_DEC_USE_COUNT;
      return -EINTR;
    }
  }

  /* Si estamos aquí, Already_Open debe ser cero */

  /* Abre el fichero */
  Already_Open = 1;
  return 0;  /* Permite el acceso */
}



/* Llamado cuando el fichero /proc se cierra*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
int module_close(struct inode *inode, struct file *file)
#else
void module_close(struct inode *inode, struct file *file)
#endif
{
  /* Establece Already_Open a cero, por lo tanto uno de los procesos
   * en WaitQ será capaz de establecer Already_Open otra vez a uno y
   * abrir el fichero. Todos los otros procesos serán llamados cuando
   * Already_Open vuelva a ser uno, por lo tanto volverán a
   * dormir. */
  Already_Open = 0;

  /* Despertamos a todos los procesos en WaitQ, por lo tanto si
   * alguien está esperando por el fichero, lo puede tener. */
  module_wake_up(&WaitQ);

  MOD_DEC_USE_COUNT;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
  return 0;  /* finalizado con éxito */
#endif
}