changes from Greg Crain on his mpu401 module, Thanks!
style fixes git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17573 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -2,5 +2,6 @@ SubDir HAIKU_TOP src add-ons kernel generic mpu401 ;
|
|||||||
|
|
||||||
KernelAddon mpu401 : kernel generic :
|
KernelAddon mpu401 : kernel generic :
|
||||||
mpu401.c
|
mpu401.c
|
||||||
|
debug.c
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* BeOS Driver for Intel ICH AC'97 Link interface
|
||||||
|
*
|
||||||
|
* Copyright (c) 2002, Marcus Overhagen <[email protected]>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||||
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <OS.h>
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define DRIVER_NAME "mpu401"
|
||||||
|
#define VERSION "0.2"
|
||||||
|
|
||||||
|
void debug_printf(const char *text,...)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap,text);
|
||||||
|
vsprintf(buf,text,ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
dprintf(DRIVER_NAME ": %s",buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG > 0
|
||||||
|
|
||||||
|
static const char * logfile="/boot/home/mpu401.log";
|
||||||
|
static sem_id loglock;
|
||||||
|
|
||||||
|
void log_create(void)
|
||||||
|
{
|
||||||
|
int fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
const char *text = DRIVER_NAME ", " VERSION "\n";
|
||||||
|
loglock = create_sem(1,"logfile sem");
|
||||||
|
write(fd,text,strlen(text));
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_printf(const char *text,...)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char buf[1024];
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap,text);
|
||||||
|
vsprintf(buf,text,ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
dprintf(DRIVER_NAME ": %s",buf);
|
||||||
|
|
||||||
|
acquire_sem(loglock);
|
||||||
|
fd = open(logfile, O_WRONLY | O_APPEND);
|
||||||
|
write(fd,buf,strlen(buf));
|
||||||
|
close(fd);
|
||||||
|
release_sem(loglock);
|
||||||
|
|
||||||
|
#if DEBUG > 1
|
||||||
|
snooze(150000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* BeOS Driver for Intel ICH AC'97 Link interface
|
||||||
|
*
|
||||||
|
* Copyright (c) 2002, Marcus Overhagen <[email protected]>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||||
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _DEBUG_H_
|
||||||
|
#define _DEBUG_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PRINT() executes dprintf if DEBUG = 0 (disabled), or expands to LOG() when DEBUG > 0
|
||||||
|
* TRACE() executes dprintf if DEBUG > 0
|
||||||
|
* LOG() executes dprintf and writes to the logfile if DEBUG > 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* DEBUG == 0, no debugging, PRINT writes to syslog
|
||||||
|
* DEBUG == 1, TRACE & LOG, PRINT
|
||||||
|
* DEBUG == 2, TRACE & LOG, PRINT with snooze()
|
||||||
|
*/
|
||||||
|
#ifndef DEBUG
|
||||||
|
#define DEBUG 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef PRINT
|
||||||
|
#undef TRACE
|
||||||
|
#undef ASSERT
|
||||||
|
|
||||||
|
void debug_printf(const char *text,...);
|
||||||
|
|
||||||
|
#if DEBUG > 0
|
||||||
|
#define PRINT(a) log_printf a
|
||||||
|
#define TRACE(a) debug_printf a
|
||||||
|
#define LOG(a) log_printf a
|
||||||
|
#define LOG_CREATE() log_create()
|
||||||
|
#define DEBUG_ONLY(a) a
|
||||||
|
#define ASSERT(a) if (a) {} else LOG(("ASSERT failed! file = %s, line = %d\n",__FILE__,__LINE__))
|
||||||
|
void log_create(void);
|
||||||
|
void log_printf(const char *text,...);
|
||||||
|
#else
|
||||||
|
#define PRINT(a) debug_printf a
|
||||||
|
#define TRACE(a) ((void)(0))
|
||||||
|
#define ASSERT(a) ((void)(0))
|
||||||
|
#define LOG(a) ((void)(0))
|
||||||
|
#define LOG_CREATE()
|
||||||
|
#define DEBUG_ONLY(a)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,26 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* OpenBeOS
|
* Copyright 2003-2006, Haiku.
|
||||||
* A module driver for the generic mpu401 midi interface
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003 Greg Crain
|
* A module driver for the generic mpu401 midi interface.
|
||||||
* All rights reserved.
|
*
|
||||||
* This software is released under the MIT/OpenBeOS license.
|
* Author:
|
||||||
*
|
* Greg Crain ([email protected])
|
||||||
* mpu401.c
|
*
|
||||||
*/
|
* mpu401.c
|
||||||
|
*/
|
||||||
|
|
||||||
#include <OS.h>
|
|
||||||
#include <KernelExport.h>
|
|
||||||
#include <ISA.h>
|
#include <ISA.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <OS.h>
|
||||||
#include <midi_driver.h>
|
#include <midi_driver.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "debug.h"
|
||||||
#include "mpu401_priv.h"
|
#include "mpu401_priv.h"
|
||||||
|
|
||||||
|
|
||||||
// UART data port = addr
|
|
||||||
// UART cmd port = addr +1
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
midi_create_device -
|
midi_create_device -
|
||||||
----- */
|
----- */
|
||||||
@@ -31,32 +30,27 @@
|
|||||||
static status_t
|
static status_t
|
||||||
create_device(int port, void ** out_storage, uint32 workarounds, void (*interrupt_op)(int32 op, void * card), void * card)
|
create_device(int port, void ** out_storage, uint32 workarounds, void (*interrupt_op)(int32 op, void * card), void * card)
|
||||||
{
|
{
|
||||||
mpu401device mpu_device;
|
mpu401device mpu_device;
|
||||||
mpu401device *mpuptr;
|
mpu401device *mpuptr;
|
||||||
|
|
||||||
/* fill the structure with specific info from caller */
|
/* fill the structure with specific info from caller */
|
||||||
mpu_device.dataport = port;
|
mpu_device.addrport = port;
|
||||||
mpu_device.cmdport = port+1;
|
mpu_device.workarounds = workarounds;
|
||||||
mpu_device.workarounds = workarounds;
|
mpu_device.V2 = FALSE;
|
||||||
mpu_device.V2 = FALSE;
|
mpu_device.count = 1;
|
||||||
mpu_device.count = 1;
|
mpu_device.interrupt_op = interrupt_op;
|
||||||
mpu_device.interrupt_op = interrupt_op;
|
mpu_device.card = card;
|
||||||
|
|
||||||
#if MPUDEBUG
|
LOG(("create_device count= %ld, addrport 0x%x, workarounds: %d",mpu_device.count, mpu_device.addrport, mpu_device.workarounds));
|
||||||
dprintf("mpu401:create_device - count = %ld ,",mpu_device.count);
|
|
||||||
dprintf("dataport 0x%x ,",mpu_device.dataport);
|
|
||||||
dprintf("workarounds: %d\n",mpu_device.workarounds);
|
|
||||||
dprintf("**outstorage: %p\n",out_storage);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// basically, each call to create device allocates memory for
|
// basically, each call to create device allocates memory for
|
||||||
//a structure with the specific device info. The pointer to this is
|
//a structure with the specific device info. The pointer to this is
|
||||||
// returned back to calling driver
|
// returned back to calling driver
|
||||||
mpuptr = (mpu401device*)malloc ( sizeof(mpu401device));
|
mpuptr = (mpu401device*)malloc (sizeof(mpu401device));
|
||||||
memcpy ( mpuptr, &mpu_device, sizeof(mpu_device));
|
memcpy(mpuptr, &mpu_device, sizeof(mpu_device));
|
||||||
*out_storage = (void *)mpuptr;
|
*out_storage = (void *)mpuptr;
|
||||||
|
|
||||||
return (B_OK);
|
return B_OK;
|
||||||
}
|
}
|
||||||
/*-----------------------------*/
|
/*-----------------------------*/
|
||||||
/* Version 2 of mpu401 module */
|
/* Version 2 of mpu401 module */
|
||||||
@@ -65,15 +59,11 @@ create_device(int port, void ** out_storage, uint32 workarounds, void (*interrup
|
|||||||
static status_t
|
static status_t
|
||||||
create_device_v2(int port, void ** out_storage, uint32 workarounds, void (*interrupt_op)(int32 op, void * card), void * card)
|
create_device_v2(int port, void ** out_storage, uint32 workarounds, void (*interrupt_op)(int32 op, void * card), void * card)
|
||||||
{
|
{
|
||||||
mpu401device *mpuptr;
|
mpu401device *mpuptr;
|
||||||
mpu401device mpu_device;
|
mpu401device mpu_device;
|
||||||
|
|
||||||
|
LOG(("v2: create_device, **out_storage %p ,workarounds %ld ,void *card %p\n",out_storage, workarounds, card));
|
||||||
|
|
||||||
#if MPUDEBUG
|
|
||||||
dprintf("mpu401_v2: create_device\n");
|
|
||||||
dprintf("mpu401_v2: **out_storage %p ,",out_storage);
|
|
||||||
dprintf("workarounds %ld ,",workarounds);
|
|
||||||
dprintf("void *card %p\n",card);
|
|
||||||
#endif
|
|
||||||
// not sure exactly how v2 of the module works. I think that two ports are
|
// not sure exactly how v2 of the module works. I think that two ports are
|
||||||
// created. One for midi in data, and another for midi out data.
|
// created. One for midi in data, and another for midi out data.
|
||||||
// Instead of transfering data using a buffer and pointer, the midi
|
// Instead of transfering data using a buffer and pointer, the midi
|
||||||
@@ -87,18 +77,18 @@ create_device_v2(int port, void ** out_storage, uint32 workarounds, void (*inter
|
|||||||
// those calls, it needs to be known whether the mididata is to be read/written
|
// those calls, it needs to be known whether the mididata is to be read/written
|
||||||
// to a buffer, or to the port.
|
// to a buffer, or to the port.
|
||||||
|
|
||||||
mpu_device.dataport = port;
|
mpu_device.addrport = port;
|
||||||
mpu_device.cmdport = port+1;
|
|
||||||
mpu_device.workarounds = workarounds;
|
mpu_device.workarounds = workarounds;
|
||||||
mpu_device.V2 = TRUE;
|
mpu_device.V2 = TRUE;
|
||||||
mpu_device.count =1;
|
mpu_device.count =1;
|
||||||
|
mpu_device.card = card;
|
||||||
|
|
||||||
|
|
||||||
mpuptr = (mpu401device*)malloc ( sizeof(mpu401device));
|
mpuptr = (mpu401device*)malloc(sizeof(mpu401device));
|
||||||
memcpy ( mpuptr, &mpu_device, sizeof(mpu_device));
|
memcpy(mpuptr, &mpu_device, sizeof(mpu_device));
|
||||||
*out_storage = (void *)mpuptr;
|
*out_storage = (void *)mpuptr;
|
||||||
|
|
||||||
return (B_OK);
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -108,21 +98,15 @@ create_device_v2(int port, void ** out_storage, uint32 workarounds, void (*inter
|
|||||||
static status_t
|
static status_t
|
||||||
delete_device(void * storage)
|
delete_device(void * storage)
|
||||||
{
|
{
|
||||||
mpu401device * mpu_device = (mpu401device *)storage;
|
mpu401device * mpu_device = (mpu401device *)storage;
|
||||||
|
|
||||||
#if MPUDEBUG
|
LOG(("device->addrport= 0x%x count= %ld\n",mpu_device->addrport, mpu_device->count));
|
||||||
dprintf("mpu_device->dataport = 0x%x\n",mpu_device->dataport);
|
LOG(("delete_device: *storage:%p\n",storage));
|
||||||
dprintf("mpu_device->count = %ld\n",mpu_device->count);
|
|
||||||
#endif
|
free(storage); // free the memory allocated in create_device
|
||||||
// if (mpu_device->count <=0)
|
|
||||||
// return (B_ERROR);
|
|
||||||
// else
|
|
||||||
|
|
||||||
dprintf("mpu401: delete_device: *storage:%p\n",storage);
|
|
||||||
free(storage); // free the memory allocated in create_device
|
|
||||||
atomic_add(&mpu_device->count,-1);
|
atomic_add(&mpu_device->count,-1);
|
||||||
|
|
||||||
return (B_OK);
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
@@ -132,71 +116,69 @@ delete_device(void * storage)
|
|||||||
static status_t
|
static status_t
|
||||||
midi_open(void * storage, uint32 flags, void ** out_cookie)
|
midi_open(void * storage, uint32 flags, void ** out_cookie)
|
||||||
{
|
{
|
||||||
char semname[25];
|
char semname[25];
|
||||||
int ack_byte;
|
int ack_byte;
|
||||||
mpu401device * mpu_device = (mpu401device *)storage;
|
mpu401device * mpu_device = (mpu401device *)storage;
|
||||||
|
|
||||||
#if MPUDEBUG
|
LOG(("open() flags: %ld, * storage: %p, **out_cookie: %p\n",flags, storage,out_cookie));
|
||||||
dprintf("mpu401: midi_open() flags: %ld,",flags);
|
LOG(("open: device->addrport 0x%x ,workarounds 0x%x\n",mpu_device->addrport, mpu_device->workarounds));
|
||||||
dprintf(" * storage: %p,", storage);
|
|
||||||
dprintf(" **out_cookie: %p\n",out_cookie);
|
|
||||||
dprintf("mpu401:@open: mpu_device->dataport 0x%x\n",mpu_device->dataport);
|
|
||||||
dprintf("mpu401:@open: mpu_device->workarounds %d\n",mpu_device->workarounds);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// the undocumented V2 module is not complete
|
// the undocumented V2 module is not complete
|
||||||
// we will allow the device to be created since some drivers depend on it
|
// we will allow the device to be created since some drivers depend on it
|
||||||
// but will return an error if the actual midi device is opened:
|
// but will return an error if the actual midi device is opened:
|
||||||
if ( mpu_device->V2 == TRUE)
|
if ( mpu_device->V2 == TRUE)
|
||||||
return (B_ERROR);
|
return B_ERROR;
|
||||||
|
|
||||||
switch (mpu_device->workarounds){
|
switch (mpu_device->workarounds){
|
||||||
case 0:
|
case 0x11020004: // This is still required for Creative Audigy, Audidy2
|
||||||
// don't know the current mpu state
|
case 0x11020005:
|
||||||
dprintf("mpu401: reset MPU401\n");
|
case 0:
|
||||||
Write_MPU401(mpu_device->cmdport, MPU401_RESET);
|
// don't know the current mpu state
|
||||||
snooze (30000);
|
PRINT(("reset MPU401\n"));
|
||||||
ack_byte = Read_MPU401(mpu_device->dataport);
|
Write_MPU401(mpu_device->addrport, UARTCMD, mpu_device->workarounds, MPU401_RESET);
|
||||||
dprintf("mpu401: enable UART mode\n");
|
snooze(30000);
|
||||||
Write_MPU401(mpu_device->cmdport, MPU401_UART);
|
Write_MPU401(mpu_device->addrport, UARTCMD, mpu_device->workarounds, MPU401_RESET);
|
||||||
snooze (30000);
|
snooze(30000);
|
||||||
ack_byte = Read_MPU401(mpu_device->dataport );
|
ack_byte = Read_MPU401(mpu_device->addrport, UARTDATA, mpu_device->workarounds);
|
||||||
dprintf("port cmd ack is 0x%x\n", ack_byte);
|
PRINT(("enable UART mode\n"));
|
||||||
|
Write_MPU401(mpu_device->addrport, UARTCMD, mpu_device->workarounds, MPU401_UART);
|
||||||
|
snooze(30000);
|
||||||
|
ack_byte = Read_MPU401(mpu_device->addrport, UARTDATA, mpu_device->workarounds );
|
||||||
|
PRINT(("port cmd ack is 0x%x\n", ack_byte));
|
||||||
*out_cookie = mpu_device;
|
*out_cookie = mpu_device;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// only a guess here... don't have any knowledge of workaround values
|
// Some devices are always in UART mode
|
||||||
dprintf("mpu401a: in UART mode\n");
|
PRINT(("already in UART mode\n"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dprintf("mpu401: Unknown workaround value: %d\n",mpu_device->workarounds);
|
PRINT(("Unknown workaround value: %d\n", mpu_device->workarounds));
|
||||||
break;
|
break;
|
||||||
} //end switch
|
} //end switch
|
||||||
|
|
||||||
// Create Read semaphore for midi-in data
|
// Create Read semaphore for midi-in data
|
||||||
sprintf(semname,"mpu401:%04x:read_sem",mpu_device->dataport );
|
sprintf(semname, "mpu401:%04x:read_sem", mpu_device->addrport);
|
||||||
mpu_device->readsemaphore = create_sem(0,semname);
|
mpu_device->readsemaphore = create_sem(0, semname);
|
||||||
|
|
||||||
// Create Write semaphore for midi-out data
|
// Create Write semaphore for midi-out data
|
||||||
sprintf(semname,"mpu401:%04x:write_sem",mpu_device->dataport );
|
sprintf(semname,"mpu401:%04x:write_sem", mpu_device->addrport);
|
||||||
mpu_device->writesemaphore = create_sem(1,semname);
|
mpu_device->writesemaphore = create_sem(1, semname);
|
||||||
|
|
||||||
|
// clear midi-in buffer
|
||||||
|
mbuf_bytes=0;
|
||||||
|
mbuf_current=0;
|
||||||
|
mbuf_start=0;
|
||||||
|
|
||||||
//Enable midi interrupts
|
//Enable midi interrupts
|
||||||
mpu_device->interrupt_op(B_MPU_401_ENABLE_CARD_INT, &mpu_device);
|
mpu_device->interrupt_op(B_MPU_401_ENABLE_CARD_INT, mpu_device->card );
|
||||||
|
|
||||||
// clear midi-in buffer
|
if ((mpu_device->readsemaphore > B_OK)
|
||||||
mbuf_bytes=0;
|
&& (mpu_device->writesemaphore > B_OK)) {
|
||||||
mbuf_current=0;
|
atomic_add(&mpu_device->count, 1);
|
||||||
mbuf_start=0;
|
PRINT(("midi_open() done (count = %x)\n", open_count));
|
||||||
|
return B_OK;
|
||||||
if ((mpu_device->readsemaphore > B_OK)&&(mpu_device->writesemaphore > B_OK))
|
}
|
||||||
{
|
return B_ERROR;
|
||||||
atomic_add(&mpu_device->count, 1);
|
|
||||||
dprintf("mpu401: midi_open() done (count = %x)\n", open_count);
|
|
||||||
return (B_OK);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return (B_ERROR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
@@ -207,35 +189,30 @@ midi_close(void * cookie)
|
|||||||
{
|
{
|
||||||
mpu401device * mpu_device = (mpu401device *)cookie;
|
mpu401device * mpu_device = (mpu401device *)cookie;
|
||||||
|
|
||||||
#if MPUDEBUG
|
|
||||||
dprintf("mpu401: close\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mpu_device->count <= 0)
|
if (mpu_device->count <= 0)
|
||||||
return(B_ERROR);
|
return B_ERROR;
|
||||||
|
|
||||||
//Disable soundcard midi interrupts
|
//Disable soundcard midi interrupts
|
||||||
mpu_device->interrupt_op(B_MPU_401_DISABLE_CARD_INT, &mpu_device);
|
mpu_device->interrupt_op(B_MPU_401_DISABLE_CARD_INT, mpu_device->card );
|
||||||
|
|
||||||
// Delete the semaphores
|
// Delete the semaphores
|
||||||
delete_sem(mpu_device->readsemaphore);
|
delete_sem(mpu_device->readsemaphore);
|
||||||
delete_sem(mpu_device->writesemaphore);
|
delete_sem(mpu_device->writesemaphore);
|
||||||
|
|
||||||
atomic_add(&mpu_device->count, -1);
|
atomic_add(&mpu_device->count, -1);
|
||||||
dprintf("mpu401: midi_close() done (count = %lu)\n", mpu_device->count);
|
PRINT(("midi_close() done (count = %lu)\n", mpu_device->count));
|
||||||
|
|
||||||
return (B_OK);
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
midi_free - free up allocated memory
|
midi_free - free up allocated memory
|
||||||
----- */
|
----- */
|
||||||
static status_t
|
static status_t
|
||||||
midi_free(void * cookie)
|
midi_free(void * cookie)
|
||||||
{
|
{
|
||||||
#if MPUDEBUG
|
LOG(("midi_free()\n"));
|
||||||
dprintf("mpu401: free\n");
|
return B_OK;
|
||||||
#endif
|
|
||||||
return (B_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
@@ -246,11 +223,9 @@ midi_control(void * cookie, uint32 op, void * data, size_t len)
|
|||||||
{
|
{
|
||||||
//mpu401device *mpu_device = (mpu401device *)cookie;
|
//mpu401device *mpu_device = (mpu401device *)cookie;
|
||||||
|
|
||||||
/* I don't think this is ever called ...*/
|
/* I don't think this is ever called ...*/
|
||||||
#if MPUDEBUG
|
LOG(("midi_control()\n"));
|
||||||
dprintf("mpu401: control\n");
|
return B_OK;
|
||||||
#endif
|
|
||||||
return (B_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -260,20 +235,15 @@ midi_control(void * cookie, uint32 op, void * data, size_t len)
|
|||||||
static status_t
|
static status_t
|
||||||
midi_read(void *cookie, off_t pos, void *buffer, size_t *num_bytes)
|
midi_read(void *cookie, off_t pos, void *buffer, size_t *num_bytes)
|
||||||
{
|
{
|
||||||
/* The actual midi data is read from the device in the interrupt handler;
|
/* The actual midi data is read from the device in the interrupt handler;
|
||||||
this reads and returns the data from a buffer */
|
this reads and returns the data from a buffer */
|
||||||
|
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
size_t count;
|
size_t count;
|
||||||
cpu_status status;
|
cpu_status status;
|
||||||
status_t bestat;
|
status_t bestat;
|
||||||
mpu401device *mpu_device = (mpu401device *)cookie;
|
mpu401device *mpu_device = (mpu401device *)cookie;
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
dprintf("mpu401: read\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
data = (unsigned char*)buffer;
|
data = (unsigned char*)buffer;
|
||||||
count = *(num_bytes);
|
count = *(num_bytes);
|
||||||
@@ -281,36 +251,30 @@ mpu401device *mpu_device = (mpu401device *)cookie;
|
|||||||
i=0;
|
i=0;
|
||||||
*num_bytes=0;
|
*num_bytes=0;
|
||||||
bestat = acquire_sem_etc ( mpu_device->readsemaphore, 1, B_CAN_INTERRUPT, 0);
|
bestat = acquire_sem_etc ( mpu_device->readsemaphore, 1, B_CAN_INTERRUPT, 0);
|
||||||
if (bestat == B_INTERRUPTED)
|
if (bestat == B_INTERRUPTED) {
|
||||||
{
|
//PRINT(("acquire_sem B_INTERRUPTED!\n"));
|
||||||
#if MPUDEBUG
|
return B_INTERRUPTED;
|
||||||
dprintf("mpu401: acquire_sem B_INTERRUPTED!\n");
|
}
|
||||||
#endif
|
if (bestat != B_OK) {
|
||||||
return (B_INTERRUPTED);
|
TRACE(("acquire_sem not B_OK %d\n",(int)bestat));
|
||||||
}
|
*num_bytes = 1;
|
||||||
if (bestat != B_OK)
|
return B_INTERRUPTED;
|
||||||
{
|
}
|
||||||
#if MPUDEBUG
|
if (bestat == B_OK) {
|
||||||
dprintf("mpu401: acquire_sem not B_OK %d\n",bestat);
|
status = lock();
|
||||||
#endif
|
*(data+i) = mpubuffer[mbuf_start];
|
||||||
*num_bytes = 1;
|
i++;
|
||||||
return (B_INTERRUPTED);
|
mbuf_start++; // pointer to data in ringbuffer
|
||||||
}
|
if (mbuf_start >= (MBUF_ELEMENTS-1))
|
||||||
if (bestat == B_OK)
|
mbuf_start = 0; //wraparound of ringbuffer
|
||||||
{
|
*num_bytes =1; // tell caller how many bytes are being returned in buffer
|
||||||
status = lock();
|
if (mbuf_bytes>0)
|
||||||
*(data+i) = mpubuffer[mbuf_start];
|
mbuf_bytes--; // bytes read from buffer, so decrement buffer count
|
||||||
i++;
|
unlock(status);
|
||||||
mbuf_start++; // pointer to data in ringbuffer
|
//PRINT(("bytes in buffer: %d\n",mbuf_bytes));
|
||||||
if (mbuf_start >= (MBUF_ELEMENTS-1))
|
}
|
||||||
mbuf_start = 0; //wraparound of ringbuffer
|
|
||||||
*num_bytes =1; // tell caller how many bytes are being returned in buffer
|
return B_OK;
|
||||||
if (mbuf_bytes>0) mbuf_bytes--; // bytes read from buffer, so decrement buffer count
|
|
||||||
unlock(status);
|
|
||||||
//dprintf("mpu401: bytes in buffer: %d\n",mbuf_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (B_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
@@ -319,32 +283,28 @@ mpu401device *mpu_device = (mpu401device *)cookie;
|
|||||||
static status_t
|
static status_t
|
||||||
midi_write(void * cookie, off_t pos, const void * data, size_t * num_bytes)
|
midi_write(void * cookie, off_t pos, const void * data, size_t * num_bytes)
|
||||||
{
|
{
|
||||||
unsigned char *bufdata;
|
unsigned char *bufdata;
|
||||||
uint32 i;
|
uint32 i;
|
||||||
size_t count;
|
size_t count;
|
||||||
|
|
||||||
mpu401device *mpu_device = (mpu401device *)cookie;
|
mpu401device *mpu_device = (mpu401device *)cookie;
|
||||||
bufdata = (unsigned char*)data; /* Pointer to midi data buffer */
|
bufdata = (unsigned char*)data; /* Pointer to midi data buffer */
|
||||||
count = *num_bytes;
|
count = *num_bytes;
|
||||||
|
|
||||||
#if 0
|
/* Only for deep debugging..will slow things down */
|
||||||
dprintf("mpu401_w: write %d bytes\n",count);
|
//PRINT(("write %d bytes, addrport 0x%x, workarounds 0x%x\n",(int)count,mpu_device->addrport, mpu_device->workarounds));
|
||||||
dprintf("mpu401_w: mpu_device->dataport 0x%x\n",mpu_device->dataport);
|
|
||||||
dprintf("mpu401_w: workarounds %d\n",mpu_device->workarounds);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
acquire_sem (mpu_device->writesemaphore);
|
acquire_sem(mpu_device->writesemaphore);
|
||||||
for (i=0; i<count; i++)
|
for (i=0; i<count; i++) {
|
||||||
{
|
// wait until device is ready
|
||||||
// wait until device is ready
|
while ((Read_MPU401(mpu_device->addrport, UARTCMD, mpu_device->workarounds) & MPU401_OK2WR));
|
||||||
while ((Read_MPU401( mpu_device->cmdport) & MPU401_OK2WR));
|
Write_MPU401(mpu_device->addrport, UARTDATA, mpu_device->workarounds, *(bufdata+i));
|
||||||
Write_MPU401 ( mpu_device->dataport, *(bufdata+i) );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
*num_bytes = 0;
|
*num_bytes = 0;
|
||||||
release_sem (mpu_device->writesemaphore);
|
release_sem(mpu_device->writesemaphore);
|
||||||
|
|
||||||
return (B_OK);
|
return B_OK;
|
||||||
}
|
}
|
||||||
/* ----------
|
/* ----------
|
||||||
interrupt_hook - handle interrupts for mpu401 data
|
interrupt_hook - handle interrupts for mpu401 data
|
||||||
@@ -355,77 +315,120 @@ interrupt_hook(void * cookie)
|
|||||||
status_t bestat;
|
status_t bestat;
|
||||||
mpu401device *mpu_device = (mpu401device *)cookie;
|
mpu401device *mpu_device = (mpu401device *)cookie;
|
||||||
|
|
||||||
#if 0
|
//PRINT(("irq! port: 0x%x\n",mpu_device->addrport)); /* Only for deep debugging..will slow things down */
|
||||||
dprintf("mpu401: irq! port: 0x%x\n",mpu_device->dataport);
|
|
||||||
#endif
|
/* Input data is available when bit 7 of the Status port is zero. Conversely, when bit 7 is
|
||||||
/* Input data is available when bit 7 of the Status port is zero. Conversely, when bit 7 is
|
is a one, no MIDI data is available. Reading from the data port will often clear the
|
||||||
is a one, no MIDI data is available. Reading from the data port will clear the interrupt signal */
|
interrupt signal depending on the sound card. */
|
||||||
|
|
||||||
if ( (Read_MPU401(mpu_device->cmdport) & MPU401_OK2RD) == 0 )
|
if ((Read_MPU401(mpu_device->addrport, UARTCMD, mpu_device->workarounds) & MPU401_OK2RD) == 0) {
|
||||||
{
|
|
||||||
/* Okay, midi data waiting to be read from device */
|
/* Okay, midi data waiting to be read from device */
|
||||||
if (mbuf_current >= (MBUF_ELEMENTS-1))
|
if (mbuf_current >= (MBUF_ELEMENTS-1))
|
||||||
mbuf_current = 0;
|
mbuf_current = 0;
|
||||||
|
|
||||||
mpubuffer[mbuf_current] = Read_MPU401(mpu_device->dataport); /* store midi data byte into buffer */
|
mpubuffer[mbuf_current] = Read_MPU401(mpu_device->addrport,
|
||||||
mbuf_current++; /* pointer to next blank byte */
|
UARTDATA, mpu_device->workarounds); /* store midi data byte into buffer */
|
||||||
mbuf_bytes++; /* increment count of midi data bytes */
|
mbuf_current++; /* pointer to next blank byte */
|
||||||
|
mbuf_bytes++; /* increment count of midi data bytes */
|
||||||
|
|
||||||
bestat = release_sem_etc(mpu_device->readsemaphore, 1, B_DO_NOT_RESCHEDULE);
|
bestat = release_sem_etc(mpu_device->readsemaphore, 1, B_DO_NOT_RESCHEDULE);
|
||||||
//bestat = get_sem_count ( mpu_device->readsemaphore, &semcount);
|
|
||||||
//dprintf("irq:get_sem_count: %d\n",semcount);
|
|
||||||
|
|
||||||
return (TRUE); //B_INVOKE_SCHEDULER
|
return TRUE; //B_INVOKE_SCHEDULER
|
||||||
}
|
}
|
||||||
else
|
/* No midi data from this interrupt */
|
||||||
{
|
return FALSE; //B_UNHANDLED_INTERRUPT
|
||||||
/* No midi data from this interrupt */
|
|
||||||
return(FALSE); //B_UNHANDLED_INTERRUPT
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------*/
|
/*-----------------------------------------------------------------*/
|
||||||
|
|
||||||
uchar Read_MPU401( unsigned int addrport ){
|
uchar
|
||||||
|
Read_MPU401(unsigned int addrport, const char cmdtype, unsigned int workarounds)
|
||||||
|
{
|
||||||
uchar mpudatabyte;
|
uchar mpudatabyte;
|
||||||
|
cpu_status status;
|
||||||
|
unsigned int regptr;
|
||||||
|
|
||||||
mpudatabyte = gISA->read_io_8(addrport);
|
//PRINT(("read workaround 0x%x\n",workarounds)); /* Only for deep debugging..will slow things down */
|
||||||
// dprintf ("mpu401: read 0x%x\n",mpudatabyte);
|
switch (workarounds) {
|
||||||
|
case 0x11020004: /* Creative Audigy Gameport */
|
||||||
return (mpudatabyte);
|
regptr = (((I_MPU1 + cmdtype) << 16) & PTR_ADDRESS_MASK);
|
||||||
|
status = lock();
|
||||||
|
gPCI->write_io_32(addrport + D_PTR, regptr); /*DATA or CMD */
|
||||||
|
mpudatabyte = gPCI->read_io_32(addrport + D_DATA);
|
||||||
|
unlock(status);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x11020005: /* Creative Audigy LiveDrive */
|
||||||
|
regptr = (((I_MPU2 + cmdtype) << 16) & PTR_ADDRESS_MASK);
|
||||||
|
status = lock();
|
||||||
|
gPCI->write_io_32(addrport + D_PTR, regptr); /*DATA2 or CMD2 */
|
||||||
|
mpudatabyte = gPCI->read_io_32(addrport + D_DATA);
|
||||||
|
unlock(status);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
mpudatabyte = gISA->read_io_8(addrport + cmdtype );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return mpudatabyte;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t Write_MPU401( int addrport, uchar mpudatabyte ){
|
|
||||||
|
|
||||||
// dprintf("mpu401: write 0x%x",mpudatabyte);
|
status_t
|
||||||
// dprintf(" at addr: 0x%x\n",addrport);
|
Write_MPU401(unsigned int addrport, const char cmdtype, unsigned int workarounds, uchar mpudatabyte )
|
||||||
gISA->write_io_8(addrport, mpudatabyte);
|
{
|
||||||
|
cpu_status status;
|
||||||
|
unsigned int regptr;
|
||||||
|
|
||||||
|
/* Only for deep debugging..will slow things down */
|
||||||
|
//PRINT(("write workaround 0x%x at addr: 0x%x\n",workarounds,addrport));
|
||||||
|
switch (workarounds) {
|
||||||
|
case 0x11020004: /* Creative Audigy Gameport */
|
||||||
|
regptr = (((I_MPU1 + cmdtype ) << 16) & PTR_ADDRESS_MASK);
|
||||||
|
status = lock();
|
||||||
|
gPCI->write_io_32(addrport + D_PTR, regptr); /*DATA or CMD */
|
||||||
|
gPCI->write_io_32(addrport + D_DATA, mpudatabyte );
|
||||||
|
unlock(status);
|
||||||
|
break;
|
||||||
|
|
||||||
return (B_OK);
|
case 0x11020005: /* Creative Audigy LiveDrive */
|
||||||
|
regptr = (((I_MPU2 + cmdtype ) << 16) & PTR_ADDRESS_MASK);
|
||||||
|
status = lock();
|
||||||
|
gPCI->write_io_32(addrport + D_PTR, regptr); /*DATA2 or CMD2 */
|
||||||
|
gPCI->write_io_32(addrport + D_DATA, mpudatabyte );
|
||||||
|
unlock(status);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
gISA->write_io_8(addrport + cmdtype, mpudatabyte);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------*/
|
/*-----------------------------------------------------------------*/
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
std_ops(int32 op, ...)
|
std_ops(int32 op, ...)
|
||||||
{
|
{
|
||||||
#if MPUDEBUG
|
|
||||||
bool former;
|
|
||||||
former = set_dprintf_enabled ( true );
|
|
||||||
dprintf("mpu401:std_ops 0x%lx\n", op);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch(op) {
|
switch(op) {
|
||||||
|
|
||||||
case B_MODULE_INIT:
|
case B_MODULE_INIT:
|
||||||
dprintf("mpu401: B_MODULE_INIT\n");
|
|
||||||
|
LOG_CREATE();
|
||||||
|
PRINT(("B_MODULE_INIT\n"));
|
||||||
|
|
||||||
if (get_module(B_ISA_MODULE_NAME, (module_info **)&gISA) < B_OK)
|
if (get_module(B_ISA_MODULE_NAME, (module_info **)&gISA) < B_OK)
|
||||||
return (B_ERROR);
|
return B_ERROR;
|
||||||
|
if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI) < B_OK)
|
||||||
|
return B_ERROR;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
case B_MODULE_UNINIT:
|
case B_MODULE_UNINIT:
|
||||||
put_module (B_ISA_MODULE_NAME);
|
put_module(B_ISA_MODULE_NAME);
|
||||||
dprintf("mpu401: B_MODULE_UNINIT\n");
|
put_module(B_PCI_MODULE_NAME);
|
||||||
|
PRINT(("B_MODULE_UNINIT\n"));
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -450,6 +453,7 @@ static generic_mpu401_module mpu401_module =
|
|||||||
midi_write,
|
midi_write,
|
||||||
interrupt_hook
|
interrupt_hook
|
||||||
};
|
};
|
||||||
|
|
||||||
// Module v2 seems to be undocumented
|
// Module v2 seems to be undocumented
|
||||||
static generic_mpu401_module mpu401_module2 =
|
static generic_mpu401_module mpu401_module2 =
|
||||||
{
|
{
|
||||||
@@ -477,16 +481,18 @@ _EXPORT generic_mpu401_module *modules[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
spinlock locked = 0;
|
spinlock locked = 0;
|
||||||
cpu_status lock(void)
|
cpu_status
|
||||||
|
lock(void)
|
||||||
{
|
{
|
||||||
cpu_status status = disable_interrupts();
|
cpu_status status = disable_interrupts();
|
||||||
acquire_spinlock (&locked);
|
acquire_spinlock(&locked);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock( cpu_status status)
|
void
|
||||||
|
unlock(cpu_status status)
|
||||||
{
|
{
|
||||||
release_spinlock(&locked);
|
release_spinlock(&locked);
|
||||||
restore_interrupts (status);
|
restore_interrupts(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,53 +1,92 @@
|
|||||||
/*
|
/*
|
||||||
* OpenBeOS
|
* Copyright 2003-2006, Haiku.
|
||||||
* A module driver for the generic mpu401 midi interface
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003 Greg Crain
|
* A module driver for the generic mpu401 midi interface.
|
||||||
* All rights reserved.
|
*
|
||||||
* This software is released under the MIT/OpenBeOS license.
|
* Author:
|
||||||
*
|
* Greg Crain ([email protected])
|
||||||
* mpu401_priv.h
|
*
|
||||||
*/
|
* mpu401_priv.h
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef mpu401_H
|
#ifndef mpu401_priv_H
|
||||||
#define mpu401_H
|
#define mpu401_priv_H
|
||||||
|
|
||||||
#include <module.h>
|
#include <module.h>
|
||||||
|
#include <PCI.h>
|
||||||
|
|
||||||
//Private header info
|
/*--------------------------------*/
|
||||||
|
/* UART Definitions */
|
||||||
typedef struct _mpu401device
|
|
||||||
{
|
|
||||||
unsigned int dataport;
|
|
||||||
unsigned int cmdport;
|
|
||||||
unsigned int workarounds;
|
|
||||||
int32 count;
|
|
||||||
bool V2;
|
|
||||||
sem_id readsemaphore;
|
|
||||||
sem_id writesemaphore;
|
|
||||||
void (*interrupt_op)(int32 op, void * card);
|
|
||||||
} mpu401device;
|
|
||||||
|
|
||||||
#define MPU401_RESET 0xff
|
#define MPU401_RESET 0xff
|
||||||
#define MPU401_UART 0x3f
|
#define MPU401_UART 0x3f
|
||||||
#define MPU401_CMDOK 0xfe
|
#define MPU401_CMDOK 0xfe
|
||||||
#define MPU401_OK2WR 0x40
|
#define MPU401_OK2WR 0x40
|
||||||
#define MPU401_OK2RD 0x80
|
#define MPU401_OK2RD 0x80
|
||||||
|
// Typically,
|
||||||
|
// UART data port = addr
|
||||||
|
// UART cmd port = addr +1
|
||||||
|
#define UARTDATA 0
|
||||||
|
#define UARTCMD 1
|
||||||
|
|
||||||
|
#define MBUF_ELEMENTS 1000 //Input buffer size
|
||||||
|
|
||||||
#define MPUDEBUG 1
|
|
||||||
#define MBUF_ELEMENTS 1000
|
|
||||||
/*--------------------------------*/
|
/*--------------------------------*/
|
||||||
unsigned char Read_MPU401( unsigned int );
|
/* Private definitions */
|
||||||
status_t Write_MPU401( int, unsigned char );
|
|
||||||
|
typedef struct _mpu401device {
|
||||||
|
unsigned int addrport;
|
||||||
|
unsigned int workarounds;
|
||||||
|
int32 count;
|
||||||
|
bool V2;
|
||||||
|
sem_id readsemaphore;
|
||||||
|
sem_id writesemaphore;
|
||||||
|
void (*interrupt_op)(int32 op, void * card);
|
||||||
|
void *card;
|
||||||
|
} mpu401device;
|
||||||
|
|
||||||
|
int mbuf_current;
|
||||||
|
int mbuf_start;
|
||||||
|
int mbuf_bytes;
|
||||||
|
unsigned char mpubuffer[MBUF_ELEMENTS];
|
||||||
|
static int open_count;
|
||||||
|
static isa_module_info *gISA;
|
||||||
|
static pci_module_info *gPCI;
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------*/
|
||||||
|
/* Function prototypes */
|
||||||
|
|
||||||
|
unsigned char Read_MPU401(unsigned int, const char, unsigned int);
|
||||||
|
status_t Write_MPU401(unsigned int, const char, unsigned int, uchar);
|
||||||
|
|
||||||
cpu_status lock(void);
|
cpu_status lock(void);
|
||||||
void unlock (cpu_status);
|
void unlock (cpu_status);
|
||||||
/*--------------------------------*/
|
|
||||||
short open_count=0;
|
|
||||||
int mbuf_current=0;
|
|
||||||
int mbuf_start=0;
|
|
||||||
int mbuf_bytes=0;
|
|
||||||
unsigned char mpubuffer[MBUF_ELEMENTS];
|
|
||||||
static isa_module_info *gISA;
|
|
||||||
|
|
||||||
#endif // mpu401.h
|
/********************/
|
||||||
|
/* Workarounds */
|
||||||
|
/********************/
|
||||||
|
// This is a list of workarounds in order to
|
||||||
|
// get a specific manufacturer, card vendor, or UART type
|
||||||
|
// to work nicely with the generic module.
|
||||||
|
// The defined workaround value must match the value that
|
||||||
|
// is used in the driver 'create_device' call.
|
||||||
|
|
||||||
|
|
||||||
|
/****************************/
|
||||||
|
/* Creative Audigy, Audigy2 */
|
||||||
|
/****************************/
|
||||||
|
/* 0x11020004 Gameport Midi connector */
|
||||||
|
/* 0x11020005 LiveDrive Expansion connector */
|
||||||
|
/* IN the create_device hook, use the PCI base*/
|
||||||
|
/* address, instead of midi address port */
|
||||||
|
#define PTR_ADDRESS_MASK 0x0fff0000
|
||||||
|
#define D_DATA 0x04
|
||||||
|
#define D_PTR 0x00
|
||||||
|
#define I_MPU1 0x70
|
||||||
|
#define I_MPU2 0x72
|
||||||
|
|
||||||
|
|
||||||
|
#endif // mpu401_priv_H
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user