File: detect.c

package info (click to toggle)
alsadriver 0.2.0-pre8-3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 2,808 kB
  • ctags: 6,550
  • sloc: ansic: 43,490; sh: 916; makefile: 759; perl: 54
file content (161 lines) | stat: -rw-r--r-- 4,758 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
 *  Main detection routines
 *  Copyright (c) by Jaroslav Kysela <perex@jcu.cz>
 *
 *
 *   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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#define SND_MAIN_OBJECT_FILE
#include "driver.h"
#include "sndpci.h"
#include "info.h"
#include <stdarg.h>

#define SND_DETECT_VERSION	"1.1"
#define SND_DETECT_BUFFER_SIZE	(32 * 1024)

typedef int (*snd_isa_probe)( snd_card_t *card, char *name, unsigned int *type, unsigned short *port );

extern int snd_detect_interwave( snd_card_t *card, char *name, unsigned int *type, unsigned short *port );
extern int snd_detect_gus( snd_card_t *card, char *name, unsigned int *type, unsigned short *port );
extern int snd_detect_es1688( snd_card_t *card, char *name, unsigned int *type, unsigned short *port );
extern int snd_detect_sb( snd_card_t *card, char *name, unsigned int *type, unsigned short *port );

static snd_info_entry_t *snd_detect_info_entry = NULL;

static snd_isa_probe snd_isa_probes[] = {
  snd_detect_es1688,
  snd_detect_interwave,
  snd_detect_gus,
  snd_detect_sb,
};

#define SND_DETECT_ISA_COUNT (sizeof(snd_isa_probes)/sizeof(void *))

#ifdef CONFIG_PCI

struct snd_pci_probe {
  unsigned int vendor;
  unsigned int device;
  unsigned int type;
  char *name;
};

static struct snd_pci_probe snd_pci_probes[] = {
  { 0x1274, 0x5000, SND_CARD_TYPE_ES1370, "Ensoniq AudioPCI ES1370" },
  { 0x1274, 0x1371, SND_CARD_TYPE_ES1371, "Ensoniq AudioPCI ES1371" },
  { 0x5333, 0xca00, SND_CARD_TYPE_S3_SONICVIBES, "S3 SonicVibes" },
};

#define SND_DETECT_PCI_COUNT (sizeof(snd_pci_probes)/sizeof(struct snd_pci_probe))

#endif

static void snd_detect_use_inc( snd_card_t *card )
{
  MOD_INC_USE_COUNT;
}

static void snd_detect_use_dec( snd_card_t *card )
{
  MOD_DEC_USE_COUNT;
}

static void snd_detect_read( snd_info_buffer_t *buffer, void *private_data )
{
  int idx, cardidx;
  snd_card_t *cards[ SND_CARDS ];	/* detected cards */
  char name[64];
  unsigned int type;
  unsigned short port;
#ifdef CONFIG_PCI
  struct snd_pci_dev pcidev;
#endif

  buffer -> curr = buffer -> buffer;
  *buffer -> buffer = 0;
  snd_iprintf( buffer, "Version: " SND_DETECT_VERSION "\n" );
  if ( snd_cards_count > 0 ) {
    buffer -> error = -EBUSY;
    return;
  }
  memset( &cards, 0, sizeof( cards ) );
  cardidx = 0;
  for ( idx = 0; idx < SND_CARDS; idx++ ) {
    cards[ idx ] = snd_card_new( idx + 1, NULL, snd_detect_use_inc, snd_detect_use_dec );
    if ( !cards[ idx ] ) {
      for ( idx = 0; idx < SND_CARDS; idx++ ) {
        if ( cards[ idx ] ) snd_card_free( cards[ idx ] );
      }
      buffer -> error = -ENOMEM;
      return;
    }
  }
  for ( idx = 0; cardidx < SND_CARDS && idx < SND_DETECT_ISA_COUNT; idx++ ) {
    while ( !snd_isa_probes[ idx ]( cards[ cardidx ], name, &type, &port ) ) {
      snd_iprintf( buffer, "ISA#0x%x#%s#0x%x\n", type, name, port );
      cardidx++;
    }
  }
  for ( idx = 0; idx < SND_CARDS; idx++ ) {
    if ( cards[ idx ] ) snd_card_free( cards[ idx ] );
  }
#ifdef CONFIG_PCI
  for ( idx = 0; idx < SND_DETECT_PCI_COUNT; idx++ ) {
    for ( cardidx = 0; cardidx < 8; cardidx++ ) {
      if ( snd_pci_find_device( snd_pci_probes[ idx ].vendor, snd_pci_probes[ idx ].device, cardidx, &pcidev ) < 0 ) break;
      snd_iprintf( buffer, "PCI#0x%x#%s#%i#%i#%i\n", snd_pci_probes[ idx ].type, snd_pci_probes[ idx ].name, pcidev.bus, PCI_SLOT( pcidev.devfn ), PCI_FUNC( pcidev.devfn ) );
    }
  }
#endif
}

static int snd_detect_info_init( void )
{
  snd_info_entry_t *entry;

  entry = snd_info_create_entry( NULL, "detect" );
  if ( !entry ) return -ENOMEM;
  entry -> t.text.read_size = PAGE_SIZE;
  entry -> t.text.read = snd_detect_read;
  if ( snd_info_register( entry ) < 0 ) {
    snd_info_free_entry( entry );
    return -ENOMEM;
  }
  snd_detect_info_entry = entry;
  return 0;
}

static int snd_detect_info_done( void )
{
  if ( snd_detect_info_entry )
    snd_info_unregister( snd_detect_info_entry );
  return 0;
}

int init_module( void )
{
#ifndef LINUX_2_1
  register_symtab( NULL );
#endif
  return snd_detect_info_init();
}

void cleanup_module( void )
{
  snd_detect_info_done();
}