cardmo.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. **********************************************************************
  3. * cardmo.c - MIDI UART output HAL for emu10k1 driver
  4. * Copyright 1999, 2000 Creative Labs, Inc.
  5. *
  6. **********************************************************************
  7. *
  8. * Date Author Summary of changes
  9. * ---- ------ ------------------
  10. * October 20, 1999 Bertrand Lee base code release
  11. * November 2, 1999 Alan Cox cleaned up
  12. *
  13. **********************************************************************
  14. *
  15. * This program is free software; you can redistribute it and/or
  16. * modify it under the terms of the GNU General Public License as
  17. * published by the Free Software Foundation; either version 2 of
  18. * the License, or (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public
  26. * License along with this program; if not, write to the Free
  27. * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  28. * USA.
  29. *
  30. **********************************************************************
  31. */
  32. #include <linux/slab.h>
  33. #include "hwaccess.h"
  34. #include "8010.h"
  35. #include "cardmo.h"
  36. #include "irqmgr.h"
  37. /* Installs the IRQ handler for the MPU out port *
  38. * and initialize parameters */
  39. int emu10k1_mpuout_open(struct emu10k1_card *card, struct midi_openinfo *openinfo)
  40. {
  41. struct emu10k1_mpuout *card_mpuout = card->mpuout;
  42. DPF(2, "emu10k1_mpuout_open()\n");
  43. if (!(card_mpuout->status & FLAGS_AVAILABLE))
  44. return -1;
  45. /* Copy open info and mark channel as in use */
  46. card_mpuout->intr = 0;
  47. card_mpuout->openinfo = *openinfo;
  48. card_mpuout->status &= ~FLAGS_AVAILABLE;
  49. card_mpuout->laststatus = 0x80;
  50. card_mpuout->firstmidiq = NULL;
  51. card_mpuout->lastmidiq = NULL;
  52. emu10k1_mpu_reset(card);
  53. emu10k1_mpu_acquire(card);
  54. return 0;
  55. }
  56. int emu10k1_mpuout_close(struct emu10k1_card *card)
  57. {
  58. struct emu10k1_mpuout *card_mpuout = card->mpuout;
  59. struct midi_queue *midiq;
  60. struct midi_hdr *midihdr;
  61. unsigned long flags;
  62. DPF(2, "emu10k1_mpuout_close()\n");
  63. emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
  64. spin_lock_irqsave(&card_mpuout->lock, flags);
  65. while (card_mpuout->firstmidiq != NULL) {
  66. midiq = card_mpuout->firstmidiq;
  67. midihdr = (struct midi_hdr *) midiq->refdata;
  68. card_mpuout->firstmidiq = midiq->next;
  69. kfree(midihdr->data);
  70. kfree(midihdr);
  71. kfree(midiq);
  72. }
  73. card_mpuout->lastmidiq = NULL;
  74. emu10k1_mpu_release(card);
  75. card_mpuout->status |= FLAGS_AVAILABLE;
  76. spin_unlock_irqrestore(&card_mpuout->lock, flags);
  77. return 0;
  78. }
  79. /* If there isn't enough buffer space, reject Midi Buffer. *
  80. * Otherwise, disable TX, create object to hold Midi *
  81. * uffer, update buffer flags and other parameters *
  82. * before enabling TX again. */
  83. int emu10k1_mpuout_add_buffer(struct emu10k1_card *card, struct midi_hdr *midihdr)
  84. {
  85. struct emu10k1_mpuout *card_mpuout = card->mpuout;
  86. struct midi_queue *midiq;
  87. unsigned long flags;
  88. DPF(2, "emu10k1_mpuout_add_buffer()\n");
  89. if (card_mpuout->state == CARDMIDIOUT_STATE_SUSPEND)
  90. return 0;
  91. midihdr->flags |= MIDIBUF_INQUEUE;
  92. midihdr->flags &= ~MIDIBUF_DONE;
  93. if ((midiq = (struct midi_queue *) kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
  94. /* Message lost */
  95. return -1;
  96. }
  97. midiq->next = NULL;
  98. midiq->qtype = 1;
  99. midiq->length = midihdr->bufferlength;
  100. midiq->sizeLeft = midihdr->bufferlength;
  101. midiq->midibyte = midihdr->data;
  102. midiq->refdata = (unsigned long) midihdr;
  103. spin_lock_irqsave(&card_mpuout->lock, flags);
  104. if (card_mpuout->firstmidiq == NULL) {
  105. card_mpuout->firstmidiq = midiq;
  106. card_mpuout->lastmidiq = midiq;
  107. } else {
  108. (card_mpuout->lastmidiq)->next = midiq;
  109. card_mpuout->lastmidiq = midiq;
  110. }
  111. card_mpuout->intr = 0;
  112. emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
  113. spin_unlock_irqrestore(&card_mpuout->lock, flags);
  114. return 0;
  115. }
  116. void emu10k1_mpuout_bh(unsigned long refdata)
  117. {
  118. struct emu10k1_card *card = (struct emu10k1_card *) refdata;
  119. struct emu10k1_mpuout *card_mpuout = card->mpuout;
  120. int cByteSent = 0;
  121. struct midi_queue *midiq;
  122. struct midi_queue *doneq = NULL;
  123. unsigned long flags;
  124. spin_lock_irqsave(&card_mpuout->lock, flags);
  125. while (card_mpuout->firstmidiq != NULL) {
  126. midiq = card_mpuout->firstmidiq;
  127. while (cByteSent < 4 && midiq->sizeLeft) {
  128. if (emu10k1_mpu_write_data(card, *midiq->midibyte) < 0) {
  129. DPF(2, "emu10k1_mpuoutDpcCallback error!!\n");
  130. } else {
  131. ++cByteSent;
  132. --midiq->sizeLeft;
  133. ++midiq->midibyte;
  134. }
  135. }
  136. if (midiq->sizeLeft == 0) {
  137. if (doneq == NULL)
  138. doneq = midiq;
  139. card_mpuout->firstmidiq = midiq->next;
  140. } else
  141. break;
  142. }
  143. if (card_mpuout->firstmidiq == NULL)
  144. card_mpuout->lastmidiq = NULL;
  145. if (doneq != NULL) {
  146. while (doneq != card_mpuout->firstmidiq) {
  147. unsigned long callback_msg[3];
  148. midiq = doneq;
  149. doneq = midiq->next;
  150. if (midiq->qtype) {
  151. callback_msg[0] = 0;
  152. callback_msg[1] = midiq->length;
  153. callback_msg[2] = midiq->refdata;
  154. emu10k1_midi_callback(ICARDMIDI_OUTLONGDATA, card_mpuout->openinfo.refdata, callback_msg);
  155. } else if (((u8) midiq->refdata) < 0xF0 && ((u8) midiq->refdata) > 0x7F)
  156. card_mpuout->laststatus = (u8) midiq->refdata;
  157. kfree(midiq);
  158. }
  159. }
  160. if ((card_mpuout->firstmidiq != NULL) || cByteSent) {
  161. card_mpuout->intr = 0;
  162. emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
  163. }
  164. spin_unlock_irqrestore(&card_mpuout->lock, flags);
  165. return;
  166. }
  167. int emu10k1_mpuout_irqhandler(struct emu10k1_card *card)
  168. {
  169. struct emu10k1_mpuout *card_mpuout = card->mpuout;
  170. DPF(4, "emu10k1_mpuout_irqhandler\n");
  171. card_mpuout->intr = 1;
  172. emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
  173. tasklet_hi_schedule(&card_mpuout->tasklet);
  174. return 0;
  175. }