auich: use user_memcpy to read/write the user buffers.
* also check buffer addresses passed through structures. * map registers kernel only. * alloc dma descriptors kernel only.
This commit is contained in:
parent
13daa9299e
commit
3bcf027203
|
@ -1,8 +1,9 @@
|
||||||
SubDir HAIKU_TOP src add-ons kernel drivers audio ac97 auich ;
|
SubDir HAIKU_TOP src add-ons kernel drivers audio ac97 auich ;
|
||||||
|
|
||||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||||
UsePrivateSystemHeaders ;
|
UsePrivateKernelHeaders ;
|
||||||
UsePrivateHeaders media ;
|
UsePrivateHeaders media ;
|
||||||
|
|
||||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,8 @@ auich_mem_new(auich_dev *card, size_t size)
|
||||||
if ((mem = malloc(sizeof(*mem))) == NULL)
|
if ((mem = malloc(sizeof(*mem))) == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "auich buffer");
|
mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "auich buffer",
|
||||||
|
true);
|
||||||
mem->size = size;
|
mem->size = size;
|
||||||
if (mem->area < B_OK) {
|
if (mem->area < B_OK) {
|
||||||
free(mem);
|
free(mem);
|
||||||
|
@ -345,7 +346,7 @@ auich_stream_new(auich_dev *card, uint8 use, uint32 bufframes, uint8 bufcount)
|
||||||
|
|
||||||
/* allocate memory for our dma ops */
|
/* allocate memory for our dma ops */
|
||||||
stream->dmaops_area = alloc_mem(&stream->dmaops_phy_base, &stream->dmaops_log_base,
|
stream->dmaops_area = alloc_mem(&stream->dmaops_phy_base, &stream->dmaops_log_base,
|
||||||
sizeof(auich_dmalist) * AUICH_DMALIST_MAX, "auich dmaops");
|
sizeof(auich_dmalist) * AUICH_DMALIST_MAX, "auich dmaops", false);
|
||||||
|
|
||||||
if (stream->dmaops_area < B_OK) {
|
if (stream->dmaops_area < B_OK) {
|
||||||
PRINT(("couldn't allocate memory\n"));
|
PRINT(("couldn't allocate memory\n"));
|
||||||
|
|
|
@ -32,7 +32,11 @@
|
||||||
#include <driver_settings.h>
|
#include <driver_settings.h>
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
#include <MediaDefs.h>
|
#include <MediaDefs.h>
|
||||||
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
#include "hmulti_audio.h"
|
#include "hmulti_audio.h"
|
||||||
#include "multi.h"
|
#include "multi.h"
|
||||||
#include "ac97.h"
|
#include "ac97.h"
|
||||||
|
@ -726,17 +730,6 @@ auich_get_enabled_channels(auich_dev *card, multi_channel_enable *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
auich_set_enabled_channels(auich_dev *card, multi_channel_enable *data)
|
|
||||||
{
|
|
||||||
PRINT(("set_enabled_channels 0 : %s\n", B_TEST_CHANNEL(data->enable_bits, 0) ? "enabled": "disabled"));
|
|
||||||
PRINT(("set_enabled_channels 1 : %s\n", B_TEST_CHANNEL(data->enable_bits, 1) ? "enabled": "disabled"));
|
|
||||||
PRINT(("set_enabled_channels 2 : %s\n", B_TEST_CHANNEL(data->enable_bits, 2) ? "enabled": "disabled"));
|
|
||||||
PRINT(("set_enabled_channels 3 : %s\n", B_TEST_CHANNEL(data->enable_bits, 3) ? "enabled": "disabled"));
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
auich_get_global_format(auich_dev *card, multi_format_info *data)
|
auich_get_global_format(auich_dev *card, multi_format_info *data)
|
||||||
{
|
{
|
||||||
|
@ -758,6 +751,14 @@ auich_get_global_format(auich_dev *card, multi_format_info *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
auich_set_global_format(auich_dev *card, multi_format_info* data)
|
||||||
|
{
|
||||||
|
// TODO: it looks like we're not supposed to fail; fix this!
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
auich_get_buffers(auich_dev *card, multi_buffer_list *data)
|
auich_get_buffers(auich_dev *card, multi_buffer_list *data)
|
||||||
{
|
{
|
||||||
|
@ -794,12 +795,18 @@ auich_get_buffers(auich_dev *card, multi_buffer_list *data)
|
||||||
if (bufcount > data->request_playback_buffers)
|
if (bufcount > data->request_playback_buffers)
|
||||||
bufcount = data->request_playback_buffers;
|
bufcount = data->request_playback_buffers;
|
||||||
|
|
||||||
for (i = 0; i < bufcount; i++)
|
for (i = 0; i < bufcount; i++) {
|
||||||
|
struct buffer_desc descs[data->return_playback_channels];
|
||||||
for (j=0; j<pchannels; j++)
|
for (j=0; j<pchannels; j++)
|
||||||
auich_stream_get_nth_buffer(card->pstream, j, i,
|
auich_stream_get_nth_buffer(card->pstream, j, i,
|
||||||
&data->playback_buffers[i][j].base,
|
&descs[j].base,
|
||||||
&data->playback_buffers[i][j].stride);
|
&descs[j].stride);
|
||||||
|
if (!IS_USER_ADDRESS(data->playback_buffers[i])
|
||||||
|
|| user_memcpy(data->playback_buffers[i], descs, sizeof(descs))
|
||||||
|
< B_OK) {
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
data->return_record_buffers = current_settings.buffer_count;
|
data->return_record_buffers = current_settings.buffer_count;
|
||||||
data->return_record_channels = rchannels;
|
data->return_record_channels = rchannels;
|
||||||
data->return_record_buffer_size = current_settings.buffer_frames; /* frames */
|
data->return_record_buffer_size = current_settings.buffer_frames; /* frames */
|
||||||
|
@ -808,12 +815,18 @@ auich_get_buffers(auich_dev *card, multi_buffer_list *data)
|
||||||
if (bufcount > data->request_record_buffers)
|
if (bufcount > data->request_record_buffers)
|
||||||
bufcount = data->request_record_buffers;
|
bufcount = data->request_record_buffers;
|
||||||
|
|
||||||
for (i = 0; i < bufcount; i++)
|
for (i = 0; i < bufcount; i++) {
|
||||||
|
struct buffer_desc descs[data->return_record_channels];
|
||||||
for (j=0; j<rchannels; j++)
|
for (j=0; j<rchannels; j++)
|
||||||
auich_stream_get_nth_buffer(card->rstream, j, i,
|
auich_stream_get_nth_buffer(card->rstream, j, i,
|
||||||
&data->record_buffers[i][j].base,
|
&descs[j].base,
|
||||||
&data->record_buffers[i][j].stride);
|
&descs[j].stride);
|
||||||
|
if (!IS_USER_ADDRESS(data->record_buffers[i])
|
||||||
|
|| user_memcpy(data->record_buffers[i], descs, sizeof(descs))
|
||||||
|
< B_OK) {
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -947,77 +960,28 @@ auich_buffer_force_stop(auich_dev *card)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define cookie_type auich_dev
|
||||||
|
#define get_description auich_get_description
|
||||||
|
#define get_enabled_channels auich_get_enabled_channels
|
||||||
|
#define get_global_format auich_get_global_format
|
||||||
|
#define set_global_format auich_set_global_format
|
||||||
|
#define list_mix_channels auich_list_mix_channels
|
||||||
|
#define list_mix_controls auich_list_mix_controls
|
||||||
|
#define list_mix_connections auich_list_mix_connections
|
||||||
|
#define get_mix auich_get_mix
|
||||||
|
#define set_mix auich_set_mix
|
||||||
|
#define get_buffers auich_get_buffers
|
||||||
|
#define buffer_exchange auich_buffer_exchange
|
||||||
|
#define buffer_force_stop auich_buffer_force_stop
|
||||||
|
#include "../generic/multi.c"
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
auich_multi_control(void *cookie, uint32 op, void *data, size_t length)
|
auich_multi_control(void *cookie, uint32 op, void *arg, size_t length)
|
||||||
{
|
{
|
||||||
auich_dev *card = (auich_dev *)cookie;
|
auich_dev *card = (auich_dev *)cookie;
|
||||||
|
|
||||||
switch (op) {
|
return multi_audio_control_generic(card, op, arg, length);
|
||||||
case B_MULTI_GET_DESCRIPTION:
|
|
||||||
LOG(("B_MULTI_GET_DESCRIPTION\n"));
|
|
||||||
return auich_get_description(card, (multi_description *)data);
|
|
||||||
case B_MULTI_GET_EVENT_INFO:
|
|
||||||
LOG(("B_MULTI_GET_EVENT_INFO\n"));
|
|
||||||
return B_ERROR;
|
|
||||||
case B_MULTI_SET_EVENT_INFO:
|
|
||||||
LOG(("B_MULTI_SET_EVENT_INFO\n"));
|
|
||||||
return B_ERROR;
|
|
||||||
case B_MULTI_GET_EVENT:
|
|
||||||
LOG(("B_MULTI_GET_EVENT\n"));
|
|
||||||
return B_ERROR;
|
|
||||||
case B_MULTI_GET_ENABLED_CHANNELS:
|
|
||||||
LOG(("B_MULTI_GET_ENABLED_CHANNELS\n"));
|
|
||||||
return auich_get_enabled_channels(card, (multi_channel_enable *)data);
|
|
||||||
case B_MULTI_SET_ENABLED_CHANNELS:
|
|
||||||
LOG(("B_MULTI_SET_ENABLED_CHANNELS\n"));
|
|
||||||
return auich_set_enabled_channels(card, (multi_channel_enable *)data);
|
|
||||||
case B_MULTI_GET_GLOBAL_FORMAT:
|
|
||||||
LOG(("B_MULTI_GET_GLOBAL_FORMAT\n"));
|
|
||||||
return auich_get_global_format(card, (multi_format_info *)data);
|
|
||||||
case B_MULTI_SET_GLOBAL_FORMAT:
|
|
||||||
LOG(("B_MULTI_SET_GLOBAL_FORMAT\n"));
|
|
||||||
return B_OK; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent
|
|
||||||
* BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT
|
|
||||||
*/
|
|
||||||
case B_MULTI_GET_CHANNEL_FORMATS:
|
|
||||||
LOG(("B_MULTI_GET_CHANNEL_FORMATS\n"));
|
|
||||||
return B_ERROR;
|
|
||||||
case B_MULTI_SET_CHANNEL_FORMATS: /* only implemented if possible */
|
|
||||||
LOG(("B_MULTI_SET_CHANNEL_FORMATS\n"));
|
|
||||||
return B_ERROR;
|
|
||||||
case B_MULTI_GET_MIX:
|
|
||||||
LOG(("B_MULTI_GET_MIX\n"));
|
|
||||||
return auich_get_mix(card, (multi_mix_value_info *)data);
|
|
||||||
case B_MULTI_SET_MIX:
|
|
||||||
LOG(("B_MULTI_SET_MIX\n"));
|
|
||||||
return auich_set_mix(card, (multi_mix_value_info *)data);
|
|
||||||
case B_MULTI_LIST_MIX_CHANNELS:
|
|
||||||
LOG(("B_MULTI_LIST_MIX_CHANNELS\n"));
|
|
||||||
return auich_list_mix_channels(card, (multi_mix_channel_info *)data);
|
|
||||||
case B_MULTI_LIST_MIX_CONTROLS:
|
|
||||||
LOG(("B_MULTI_LIST_MIX_CONTROLS\n"));
|
|
||||||
return auich_list_mix_controls(card, (multi_mix_control_info *)data);
|
|
||||||
case B_MULTI_LIST_MIX_CONNECTIONS:
|
|
||||||
LOG(("B_MULTI_LIST_MIX_CONNECTIONS\n"));
|
|
||||||
return auich_list_mix_connections(card, (multi_mix_connection_info *)data);
|
|
||||||
case B_MULTI_GET_BUFFERS: /* Fill out the struct for the first time; doesn't start anything. */
|
|
||||||
LOG(("B_MULTI_GET_BUFFERS\n"));
|
|
||||||
return auich_get_buffers(card, data);
|
|
||||||
case B_MULTI_SET_BUFFERS: /* Set what buffers to use, if the driver supports soft buffers. */
|
|
||||||
LOG(("B_MULTI_SET_BUFFERS\n"));
|
|
||||||
return B_ERROR; /* we do not support soft buffers */
|
|
||||||
case B_MULTI_SET_START_TIME: /* When to actually start */
|
|
||||||
LOG(("B_MULTI_SET_START_TIME\n"));
|
|
||||||
return B_ERROR;
|
|
||||||
case B_MULTI_BUFFER_EXCHANGE: /* stop and go are derived from this being called */
|
|
||||||
//TRACE(("B_MULTI_BUFFER_EXCHANGE\n"));
|
|
||||||
return auich_buffer_exchange(card, (multi_buffer_info *)data);
|
|
||||||
case B_MULTI_BUFFER_FORCE_STOP: /* force stop of playback, nothing in data */
|
|
||||||
LOG(("B_MULTI_BUFFER_FORCE_STOP\n"));
|
|
||||||
return auich_buffer_force_stop(card);
|
|
||||||
}
|
|
||||||
LOG(("ERROR: unknown multi_control %#x\n",op));
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static status_t auich_open(const char *name, uint32 flags, void** cookie);
|
static status_t auich_open(const char *name, uint32 flags, void** cookie);
|
||||||
|
|
|
@ -64,18 +64,22 @@ round_to_pagesize(uint32 size)
|
||||||
|
|
||||||
|
|
||||||
area_id
|
area_id
|
||||||
alloc_mem(phys_addr_t *phy, void **log, size_t size, const char *name)
|
alloc_mem(phys_addr_t *phy, void **log, size_t size, const char *name, bool user)
|
||||||
{
|
{
|
||||||
physical_entry pe;
|
physical_entry pe;
|
||||||
void * logadr;
|
void * logadr;
|
||||||
area_id area;
|
area_id area;
|
||||||
status_t rv;
|
status_t rv;
|
||||||
|
uint32 protection;
|
||||||
|
|
||||||
LOG(("allocating %d bytes for %s\n",size,name));
|
LOG(("allocating %d bytes for %s\n",size,name));
|
||||||
|
|
||||||
|
protection = B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA;
|
||||||
|
if (user)
|
||||||
|
protection = B_READ_AREA | B_WRITE_AREA;
|
||||||
size = round_to_pagesize(size);
|
size = round_to_pagesize(size);
|
||||||
area = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS, size,
|
area = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS, size,
|
||||||
B_32_BIT_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
|
B_32_BIT_CONTIGUOUS, protection);
|
||||||
// TODO: The rest of the code doesn't deal correctly with physical
|
// TODO: The rest of the code doesn't deal correctly with physical
|
||||||
// addresses > 4 GB, so we have to force 32 bit addresses here.
|
// addresses > 4 GB, so we have to force 32 bit addresses here.
|
||||||
if (area < B_OK) {
|
if (area < B_OK) {
|
||||||
|
@ -88,7 +92,10 @@ alloc_mem(phys_addr_t *phy, void **log, size_t size, const char *name)
|
||||||
PRINT(("couldn't map %s\n",name));
|
PRINT(("couldn't map %s\n",name));
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
memset(logadr, 0, size);
|
if (user)
|
||||||
|
user_memset(logadr, 0, size);
|
||||||
|
else
|
||||||
|
memset(logadr, 0, size);
|
||||||
if (log)
|
if (log)
|
||||||
*log = logadr;
|
*log = logadr;
|
||||||
if (phy)
|
if (phy)
|
||||||
|
@ -113,7 +120,7 @@ map_mem(void **log, phys_addr_t phy, size_t size, const char *name)
|
||||||
phyadr = phy - offset;
|
phyadr = phy - offset;
|
||||||
size = round_to_pagesize(size + offset);
|
size = round_to_pagesize(size + offset);
|
||||||
area = map_physical_memory(name, phyadr, size, B_ANY_KERNEL_ADDRESS,
|
area = map_physical_memory(name, phyadr, size, B_ANY_KERNEL_ADDRESS,
|
||||||
0, &mapadr);
|
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, &mapadr);
|
||||||
*log = mapadr + offset;
|
*log = mapadr + offset;
|
||||||
|
|
||||||
LOG(("physical = %p, logical = %p, offset = %#x, phyadr = %p, mapadr = %p, size = %#x, area = %#x\n",
|
LOG(("physical = %p, logical = %p, offset = %#x, phyadr = %p, mapadr = %p, size = %#x, area = %#x\n",
|
||||||
|
|
|
@ -30,7 +30,8 @@
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
area_id alloc_mem(phys_addr_t *phy, void **log, size_t size, const char *name);
|
area_id alloc_mem(phys_addr_t *phy, void **log, size_t size, const char *name,
|
||||||
|
bool user);
|
||||||
area_id map_mem(void **log, phys_addr_t phy, size_t size, const char *name);
|
area_id map_mem(void **log, phys_addr_t phy, size_t size, const char *name);
|
||||||
|
|
||||||
cpu_status lock(void);
|
cpu_status lock(void);
|
||||||
|
|
Loading…
Reference in New Issue