Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Driver for Digigram miXart soundcards
0004  *
0005  * low level interface with interrupt handling and mail box implementation
0006  *
0007  * Copyright (c) 2003 by Digigram <alsa@digigram.com>
0008  */
0009 
0010 #include <linux/interrupt.h>
0011 #include <linux/mutex.h>
0012 #include <linux/pci.h>
0013 #include <linux/io.h>
0014 
0015 #include <sound/core.h>
0016 #include "mixart.h"
0017 #include "mixart_hwdep.h"
0018 #include "mixart_core.h"
0019 
0020 
0021 #define MSG_TIMEOUT_JIFFIES         (400 * HZ) / 1000 /* 400 ms */
0022 
0023 #define MSG_DESCRIPTOR_SIZE         0x24
0024 #define MSG_HEADER_SIZE             (MSG_DESCRIPTOR_SIZE + 4)
0025 
0026 #define MSG_TYPE_MASK               0x00000003    /* mask for following types */
0027 #define MSG_TYPE_NOTIFY             0             /* embedded -> driver (only notification, do not get_msg() !) */
0028 #define MSG_TYPE_COMMAND            1             /* driver <-> embedded (a command has no answer) */
0029 #define MSG_TYPE_REQUEST            2             /* driver -> embedded (request will get an answer back) */
0030 #define MSG_TYPE_ANSWER             3             /* embedded -> driver */
0031 #define MSG_CANCEL_NOTIFY_MASK      0x80000000    /* this bit is set for a notification that has been canceled */
0032 
0033 
0034 static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame)
0035 {
0036     /* read the message frame fifo */
0037     u32 headptr, tailptr;
0038 
0039     tailptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL));
0040     headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_HEAD));
0041 
0042     if (tailptr == headptr)
0043         return 0; /* no message posted */
0044 
0045     if (tailptr < MSG_OUTBOUND_POST_STACK)
0046         return 0; /* error */
0047     if (tailptr >= MSG_OUTBOUND_POST_STACK + MSG_BOUND_STACK_SIZE)
0048         return 0; /* error */
0049 
0050     *msg_frame = readl_be(MIXART_MEM(mgr, tailptr));
0051 
0052     /* increment the tail index */
0053     tailptr += 4;
0054     if( tailptr >= (MSG_OUTBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) )
0055         tailptr = MSG_OUTBOUND_POST_STACK;
0056     writel_be(tailptr, MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL));
0057 
0058     return 1;
0059 }
0060 
0061 static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
0062            u32 msg_frame_address )
0063 {
0064     u32  headptr;
0065     u32  size;
0066     int  err;
0067 #ifndef __BIG_ENDIAN
0068     unsigned int i;
0069 #endif
0070 
0071     err = 0;
0072 
0073     /* copy message descriptor from miXart to driver */
0074     size                =  readl_be(MIXART_MEM(mgr, msg_frame_address));       /* size of descriptor + response */
0075     resp->message_id    =  readl_be(MIXART_MEM(mgr, msg_frame_address + 4));   /* dwMessageID */
0076     resp->uid.object_id =  readl_be(MIXART_MEM(mgr, msg_frame_address + 8));   /* uidDest */
0077     resp->uid.desc      =  readl_be(MIXART_MEM(mgr, msg_frame_address + 12));  /* */
0078 
0079     if( (size < MSG_DESCRIPTOR_SIZE) || (resp->size < (size - MSG_DESCRIPTOR_SIZE))) {
0080         err = -EINVAL;
0081         dev_err(&mgr->pci->dev,
0082             "problem with response size = %d\n", size);
0083         goto _clean_exit;
0084     }
0085     size -= MSG_DESCRIPTOR_SIZE;
0086 
0087     memcpy_fromio(resp->data, MIXART_MEM(mgr, msg_frame_address + MSG_HEADER_SIZE ), size);
0088     resp->size = size;
0089 
0090     /* swap if necessary */
0091 #ifndef __BIG_ENDIAN
0092     size /= 4; /* u32 size */
0093     for(i=0; i < size; i++) {
0094         ((u32*)resp->data)[i] = be32_to_cpu(((__be32*)resp->data)[i]);
0095     }
0096 #endif
0097 
0098     /*
0099      * free message frame address
0100      */
0101     headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
0102 
0103     if( (headptr < MSG_OUTBOUND_FREE_STACK) || ( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) {
0104         err = -EINVAL;
0105         goto _clean_exit;
0106     }
0107 
0108     /* give address back to outbound fifo */
0109     writel_be(msg_frame_address, MIXART_MEM(mgr, headptr));
0110 
0111     /* increment the outbound free head */
0112     headptr += 4;
0113     if( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) )
0114         headptr = MSG_OUTBOUND_FREE_STACK;
0115 
0116     writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
0117 
0118  _clean_exit:
0119     return err;
0120 }
0121 
0122 
0123 /*
0124  * send a message to miXart. return: the msg_frame used for this message
0125  */
0126 /* call with mgr->msg_lock held! */
0127 static int send_msg( struct mixart_mgr *mgr,
0128              struct mixart_msg *msg,
0129              int max_answersize,
0130              int mark_pending,
0131              u32 *msg_event)
0132 {
0133     u32 headptr, tailptr;
0134     u32 msg_frame_address;
0135     int i;
0136 
0137     if (snd_BUG_ON(msg->size % 4))
0138         return -EINVAL;
0139 
0140     /* get message frame address */
0141     tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
0142     headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD));
0143 
0144     if (tailptr == headptr) {
0145         dev_err(&mgr->pci->dev, "error: no message frame available\n");
0146         return -EBUSY;
0147     }
0148 
0149     if( (tailptr < MSG_INBOUND_FREE_STACK) || (tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) {
0150         return -EINVAL;
0151     }
0152 
0153     msg_frame_address = readl_be(MIXART_MEM(mgr, tailptr));
0154     writel(0, MIXART_MEM(mgr, tailptr)); /* set address to zero on this fifo position */
0155 
0156     /* increment the inbound free tail */
0157     tailptr += 4;
0158     if( tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) )
0159         tailptr = MSG_INBOUND_FREE_STACK;
0160 
0161     writel_be(tailptr, MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
0162 
0163     /* TODO : use memcpy_toio() with intermediate buffer to copy the message */
0164 
0165     /* copy message descriptor to card memory */
0166     writel_be( msg->size + MSG_DESCRIPTOR_SIZE,      MIXART_MEM(mgr, msg_frame_address) );      /* size of descriptor + request */
0167     writel_be( msg->message_id ,                     MIXART_MEM(mgr, msg_frame_address + 4) );  /* dwMessageID */
0168     writel_be( msg->uid.object_id,                   MIXART_MEM(mgr, msg_frame_address + 8) );  /* uidDest */
0169     writel_be( msg->uid.desc,                        MIXART_MEM(mgr, msg_frame_address + 12) ); /* */
0170     writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 16) ); /* SizeHeader */
0171     writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 20) ); /* OffsetDLL_T16 */
0172     writel_be( msg->size,                            MIXART_MEM(mgr, msg_frame_address + 24) ); /* SizeDLL_T16 */
0173     writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 28) ); /* OffsetDLL_DRV */
0174     writel_be( 0,                                    MIXART_MEM(mgr, msg_frame_address + 32) ); /* SizeDLL_DRV */
0175     writel_be( MSG_DESCRIPTOR_SIZE + max_answersize, MIXART_MEM(mgr, msg_frame_address + 36) ); /* dwExpectedAnswerSize */
0176 
0177     /* copy message data to card memory */
0178     for( i=0; i < msg->size; i+=4 ) {
0179         writel_be( *(u32*)(msg->data + i), MIXART_MEM(mgr, MSG_HEADER_SIZE + msg_frame_address + i)  );
0180     }
0181 
0182     if( mark_pending ) {
0183         if( *msg_event ) {
0184             /* the pending event is the notification we wait for ! */
0185             mgr->pending_event = *msg_event;
0186         }
0187         else {
0188             /* the pending event is the answer we wait for (same address than the request)! */
0189             mgr->pending_event = msg_frame_address;
0190 
0191             /* copy address back to caller */
0192             *msg_event = msg_frame_address;
0193         }
0194     }
0195 
0196     /* mark the frame as a request (will have an answer) */
0197     msg_frame_address |= MSG_TYPE_REQUEST;
0198 
0199     /* post the frame */
0200     headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD));
0201 
0202     if( (headptr < MSG_INBOUND_POST_STACK) || (headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE))) {
0203         return -EINVAL;
0204     }
0205 
0206     writel_be(msg_frame_address, MIXART_MEM(mgr, headptr));
0207 
0208     /* increment the inbound post head */
0209     headptr += 4;
0210     if( headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) )
0211         headptr = MSG_INBOUND_POST_STACK;
0212 
0213     writel_be(headptr, MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD));
0214 
0215     return 0;
0216 }
0217 
0218 
0219 int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int max_resp_size, void *resp_data)
0220 {
0221     struct mixart_msg resp;
0222     u32 msg_frame = 0; /* set to 0, so it's no notification to wait for, but the answer */
0223     int err;
0224     wait_queue_entry_t wait;
0225     long timeout;
0226 
0227     init_waitqueue_entry(&wait, current);
0228 
0229     mutex_lock(&mgr->msg_lock);
0230     /* send the message */
0231     err = send_msg(mgr, request, max_resp_size, 1, &msg_frame);  /* send and mark the answer pending */
0232     if (err) {
0233         mutex_unlock(&mgr->msg_lock);
0234         return err;
0235     }
0236 
0237     set_current_state(TASK_UNINTERRUPTIBLE);
0238     add_wait_queue(&mgr->msg_sleep, &wait);
0239     mutex_unlock(&mgr->msg_lock);
0240     timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
0241     remove_wait_queue(&mgr->msg_sleep, &wait);
0242 
0243     if (! timeout) {
0244         /* error - no ack */
0245         dev_err(&mgr->pci->dev,
0246             "error: no response on msg %x\n", msg_frame);
0247         return -EIO;
0248     }
0249 
0250     /* retrieve the answer into the same struct mixart_msg */
0251     resp.message_id = 0;
0252     resp.uid = (struct mixart_uid){0,0};
0253     resp.data = resp_data;
0254     resp.size = max_resp_size;
0255 
0256     mutex_lock(&mgr->msg_lock);
0257     err = get_msg(mgr, &resp, msg_frame);
0258     mutex_unlock(&mgr->msg_lock);
0259 
0260     if( request->message_id != resp.message_id )
0261         dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n");
0262 
0263     return err;
0264 }
0265 
0266 
0267 int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr,
0268                    struct mixart_msg *request, u32 notif_event)
0269 {
0270     int err;
0271     wait_queue_entry_t wait;
0272     long timeout;
0273 
0274     if (snd_BUG_ON(!notif_event))
0275         return -EINVAL;
0276     if (snd_BUG_ON((notif_event & MSG_TYPE_MASK) != MSG_TYPE_NOTIFY))
0277         return -EINVAL;
0278     if (snd_BUG_ON(notif_event & MSG_CANCEL_NOTIFY_MASK))
0279         return -EINVAL;
0280 
0281     init_waitqueue_entry(&wait, current);
0282 
0283     mutex_lock(&mgr->msg_lock);
0284     /* send the message */
0285     err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, &notif_event);  /* send and mark the notification event pending */
0286     if(err) {
0287         mutex_unlock(&mgr->msg_lock);
0288         return err;
0289     }
0290 
0291     set_current_state(TASK_UNINTERRUPTIBLE);
0292     add_wait_queue(&mgr->msg_sleep, &wait);
0293     mutex_unlock(&mgr->msg_lock);
0294     timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
0295     remove_wait_queue(&mgr->msg_sleep, &wait);
0296 
0297     if (! timeout) {
0298         /* error - no ack */
0299         dev_err(&mgr->pci->dev,
0300             "error: notification %x not received\n", notif_event);
0301         return -EIO;
0302     }
0303 
0304     return 0;
0305 }
0306 
0307 
0308 int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request)
0309 {
0310     u32 message_frame;
0311     int err;
0312 
0313     /* just send the message (do not mark it as a pending one) */
0314     mutex_lock(&mgr->msg_lock);
0315     err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame);
0316     mutex_unlock(&mgr->msg_lock);
0317 
0318     /* the answer will be handled by snd_struct mixart_msgasklet()  */
0319     atomic_inc(&mgr->msg_processed);
0320 
0321     return err;
0322 }
0323 
0324 
0325 /* common buffer of interrupt to send/receive messages */
0326 static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4];
0327 
0328 
0329 static void snd_mixart_process_msg(struct mixart_mgr *mgr)
0330 {
0331     struct mixart_msg resp;
0332     u32 msg, addr, type;
0333     int err;
0334 
0335     while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) {
0336         msg = mgr->msg_fifo[mgr->msg_fifo_readptr];
0337         mgr->msg_fifo_readptr++;
0338         mgr->msg_fifo_readptr %= MSG_FIFO_SIZE;
0339 
0340         /* process the message ... */
0341         addr = msg & ~MSG_TYPE_MASK;
0342         type = msg & MSG_TYPE_MASK;
0343 
0344         switch (type) {
0345         case MSG_TYPE_ANSWER:
0346             /* answer to a message on that we did not wait for (send_msg_nonblock) */
0347             resp.message_id = 0;
0348             resp.data = mixart_msg_data;
0349             resp.size = sizeof(mixart_msg_data);
0350             err = get_msg(mgr, &resp, addr);
0351             if( err < 0 ) {
0352                 dev_err(&mgr->pci->dev,
0353                     "error(%d) reading mf %x\n",
0354                     err, msg);
0355                 break;
0356             }
0357 
0358             switch(resp.message_id) {
0359             case MSG_STREAM_START_INPUT_STAGE_PACKET:
0360             case MSG_STREAM_START_OUTPUT_STAGE_PACKET:
0361             case MSG_STREAM_STOP_INPUT_STAGE_PACKET:
0362             case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET:
0363                 if(mixart_msg_data[0])
0364                     dev_err(&mgr->pci->dev,
0365                         "error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n",
0366                         mixart_msg_data[0]);
0367                 break;
0368             default:
0369                 dev_dbg(&mgr->pci->dev,
0370                     "received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
0371                        msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size);
0372                 break;
0373             }
0374             break;
0375         case MSG_TYPE_NOTIFY:
0376             /* msg contains no address ! do not get_msg() ! */
0377         case MSG_TYPE_COMMAND:
0378             /* get_msg() necessary */
0379         default:
0380             dev_err(&mgr->pci->dev,
0381                 "doesn't know what to do with message %x\n",
0382                 msg);
0383         } /* switch type */
0384 
0385         /* decrement counter */
0386         atomic_dec(&mgr->msg_processed);
0387 
0388     } /* while there is a msg in fifo */
0389 }
0390 
0391 
0392 irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
0393 {
0394     struct mixart_mgr *mgr = dev_id;
0395     u32 it_reg;
0396 
0397     it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET));
0398     if( !(it_reg & MIXART_OIDI) ) {
0399         /* this device did not cause the interrupt */
0400         return IRQ_NONE;
0401     }
0402 
0403     /* mask all interrupts */
0404     writel_le(MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG(mgr, MIXART_PCI_OMIMR_OFFSET));
0405 
0406     /* outdoorbell register clear */
0407     it_reg = readl(MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET));
0408     writel(it_reg, MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET));
0409 
0410     /* clear interrupt */
0411     writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) );
0412 
0413     return IRQ_WAKE_THREAD;
0414 }
0415 
0416 irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id)
0417 {
0418     struct mixart_mgr *mgr = dev_id;
0419     int err;
0420     struct mixart_msg resp;
0421     u32 msg;
0422 
0423     mutex_lock(&mgr->lock);
0424     /* process interrupt */
0425     while (retrieve_msg_frame(mgr, &msg)) {
0426 
0427         switch (msg & MSG_TYPE_MASK) {
0428         case MSG_TYPE_COMMAND:
0429             resp.message_id = 0;
0430             resp.data = mixart_msg_data;
0431             resp.size = sizeof(mixart_msg_data);
0432             err = get_msg(mgr, &resp, msg & ~MSG_TYPE_MASK);
0433             if( err < 0 ) {
0434                 dev_err(&mgr->pci->dev,
0435                     "interrupt: error(%d) reading mf %x\n",
0436                     err, msg);
0437                 break;
0438             }
0439 
0440             if(resp.message_id == MSG_SERVICES_TIMER_NOTIFY) {
0441                 int i;
0442                 struct mixart_timer_notify *notify;
0443                 notify = (struct mixart_timer_notify *)mixart_msg_data;
0444 
0445                 BUILD_BUG_ON(sizeof(notify) > sizeof(mixart_msg_data));
0446                 if (snd_BUG_ON(notify->stream_count > ARRAY_SIZE(notify->streams)))
0447                     break;
0448                 for(i=0; i<notify->stream_count; i++) {
0449 
0450                     u32 buffer_id = notify->streams[i].buffer_id;
0451                     unsigned int chip_number =  (buffer_id & MIXART_NOTIFY_CARD_MASK) >> MIXART_NOTIFY_CARD_OFFSET; /* card0 to 3 */
0452                     unsigned int pcm_number  =  (buffer_id & MIXART_NOTIFY_PCM_MASK ) >> MIXART_NOTIFY_PCM_OFFSET;  /* pcm0 to 3  */
0453                     unsigned int sub_number  =   buffer_id & MIXART_NOTIFY_SUBS_MASK;             /* 0 to MIXART_PLAYBACK_STREAMS */
0454                     unsigned int is_capture  = ((buffer_id & MIXART_NOTIFY_CAPT_MASK) != 0);      /* playback == 0 / capture == 1 */
0455 
0456                     struct snd_mixart *chip  = mgr->chip[chip_number];
0457                     struct mixart_stream *stream;
0458 
0459                     if ((chip_number >= mgr->num_cards) || (pcm_number >= MIXART_PCM_TOTAL) || (sub_number >= MIXART_PLAYBACK_STREAMS)) {
0460                         dev_err(&mgr->pci->dev,
0461                             "error MSG_SERVICES_TIMER_NOTIFY buffer_id (%x) pos(%d)\n",
0462                                buffer_id, notify->streams[i].sample_pos_low_part);
0463                         break;
0464                     }
0465 
0466                     if (is_capture)
0467                         stream = &chip->capture_stream[pcm_number];
0468                     else
0469                         stream = &chip->playback_stream[pcm_number][sub_number];
0470 
0471                     if (stream->substream && (stream->status == MIXART_STREAM_STATUS_RUNNING)) {
0472                         struct snd_pcm_runtime *runtime = stream->substream->runtime;
0473                         int elapsed = 0;
0474                         u64 sample_count = ((u64)notify->streams[i].sample_pos_high_part) << 32;
0475                         sample_count |= notify->streams[i].sample_pos_low_part;
0476 
0477                         while (1) {
0478                             u64 new_elapse_pos = stream->abs_period_elapsed +  runtime->period_size;
0479 
0480                             if (new_elapse_pos > sample_count) {
0481                                 break; /* while */
0482                             }
0483                             else {
0484                                 elapsed = 1;
0485                                 stream->buf_periods++;
0486                                 if (stream->buf_periods >= runtime->periods)
0487                                     stream->buf_periods = 0;
0488 
0489                                 stream->abs_period_elapsed = new_elapse_pos;
0490                             }
0491                         }
0492                         stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed );
0493 
0494                         if(elapsed) {
0495                             mutex_unlock(&mgr->lock);
0496                             snd_pcm_period_elapsed(stream->substream);
0497                             mutex_lock(&mgr->lock);
0498                         }
0499                     }
0500                 }
0501                 break;
0502             }
0503             if(resp.message_id == MSG_SERVICES_REPORT_TRACES) {
0504                 if(resp.size > 1) {
0505 #ifndef __BIG_ENDIAN
0506                     /* Traces are text: the swapped msg_data has to be swapped back ! */
0507                     int i;
0508                     for(i=0; i<(resp.size/4); i++) {
0509                         ((__be32*)mixart_msg_data)[i] = cpu_to_be32((mixart_msg_data)[i]);
0510                     }
0511 #endif
0512                     ((char*)mixart_msg_data)[resp.size - 1] = 0;
0513                     dev_dbg(&mgr->pci->dev,
0514                         "MIXART TRACE : %s\n",
0515                         (char *)mixart_msg_data);
0516                 }
0517                 break;
0518             }
0519 
0520             dev_dbg(&mgr->pci->dev, "command %x not handled\n",
0521                 resp.message_id);
0522             break;
0523 
0524         case MSG_TYPE_NOTIFY:
0525             if(msg & MSG_CANCEL_NOTIFY_MASK) {
0526                 msg &= ~MSG_CANCEL_NOTIFY_MASK;
0527                 dev_err(&mgr->pci->dev,
0528                     "canceled notification %x !\n", msg);
0529             }
0530             fallthrough;
0531         case MSG_TYPE_ANSWER:
0532             /* answer or notification to a message we are waiting for*/
0533             mutex_lock(&mgr->msg_lock);
0534             if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) {
0535                 wake_up(&mgr->msg_sleep);
0536                 mgr->pending_event = 0;
0537             }
0538             /* answer to a message we did't want to wait for */
0539             else {
0540                 mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg;
0541                 mgr->msg_fifo_writeptr++;
0542                 mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE;
0543                 snd_mixart_process_msg(mgr);
0544             }
0545             mutex_unlock(&mgr->msg_lock);
0546             break;
0547         case MSG_TYPE_REQUEST:
0548         default:
0549             dev_dbg(&mgr->pci->dev,
0550                 "interrupt received request %x\n", msg);
0551             /* TODO : are there things to do here ? */
0552             break;
0553         } /* switch on msg type */
0554     } /* while there are msgs */
0555 
0556     /* allow interrupt again */
0557     writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
0558 
0559     mutex_unlock(&mgr->lock);
0560 
0561     return IRQ_HANDLED;
0562 }
0563 
0564 
0565 void snd_mixart_init_mailbox(struct mixart_mgr *mgr)
0566 {
0567     writel( 0, MIXART_MEM( mgr, MSG_HOST_RSC_PROTECTION ) );
0568     writel( 0, MIXART_MEM( mgr, MSG_AGENT_RSC_PROTECTION ) );
0569 
0570     /* allow outbound messagebox to generate interrupts */
0571     if(mgr->irq >= 0) {
0572         writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
0573     }
0574     return;
0575 }
0576 
0577 void snd_mixart_exit_mailbox(struct mixart_mgr *mgr)
0578 {
0579     /* no more interrupts on outbound messagebox */
0580     writel_le( MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
0581     return;
0582 }
0583 
0584 void snd_mixart_reset_board(struct mixart_mgr *mgr)
0585 {
0586     /* reset miXart */
0587     writel_be( 1, MIXART_REG(mgr, MIXART_BA1_BRUTAL_RESET_OFFSET) );
0588     return;
0589 }