2005-04-16 15:20:36 -07:00
/*
2007-10-15 09:50:19 +02:00
* Copyright ( c ) by Jaroslav Kysela < perex @ perex . cz >
2005-04-16 15:20:36 -07:00
* GUS ' s memory access via proc filesystem
*
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
# include <linux/slab.h>
# include <sound/core.h>
# include <sound/gus.h>
# include <sound/info.h>
2005-11-17 14:36:44 +01:00
struct gus_proc_private {
2005-04-16 15:20:36 -07:00
int rom ; /* data are in ROM */
unsigned int address ;
unsigned int size ;
2005-11-17 14:36:44 +01:00
struct snd_gus_card * gus ;
} ;
2005-04-16 15:20:36 -07:00
2005-11-17 14:36:44 +01:00
static long snd_gf1_mem_proc_dump ( struct snd_info_entry * entry , void * file_private_data ,
2005-04-16 15:20:36 -07:00
struct file * file , char __user * buf ,
unsigned long count , unsigned long pos )
{
long size ;
2005-11-17 14:36:44 +01:00
struct gus_proc_private * priv = entry - > private_data ;
struct snd_gus_card * gus = priv - > gus ;
2005-04-16 15:20:36 -07:00
int err ;
size = count ;
if ( pos + size > priv - > size )
size = ( long ) priv - > size - pos ;
if ( size > 0 ) {
if ( ( err = snd_gus_dram_read ( gus , buf , pos , size , priv - > rom ) ) < 0 )
return err ;
return size ;
}
return 0 ;
}
2005-11-17 14:36:44 +01:00
static long long snd_gf1_mem_proc_llseek ( struct snd_info_entry * entry ,
2005-04-16 15:20:36 -07:00
void * private_file_data ,
struct file * file ,
long long offset ,
int orig )
{
2005-11-17 14:36:44 +01:00
struct gus_proc_private * priv = entry - > private_data ;
2005-04-16 15:20:36 -07:00
switch ( orig ) {
2006-09-21 11:33:14 +02:00
case SEEK_SET :
2005-04-16 15:20:36 -07:00
file - > f_pos = offset ;
break ;
2006-09-21 11:33:14 +02:00
case SEEK_CUR :
2005-04-16 15:20:36 -07:00
file - > f_pos + = offset ;
break ;
2006-09-21 11:33:14 +02:00
case SEEK_END : /* offset is negative */
2005-04-16 15:20:36 -07:00
file - > f_pos = priv - > size + offset ;
break ;
default :
return - EINVAL ;
}
if ( file - > f_pos > priv - > size )
file - > f_pos = priv - > size ;
return file - > f_pos ;
}
2005-11-17 14:36:44 +01:00
static void snd_gf1_mem_proc_free ( struct snd_info_entry * entry )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:36:44 +01:00
struct gus_proc_private * priv = entry - > private_data ;
2005-04-16 15:20:36 -07:00
kfree ( priv ) ;
}
static struct snd_info_entry_ops snd_gf1_mem_proc_ops = {
. read = snd_gf1_mem_proc_dump ,
. llseek = snd_gf1_mem_proc_llseek ,
} ;
2005-11-17 14:36:44 +01:00
int snd_gf1_mem_proc_init ( struct snd_gus_card * gus )
2005-04-16 15:20:36 -07:00
{
int idx ;
char name [ 16 ] ;
2005-11-17 14:36:44 +01:00
struct gus_proc_private * priv ;
struct snd_info_entry * entry ;
2005-04-16 15:20:36 -07:00
for ( idx = 0 ; idx < 4 ; idx + + ) {
if ( gus - > gf1 . mem_alloc . banks_8 [ idx ] . size > 0 ) {
2005-09-09 14:21:17 +02:00
priv = kzalloc ( sizeof ( * priv ) , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( priv = = NULL )
return - ENOMEM ;
priv - > gus = gus ;
sprintf ( name , " gus-ram-%i " , idx ) ;
if ( ! snd_card_proc_new ( gus - > card , name , & entry ) ) {
entry - > content = SNDRV_INFO_CONTENT_DATA ;
entry - > private_data = priv ;
entry - > private_free = snd_gf1_mem_proc_free ;
entry - > c . ops = & snd_gf1_mem_proc_ops ;
priv - > address = gus - > gf1 . mem_alloc . banks_8 [ idx ] . address ;
priv - > size = entry - > size = gus - > gf1 . mem_alloc . banks_8 [ idx ] . size ;
}
}
}
for ( idx = 0 ; idx < 4 ; idx + + ) {
if ( gus - > gf1 . rom_present & ( 1 < < idx ) ) {
2005-09-09 14:21:17 +02:00
priv = kzalloc ( sizeof ( * priv ) , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( priv = = NULL )
return - ENOMEM ;
priv - > rom = 1 ;
priv - > gus = gus ;
sprintf ( name , " gus-rom-%i " , idx ) ;
if ( ! snd_card_proc_new ( gus - > card , name , & entry ) ) {
entry - > content = SNDRV_INFO_CONTENT_DATA ;
entry - > private_data = priv ;
entry - > private_free = snd_gf1_mem_proc_free ;
entry - > c . ops = & snd_gf1_mem_proc_ops ;
priv - > address = idx * 4096 * 1024 ;
priv - > size = entry - > size = gus - > gf1 . rom_memory ;
}
}
}
return 0 ;
}