


Totification on transmition completed:
  - By timer (calculate acurate timing)
  - By interrupt
  - never (directly write to card, because it has DPRAM)


Write to card:
  - Write Cached.
    Write to temp buffer and update if changed

    init_temp_buffer ()
      {
        int i;
        for (i=0; i<512; i++)
          tbuf[i]=0;
      }
    write_temp_buffer(int ch, int value)
      {
        if (ch>=0 && ch<512)
          tbuf[ch]=value
      }
    dump_temp_buffer ()
      {
        int i;
        for (i=0; i<512; i++)
          {
            int v = tbuf[i];
            tbuf[i]=-1;
            if (v!=-1)
              cardram_write (iobase, DMXBASE+i, v);
          }
      }

  - Write trough.
    Write directly to the card (using DPRAM).

    write_slh1512C (SLHUniverse *univ, int offs, byte *data, int size)
      {
      }

    write_data (Universe *univ, int offs, byte *data, int size)
      {
        if (offs>=0 && size+offs < 512 && is_readable (data, size))
          {
            int i;

            univ->modified = univ->modified?1:0;
            for (i=0; i<size; i++)
              if (univ->buffer[offs+i] != data[i])
                {
                  univ->modified++;
                  univ->buffer[offs+i] = data[i];
                }
            if (univ->card->type == SLH1512C)
              wake_up_interruptible (&univ->card->wait_for_data_queue);
          }
      }

    void slh_worker_thread (SLHCard *card)
      {
        long timeout = card->timeout;
        card->ending = 0;

        if (card->type==SLH1512C || card->type==SLH1512D || card->has_interrupt)
          timeout=-1;

        while (!card->ending)
          {
            sleep_on_interruptible(&card->wait_for_data_queue, timeout);

            SLHUniverse *univ = card->slhuniverses;
            while (univ)
              {
                if (univ->modified > 0)
                {
                  dump_temp_buffer (card->iobase, univ->index, univ->buffer, univ->buffersize);
                  /* Transmit data to the card */
                }
                univ = univ->next;
              }
          }
        card->ending = 2;
      }  

    int start_card (SLHCard *card)
      {
        kernel_thread (slh_worker_thread, (void *)card);
      }

    int stop_card (SLHCard *card)
      {
        if (!card->ending)
          {
            card->ending=1;
            wake_up_interruptible (&univ->card->wait_for_data_queue);
          }
        if (while (card->ending!=2))
          udelay(1000);
        udelay(1000);
      }




