cardmo.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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, 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, 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, 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_irqhandlern");
  171. card_mpuout->intr = 1;
  172. emu10k1_irq_disable(card, INTE_MIDITXENABLE);
  173. tasklet_hi_schedule(&card_mpuout->tasklet);
  174. return 0;
  175. }