cardmo.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
- /*
- **********************************************************************
- * cardmo.c - MIDI UART output HAL for emu10k1 driver
- * Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- * Date Author Summary of changes
- * ---- ------ ------------------
- * October 20, 1999 Bertrand Lee base code release
- * November 2, 1999 Alan Cox cleaned up
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- **********************************************************************
- */
- #include <linux/slab.h>
- #include "hwaccess.h"
- #include "8010.h"
- #include "cardmo.h"
- #include "irqmgr.h"
- /* Installs the IRQ handler for the MPU out port *
- * and initialize parameters */
- int emu10k1_mpuout_open(struct emu10k1_card *card, struct midi_openinfo *openinfo)
- {
- struct emu10k1_mpuout *card_mpuout = card->mpuout;
- DPF(2, "emu10k1_mpuout_open()n");
- if (!(card_mpuout->status & FLAGS_AVAILABLE))
- return -1;
- /* Copy open info and mark channel as in use */
- card_mpuout->intr = 0;
- card_mpuout->openinfo = *openinfo;
- card_mpuout->status &= ~FLAGS_AVAILABLE;
- card_mpuout->laststatus = 0x80;
- card_mpuout->firstmidiq = NULL;
- card_mpuout->lastmidiq = NULL;
- emu10k1_mpu_reset(card);
- emu10k1_mpu_acquire(card);
- return 0;
- }
- int emu10k1_mpuout_close(struct emu10k1_card *card)
- {
- struct emu10k1_mpuout *card_mpuout = card->mpuout;
- struct midi_queue *midiq;
- struct midi_hdr *midihdr;
- unsigned long flags;
- DPF(2, "emu10k1_mpuout_close()n");
- emu10k1_irq_disable(card, INTE_MIDITXENABLE);
- spin_lock_irqsave(&card_mpuout->lock, flags);
- while (card_mpuout->firstmidiq != NULL) {
- midiq = card_mpuout->firstmidiq;
- midihdr = (struct midi_hdr *) midiq->refdata;
- card_mpuout->firstmidiq = midiq->next;
- kfree(midihdr->data);
- kfree(midihdr);
- kfree(midiq);
- }
- card_mpuout->lastmidiq = NULL;
- emu10k1_mpu_release(card);
- card_mpuout->status |= FLAGS_AVAILABLE;
- spin_unlock_irqrestore(&card_mpuout->lock, flags);
- return 0;
- }
- /* If there isn't enough buffer space, reject Midi Buffer. *
- * Otherwise, disable TX, create object to hold Midi *
- * uffer, update buffer flags and other parameters *
- * before enabling TX again. */
- int emu10k1_mpuout_add_buffer(struct emu10k1_card *card, struct midi_hdr *midihdr)
- {
- struct emu10k1_mpuout *card_mpuout = card->mpuout;
- struct midi_queue *midiq;
- unsigned long flags;
- DPF(2, "emu10k1_mpuout_add_buffer()n");
- if (card_mpuout->state == CARDMIDIOUT_STATE_SUSPEND)
- return 0;
- midihdr->flags |= MIDIBUF_INQUEUE;
- midihdr->flags &= ~MIDIBUF_DONE;
- if ((midiq = (struct midi_queue *) kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
- /* Message lost */
- return -1;
- }
- midiq->next = NULL;
- midiq->qtype = 1;
- midiq->length = midihdr->bufferlength;
- midiq->sizeLeft = midihdr->bufferlength;
- midiq->midibyte = midihdr->data;
- midiq->refdata = (unsigned long) midihdr;
- spin_lock_irqsave(&card_mpuout->lock, flags);
- if (card_mpuout->firstmidiq == NULL) {
- card_mpuout->firstmidiq = midiq;
- card_mpuout->lastmidiq = midiq;
- } else {
- (card_mpuout->lastmidiq)->next = midiq;
- card_mpuout->lastmidiq = midiq;
- }
- card_mpuout->intr = 0;
- emu10k1_irq_enable(card, INTE_MIDITXENABLE);
- spin_unlock_irqrestore(&card_mpuout->lock, flags);
- return 0;
- }
- void emu10k1_mpuout_bh(unsigned long refdata)
- {
- struct emu10k1_card *card = (struct emu10k1_card *) refdata;
- struct emu10k1_mpuout *card_mpuout = card->mpuout;
- int cByteSent = 0;
- struct midi_queue *midiq;
- struct midi_queue *doneq = NULL;
- unsigned long flags;
- spin_lock_irqsave(&card_mpuout->lock, flags);
- while (card_mpuout->firstmidiq != NULL) {
- midiq = card_mpuout->firstmidiq;
- while (cByteSent < 4 && midiq->sizeLeft) {
- if (emu10k1_mpu_write_data(card, *midiq->midibyte) < 0) {
- DPF(2, "emu10k1_mpuoutDpcCallback error!!n");
- } else {
- ++cByteSent;
- --midiq->sizeLeft;
- ++midiq->midibyte;
- }
- }
- if (midiq->sizeLeft == 0) {
- if (doneq == NULL)
- doneq = midiq;
- card_mpuout->firstmidiq = midiq->next;
- } else
- break;
- }
- if (card_mpuout->firstmidiq == NULL)
- card_mpuout->lastmidiq = NULL;
- if (doneq != NULL) {
- while (doneq != card_mpuout->firstmidiq) {
- unsigned long callback_msg[3];
- midiq = doneq;
- doneq = midiq->next;
- if (midiq->qtype) {
- callback_msg[0] = 0;
- callback_msg[1] = midiq->length;
- callback_msg[2] = midiq->refdata;
- emu10k1_midi_callback(ICARDMIDI_OUTLONGDATA, card_mpuout->openinfo.refdata, callback_msg);
- } else if (((u8) midiq->refdata) < 0xF0 && ((u8) midiq->refdata) > 0x7F)
- card_mpuout->laststatus = (u8) midiq->refdata;
- kfree(midiq);
- }
- }
- if ((card_mpuout->firstmidiq != NULL) || cByteSent) {
- card_mpuout->intr = 0;
- emu10k1_irq_enable(card, INTE_MIDITXENABLE);
- }
- spin_unlock_irqrestore(&card_mpuout->lock, flags);
- return;
- }
- int emu10k1_mpuout_irqhandler(struct emu10k1_card *card)
- {
- struct emu10k1_mpuout *card_mpuout = card->mpuout;
- DPF(4, "emu10k1_mpuout_irqhandlern");
- card_mpuout->intr = 1;
- emu10k1_irq_disable(card, INTE_MIDITXENABLE);
- tasklet_hi_schedule(&card_mpuout->tasklet);
- return 0;
- }