cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mixart_core.c (17688B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Driver for Digigram miXart soundcards
      4 *
      5 * low level interface with interrupt handling and mail box implementation
      6 *
      7 * Copyright (c) 2003 by Digigram <alsa@digigram.com>
      8 */
      9
     10#include <linux/interrupt.h>
     11#include <linux/mutex.h>
     12#include <linux/pci.h>
     13#include <linux/io.h>
     14
     15#include <sound/core.h>
     16#include "mixart.h"
     17#include "mixart_hwdep.h"
     18#include "mixart_core.h"
     19
     20
     21#define MSG_TIMEOUT_JIFFIES         (400 * HZ) / 1000 /* 400 ms */
     22
     23#define MSG_DESCRIPTOR_SIZE         0x24
     24#define MSG_HEADER_SIZE             (MSG_DESCRIPTOR_SIZE + 4)
     25
     26#define MSG_TYPE_MASK               0x00000003    /* mask for following types */
     27#define MSG_TYPE_NOTIFY             0             /* embedded -> driver (only notification, do not get_msg() !) */
     28#define MSG_TYPE_COMMAND            1             /* driver <-> embedded (a command has no answer) */
     29#define MSG_TYPE_REQUEST            2             /* driver -> embedded (request will get an answer back) */
     30#define MSG_TYPE_ANSWER             3             /* embedded -> driver */
     31#define MSG_CANCEL_NOTIFY_MASK      0x80000000    /* this bit is set for a notification that has been canceled */
     32
     33
     34static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame)
     35{
     36	/* read the message frame fifo */
     37	u32 headptr, tailptr;
     38
     39	tailptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL));
     40	headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_HEAD));
     41
     42	if (tailptr == headptr)
     43		return 0; /* no message posted */
     44
     45	if (tailptr < MSG_OUTBOUND_POST_STACK)
     46		return 0; /* error */
     47	if (tailptr >= MSG_OUTBOUND_POST_STACK + MSG_BOUND_STACK_SIZE)
     48		return 0; /* error */
     49
     50	*msg_frame = readl_be(MIXART_MEM(mgr, tailptr));
     51
     52	/* increment the tail index */
     53	tailptr += 4;
     54	if( tailptr >= (MSG_OUTBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) )
     55		tailptr = MSG_OUTBOUND_POST_STACK;
     56	writel_be(tailptr, MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL));
     57
     58	return 1;
     59}
     60
     61static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
     62		   u32 msg_frame_address )
     63{
     64	u32  headptr;
     65	u32  size;
     66	int  err;
     67#ifndef __BIG_ENDIAN
     68	unsigned int i;
     69#endif
     70
     71	err = 0;
     72
     73	/* copy message descriptor from miXart to driver */
     74	size                =  readl_be(MIXART_MEM(mgr, msg_frame_address));       /* size of descriptor + response */
     75	resp->message_id    =  readl_be(MIXART_MEM(mgr, msg_frame_address + 4));   /* dwMessageID */
     76	resp->uid.object_id =  readl_be(MIXART_MEM(mgr, msg_frame_address + 8));   /* uidDest */
     77	resp->uid.desc      =  readl_be(MIXART_MEM(mgr, msg_frame_address + 12));  /* */
     78
     79	if( (size < MSG_DESCRIPTOR_SIZE) || (resp->size < (size - MSG_DESCRIPTOR_SIZE))) {
     80		err = -EINVAL;
     81		dev_err(&mgr->pci->dev,
     82			"problem with response size = %d\n", size);
     83		goto _clean_exit;
     84	}
     85	size -= MSG_DESCRIPTOR_SIZE;
     86
     87	memcpy_fromio(resp->data, MIXART_MEM(mgr, msg_frame_address + MSG_HEADER_SIZE ), size);
     88	resp->size = size;
     89
     90	/* swap if necessary */
     91#ifndef __BIG_ENDIAN
     92	size /= 4; /* u32 size */
     93	for(i=0; i < size; i++) {
     94		((u32*)resp->data)[i] = be32_to_cpu(((__be32*)resp->data)[i]);
     95	}
     96#endif
     97
     98	/*
     99	 * free message frame address
    100	 */
    101	headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
    102
    103	if( (headptr < MSG_OUTBOUND_FREE_STACK) || ( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) {
    104		err = -EINVAL;
    105		goto _clean_exit;
    106	}
    107
    108	/* give address back to outbound fifo */
    109	writel_be(msg_frame_address, MIXART_MEM(mgr, headptr));
    110
    111	/* increment the outbound free head */
    112	headptr += 4;
    113	if( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) )
    114		headptr = MSG_OUTBOUND_FREE_STACK;
    115
    116	writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
    117
    118 _clean_exit:
    119	return err;
    120}
    121
    122
    123/*
    124 * send a message to miXart. return: the msg_frame used for this message
    125 */
    126/* call with mgr->msg_lock held! */
    127static int send_msg( struct mixart_mgr *mgr,
    128		     struct mixart_msg *msg,
    129		     int max_answersize,
    130		     int mark_pending,
    131		     u32 *msg_event)
    132{
    133	u32 headptr, tailptr;
    134	u32 msg_frame_address;
    135	int i;
    136
    137	if (snd_BUG_ON(msg->size % 4))
    138		return -EINVAL;
    139
    140	/* get message frame address */
    141	tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
    142	headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD));
    143
    144	if (tailptr == headptr) {
    145		dev_err(&mgr->pci->dev, "error: no message frame available\n");
    146		return -EBUSY;
    147	}
    148
    149	if( (tailptr < MSG_INBOUND_FREE_STACK) || (tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) {
    150		return -EINVAL;
    151	}
    152
    153	msg_frame_address = readl_be(MIXART_MEM(mgr, tailptr));
    154	writel(0, MIXART_MEM(mgr, tailptr)); /* set address to zero on this fifo position */
    155
    156	/* increment the inbound free tail */
    157	tailptr += 4;
    158	if( tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) )
    159		tailptr = MSG_INBOUND_FREE_STACK;
    160
    161	writel_be(tailptr, MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
    162
    163	/* TODO : use memcpy_toio() with intermediate buffer to copy the message */
    164
    165	/* copy message descriptor to card memory */
    166	writel_be( msg->size + MSG_DESCRIPTOR_SIZE,      MIXART_MEM(mgr, msg_frame_address) );      /* size of descriptor + request */
    167	writel_be( msg->message_id ,                     MIXART_MEM(mgr, msg_frame_address + 4) );  /* dwMessageID */
    168	writel_be( msg->uid.object_id,                   MIXART_MEM(mgr, msg_frame_address + 8) );  /* uidDest */
    169	writel_be( msg->uid.desc,                        MIXART_MEM(mgr, msg_frame_address + 12) ); /* */
    170	writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 16) ); /* SizeHeader */
    171	writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 20) ); /* OffsetDLL_T16 */
    172	writel_be( msg->size,                            MIXART_MEM(mgr, msg_frame_address + 24) ); /* SizeDLL_T16 */
    173	writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 28) ); /* OffsetDLL_DRV */
    174	writel_be( 0,                                    MIXART_MEM(mgr, msg_frame_address + 32) ); /* SizeDLL_DRV */
    175	writel_be( MSG_DESCRIPTOR_SIZE + max_answersize, MIXART_MEM(mgr, msg_frame_address + 36) ); /* dwExpectedAnswerSize */
    176
    177	/* copy message data to card memory */
    178	for( i=0; i < msg->size; i+=4 ) {
    179		writel_be( *(u32*)(msg->data + i), MIXART_MEM(mgr, MSG_HEADER_SIZE + msg_frame_address + i)  );
    180	}
    181
    182	if( mark_pending ) {
    183		if( *msg_event ) {
    184			/* the pending event is the notification we wait for ! */
    185			mgr->pending_event = *msg_event;
    186		}
    187		else {
    188			/* the pending event is the answer we wait for (same address than the request)! */
    189			mgr->pending_event = msg_frame_address;
    190
    191			/* copy address back to caller */
    192			*msg_event = msg_frame_address;
    193		}
    194	}
    195
    196	/* mark the frame as a request (will have an answer) */
    197	msg_frame_address |= MSG_TYPE_REQUEST;
    198
    199	/* post the frame */
    200	headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD));
    201
    202	if( (headptr < MSG_INBOUND_POST_STACK) || (headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE))) {
    203		return -EINVAL;
    204	}
    205
    206	writel_be(msg_frame_address, MIXART_MEM(mgr, headptr));
    207
    208	/* increment the inbound post head */
    209	headptr += 4;
    210	if( headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) )
    211		headptr = MSG_INBOUND_POST_STACK;
    212
    213	writel_be(headptr, MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD));
    214
    215	return 0;
    216}
    217
    218
    219int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int max_resp_size, void *resp_data)
    220{
    221	struct mixart_msg resp;
    222	u32 msg_frame = 0; /* set to 0, so it's no notification to wait for, but the answer */
    223	int err;
    224	wait_queue_entry_t wait;
    225	long timeout;
    226
    227	init_waitqueue_entry(&wait, current);
    228
    229	mutex_lock(&mgr->msg_lock);
    230	/* send the message */
    231	err = send_msg(mgr, request, max_resp_size, 1, &msg_frame);  /* send and mark the answer pending */
    232	if (err) {
    233		mutex_unlock(&mgr->msg_lock);
    234		return err;
    235	}
    236
    237	set_current_state(TASK_UNINTERRUPTIBLE);
    238	add_wait_queue(&mgr->msg_sleep, &wait);
    239	mutex_unlock(&mgr->msg_lock);
    240	timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
    241	remove_wait_queue(&mgr->msg_sleep, &wait);
    242
    243	if (! timeout) {
    244		/* error - no ack */
    245		dev_err(&mgr->pci->dev,
    246			"error: no response on msg %x\n", msg_frame);
    247		return -EIO;
    248	}
    249
    250	/* retrieve the answer into the same struct mixart_msg */
    251	resp.message_id = 0;
    252	resp.uid = (struct mixart_uid){0,0};
    253	resp.data = resp_data;
    254	resp.size = max_resp_size;
    255
    256	mutex_lock(&mgr->msg_lock);
    257	err = get_msg(mgr, &resp, msg_frame);
    258	mutex_unlock(&mgr->msg_lock);
    259
    260	if( request->message_id != resp.message_id )
    261		dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n");
    262
    263	return err;
    264}
    265
    266
    267int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr,
    268				   struct mixart_msg *request, u32 notif_event)
    269{
    270	int err;
    271	wait_queue_entry_t wait;
    272	long timeout;
    273
    274	if (snd_BUG_ON(!notif_event))
    275		return -EINVAL;
    276	if (snd_BUG_ON((notif_event & MSG_TYPE_MASK) != MSG_TYPE_NOTIFY))
    277		return -EINVAL;
    278	if (snd_BUG_ON(notif_event & MSG_CANCEL_NOTIFY_MASK))
    279		return -EINVAL;
    280
    281	init_waitqueue_entry(&wait, current);
    282
    283	mutex_lock(&mgr->msg_lock);
    284	/* send the message */
    285	err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, &notif_event);  /* send and mark the notification event pending */
    286	if(err) {
    287		mutex_unlock(&mgr->msg_lock);
    288		return err;
    289	}
    290
    291	set_current_state(TASK_UNINTERRUPTIBLE);
    292	add_wait_queue(&mgr->msg_sleep, &wait);
    293	mutex_unlock(&mgr->msg_lock);
    294	timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
    295	remove_wait_queue(&mgr->msg_sleep, &wait);
    296
    297	if (! timeout) {
    298		/* error - no ack */
    299		dev_err(&mgr->pci->dev,
    300			"error: notification %x not received\n", notif_event);
    301		return -EIO;
    302	}
    303
    304	return 0;
    305}
    306
    307
    308int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request)
    309{
    310	u32 message_frame;
    311	int err;
    312
    313	/* just send the message (do not mark it as a pending one) */
    314	mutex_lock(&mgr->msg_lock);
    315	err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame);
    316	mutex_unlock(&mgr->msg_lock);
    317
    318	/* the answer will be handled by snd_struct mixart_msgasklet()  */
    319	atomic_inc(&mgr->msg_processed);
    320
    321	return err;
    322}
    323
    324
    325/* common buffer of interrupt to send/receive messages */
    326static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4];
    327
    328
    329static void snd_mixart_process_msg(struct mixart_mgr *mgr)
    330{
    331	struct mixart_msg resp;
    332	u32 msg, addr, type;
    333	int err;
    334
    335	while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) {
    336		msg = mgr->msg_fifo[mgr->msg_fifo_readptr];
    337		mgr->msg_fifo_readptr++;
    338		mgr->msg_fifo_readptr %= MSG_FIFO_SIZE;
    339
    340		/* process the message ... */
    341		addr = msg & ~MSG_TYPE_MASK;
    342		type = msg & MSG_TYPE_MASK;
    343
    344		switch (type) {
    345		case MSG_TYPE_ANSWER:
    346			/* answer to a message on that we did not wait for (send_msg_nonblock) */
    347			resp.message_id = 0;
    348			resp.data = mixart_msg_data;
    349			resp.size = sizeof(mixart_msg_data);
    350			err = get_msg(mgr, &resp, addr);
    351			if( err < 0 ) {
    352				dev_err(&mgr->pci->dev,
    353					"error(%d) reading mf %x\n",
    354					err, msg);
    355				break;
    356			}
    357
    358			switch(resp.message_id) {
    359			case MSG_STREAM_START_INPUT_STAGE_PACKET:
    360			case MSG_STREAM_START_OUTPUT_STAGE_PACKET:
    361			case MSG_STREAM_STOP_INPUT_STAGE_PACKET:
    362			case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET:
    363				if(mixart_msg_data[0])
    364					dev_err(&mgr->pci->dev,
    365						"error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n",
    366						mixart_msg_data[0]);
    367				break;
    368			default:
    369				dev_dbg(&mgr->pci->dev,
    370					"received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
    371					   msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size);
    372				break;
    373			}
    374			break;
    375 		case MSG_TYPE_NOTIFY:
    376			/* msg contains no address ! do not get_msg() ! */
    377		case MSG_TYPE_COMMAND:
    378			/* get_msg() necessary */
    379		default:
    380			dev_err(&mgr->pci->dev,
    381				"doesn't know what to do with message %x\n",
    382				msg);
    383		} /* switch type */
    384
    385		/* decrement counter */
    386		atomic_dec(&mgr->msg_processed);
    387
    388	} /* while there is a msg in fifo */
    389}
    390
    391
    392irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
    393{
    394	struct mixart_mgr *mgr = dev_id;
    395	u32 it_reg;
    396
    397	it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET));
    398	if( !(it_reg & MIXART_OIDI) ) {
    399		/* this device did not cause the interrupt */
    400		return IRQ_NONE;
    401	}
    402
    403	/* mask all interrupts */
    404	writel_le(MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG(mgr, MIXART_PCI_OMIMR_OFFSET));
    405
    406	/* outdoorbell register clear */
    407	it_reg = readl(MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET));
    408	writel(it_reg, MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET));
    409
    410	/* clear interrupt */
    411	writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) );
    412
    413	return IRQ_WAKE_THREAD;
    414}
    415
    416irqreturn_t snd_mixart_threaded_irq(int irq, void *dev_id)
    417{
    418	struct mixart_mgr *mgr = dev_id;
    419	int err;
    420	struct mixart_msg resp;
    421	u32 msg;
    422
    423	mutex_lock(&mgr->lock);
    424	/* process interrupt */
    425	while (retrieve_msg_frame(mgr, &msg)) {
    426
    427		switch (msg & MSG_TYPE_MASK) {
    428		case MSG_TYPE_COMMAND:
    429			resp.message_id = 0;
    430			resp.data = mixart_msg_data;
    431			resp.size = sizeof(mixart_msg_data);
    432			err = get_msg(mgr, &resp, msg & ~MSG_TYPE_MASK);
    433			if( err < 0 ) {
    434				dev_err(&mgr->pci->dev,
    435					"interrupt: error(%d) reading mf %x\n",
    436					err, msg);
    437				break;
    438			}
    439
    440			if(resp.message_id == MSG_SERVICES_TIMER_NOTIFY) {
    441				int i;
    442				struct mixart_timer_notify *notify;
    443				notify = (struct mixart_timer_notify *)mixart_msg_data;
    444
    445				BUILD_BUG_ON(sizeof(notify) > sizeof(mixart_msg_data));
    446				if (snd_BUG_ON(notify->stream_count > ARRAY_SIZE(notify->streams)))
    447					break;
    448				for(i=0; i<notify->stream_count; i++) {
    449
    450					u32 buffer_id = notify->streams[i].buffer_id;
    451					unsigned int chip_number =  (buffer_id & MIXART_NOTIFY_CARD_MASK) >> MIXART_NOTIFY_CARD_OFFSET; /* card0 to 3 */
    452					unsigned int pcm_number  =  (buffer_id & MIXART_NOTIFY_PCM_MASK ) >> MIXART_NOTIFY_PCM_OFFSET;  /* pcm0 to 3  */
    453					unsigned int sub_number  =   buffer_id & MIXART_NOTIFY_SUBS_MASK;             /* 0 to MIXART_PLAYBACK_STREAMS */
    454					unsigned int is_capture  = ((buffer_id & MIXART_NOTIFY_CAPT_MASK) != 0);      /* playback == 0 / capture == 1 */
    455
    456					struct snd_mixart *chip  = mgr->chip[chip_number];
    457					struct mixart_stream *stream;
    458
    459					if ((chip_number >= mgr->num_cards) || (pcm_number >= MIXART_PCM_TOTAL) || (sub_number >= MIXART_PLAYBACK_STREAMS)) {
    460						dev_err(&mgr->pci->dev,
    461							"error MSG_SERVICES_TIMER_NOTIFY buffer_id (%x) pos(%d)\n",
    462							   buffer_id, notify->streams[i].sample_pos_low_part);
    463						break;
    464					}
    465
    466					if (is_capture)
    467						stream = &chip->capture_stream[pcm_number];
    468					else
    469						stream = &chip->playback_stream[pcm_number][sub_number];
    470
    471					if (stream->substream && (stream->status == MIXART_STREAM_STATUS_RUNNING)) {
    472						struct snd_pcm_runtime *runtime = stream->substream->runtime;
    473						int elapsed = 0;
    474						u64 sample_count = ((u64)notify->streams[i].sample_pos_high_part) << 32;
    475						sample_count |= notify->streams[i].sample_pos_low_part;
    476
    477						while (1) {
    478							u64 new_elapse_pos = stream->abs_period_elapsed +  runtime->period_size;
    479
    480							if (new_elapse_pos > sample_count) {
    481								break; /* while */
    482							}
    483							else {
    484								elapsed = 1;
    485								stream->buf_periods++;
    486								if (stream->buf_periods >= runtime->periods)
    487									stream->buf_periods = 0;
    488
    489								stream->abs_period_elapsed = new_elapse_pos;
    490							}
    491						}
    492						stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed );
    493
    494						if(elapsed) {
    495							mutex_unlock(&mgr->lock);
    496							snd_pcm_period_elapsed(stream->substream);
    497							mutex_lock(&mgr->lock);
    498						}
    499					}
    500				}
    501				break;
    502			}
    503			if(resp.message_id == MSG_SERVICES_REPORT_TRACES) {
    504				if(resp.size > 1) {
    505#ifndef __BIG_ENDIAN
    506					/* Traces are text: the swapped msg_data has to be swapped back ! */
    507					int i;
    508					for(i=0; i<(resp.size/4); i++) {
    509						((__be32*)mixart_msg_data)[i] = cpu_to_be32((mixart_msg_data)[i]);
    510					}
    511#endif
    512					((char*)mixart_msg_data)[resp.size - 1] = 0;
    513					dev_dbg(&mgr->pci->dev,
    514						"MIXART TRACE : %s\n",
    515						(char *)mixart_msg_data);
    516				}
    517				break;
    518			}
    519
    520			dev_dbg(&mgr->pci->dev, "command %x not handled\n",
    521				resp.message_id);
    522			break;
    523
    524		case MSG_TYPE_NOTIFY:
    525			if(msg & MSG_CANCEL_NOTIFY_MASK) {
    526				msg &= ~MSG_CANCEL_NOTIFY_MASK;
    527				dev_err(&mgr->pci->dev,
    528					"canceled notification %x !\n", msg);
    529			}
    530			fallthrough;
    531		case MSG_TYPE_ANSWER:
    532			/* answer or notification to a message we are waiting for*/
    533			mutex_lock(&mgr->msg_lock);
    534			if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) {
    535				wake_up(&mgr->msg_sleep);
    536				mgr->pending_event = 0;
    537			}
    538			/* answer to a message we did't want to wait for */
    539			else {
    540				mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg;
    541				mgr->msg_fifo_writeptr++;
    542				mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE;
    543				snd_mixart_process_msg(mgr);
    544			}
    545			mutex_unlock(&mgr->msg_lock);
    546			break;
    547		case MSG_TYPE_REQUEST:
    548		default:
    549			dev_dbg(&mgr->pci->dev,
    550				"interrupt received request %x\n", msg);
    551			/* TODO : are there things to do here ? */
    552			break;
    553		} /* switch on msg type */
    554	} /* while there are msgs */
    555
    556	/* allow interrupt again */
    557	writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
    558
    559	mutex_unlock(&mgr->lock);
    560
    561	return IRQ_HANDLED;
    562}
    563
    564
    565void snd_mixart_init_mailbox(struct mixart_mgr *mgr)
    566{
    567	writel( 0, MIXART_MEM( mgr, MSG_HOST_RSC_PROTECTION ) );
    568	writel( 0, MIXART_MEM( mgr, MSG_AGENT_RSC_PROTECTION ) );
    569
    570	/* allow outbound messagebox to generate interrupts */
    571	if(mgr->irq >= 0) {
    572		writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
    573	}
    574	return;
    575}
    576
    577void snd_mixart_exit_mailbox(struct mixart_mgr *mgr)
    578{
    579	/* no more interrupts on outbound messagebox */
    580	writel_le( MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
    581	return;
    582}
    583
    584void snd_mixart_reset_board(struct mixart_mgr *mgr)
    585{
    586	/* reset miXart */
    587	writel_be( 1, MIXART_REG(mgr, MIXART_BA1_BRUTAL_RESET_OFFSET) );
    588	return;
    589}