xref: /qemu/hw/audio/soundhw.c (revision ca89f72092bdb42e077f2f64f417edad009ce0ef)
1*ca89f720SEduardo Habkost /*
2*ca89f720SEduardo Habkost  * QEMU System Emulator
3*ca89f720SEduardo Habkost  *
4*ca89f720SEduardo Habkost  * Copyright (c) 2003-2008 Fabrice Bellard
5*ca89f720SEduardo Habkost  *
6*ca89f720SEduardo Habkost  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*ca89f720SEduardo Habkost  * of this software and associated documentation files (the "Software"), to deal
8*ca89f720SEduardo Habkost  * in the Software without restriction, including without limitation the rights
9*ca89f720SEduardo Habkost  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10*ca89f720SEduardo Habkost  * copies of the Software, and to permit persons to whom the Software is
11*ca89f720SEduardo Habkost  * furnished to do so, subject to the following conditions:
12*ca89f720SEduardo Habkost  *
13*ca89f720SEduardo Habkost  * The above copyright notice and this permission notice shall be included in
14*ca89f720SEduardo Habkost  * all copies or substantial portions of the Software.
15*ca89f720SEduardo Habkost  *
16*ca89f720SEduardo Habkost  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*ca89f720SEduardo Habkost  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*ca89f720SEduardo Habkost  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19*ca89f720SEduardo Habkost  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*ca89f720SEduardo Habkost  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*ca89f720SEduardo Habkost  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22*ca89f720SEduardo Habkost  * THE SOFTWARE.
23*ca89f720SEduardo Habkost  */
24*ca89f720SEduardo Habkost #include "qemu/osdep.h"
25*ca89f720SEduardo Habkost #include "qemu-common.h"
26*ca89f720SEduardo Habkost #include "qemu/help_option.h"
27*ca89f720SEduardo Habkost #include "qemu/error-report.h"
28*ca89f720SEduardo Habkost #include "qom/object.h"
29*ca89f720SEduardo Habkost #include "hw/isa/isa.h"
30*ca89f720SEduardo Habkost #include "hw/pci/pci.h"
31*ca89f720SEduardo Habkost #include "hw/audio/audio.h"
32*ca89f720SEduardo Habkost 
33*ca89f720SEduardo Habkost struct soundhw {
34*ca89f720SEduardo Habkost     const char *name;
35*ca89f720SEduardo Habkost     const char *descr;
36*ca89f720SEduardo Habkost     int enabled;
37*ca89f720SEduardo Habkost     int isa;
38*ca89f720SEduardo Habkost     union {
39*ca89f720SEduardo Habkost         int (*init_isa) (ISABus *bus);
40*ca89f720SEduardo Habkost         int (*init_pci) (PCIBus *bus);
41*ca89f720SEduardo Habkost     } init;
42*ca89f720SEduardo Habkost };
43*ca89f720SEduardo Habkost 
44*ca89f720SEduardo Habkost static struct soundhw soundhw[9];
45*ca89f720SEduardo Habkost static int soundhw_count;
46*ca89f720SEduardo Habkost 
47*ca89f720SEduardo Habkost void isa_register_soundhw(const char *name, const char *descr,
48*ca89f720SEduardo Habkost                           int (*init_isa)(ISABus *bus))
49*ca89f720SEduardo Habkost {
50*ca89f720SEduardo Habkost     assert(soundhw_count < ARRAY_SIZE(soundhw) - 1);
51*ca89f720SEduardo Habkost     soundhw[soundhw_count].name = name;
52*ca89f720SEduardo Habkost     soundhw[soundhw_count].descr = descr;
53*ca89f720SEduardo Habkost     soundhw[soundhw_count].isa = 1;
54*ca89f720SEduardo Habkost     soundhw[soundhw_count].init.init_isa = init_isa;
55*ca89f720SEduardo Habkost     soundhw_count++;
56*ca89f720SEduardo Habkost }
57*ca89f720SEduardo Habkost 
58*ca89f720SEduardo Habkost void pci_register_soundhw(const char *name, const char *descr,
59*ca89f720SEduardo Habkost                           int (*init_pci)(PCIBus *bus))
60*ca89f720SEduardo Habkost {
61*ca89f720SEduardo Habkost     assert(soundhw_count < ARRAY_SIZE(soundhw) - 1);
62*ca89f720SEduardo Habkost     soundhw[soundhw_count].name = name;
63*ca89f720SEduardo Habkost     soundhw[soundhw_count].descr = descr;
64*ca89f720SEduardo Habkost     soundhw[soundhw_count].isa = 0;
65*ca89f720SEduardo Habkost     soundhw[soundhw_count].init.init_pci = init_pci;
66*ca89f720SEduardo Habkost     soundhw_count++;
67*ca89f720SEduardo Habkost }
68*ca89f720SEduardo Habkost 
69*ca89f720SEduardo Habkost void select_soundhw(const char *optarg)
70*ca89f720SEduardo Habkost {
71*ca89f720SEduardo Habkost     struct soundhw *c;
72*ca89f720SEduardo Habkost 
73*ca89f720SEduardo Habkost     if (is_help_option(optarg)) {
74*ca89f720SEduardo Habkost     show_valid_cards:
75*ca89f720SEduardo Habkost 
76*ca89f720SEduardo Habkost         if (soundhw_count) {
77*ca89f720SEduardo Habkost              printf("Valid sound card names (comma separated):\n");
78*ca89f720SEduardo Habkost              for (c = soundhw; c->name; ++c) {
79*ca89f720SEduardo Habkost                  printf ("%-11s %s\n", c->name, c->descr);
80*ca89f720SEduardo Habkost              }
81*ca89f720SEduardo Habkost              printf("\n-soundhw all will enable all of the above\n");
82*ca89f720SEduardo Habkost         } else {
83*ca89f720SEduardo Habkost              printf("Machine has no user-selectable audio hardware "
84*ca89f720SEduardo Habkost                     "(it may or may not have always-present audio hardware).\n");
85*ca89f720SEduardo Habkost         }
86*ca89f720SEduardo Habkost         exit(!is_help_option(optarg));
87*ca89f720SEduardo Habkost     }
88*ca89f720SEduardo Habkost     else {
89*ca89f720SEduardo Habkost         size_t l;
90*ca89f720SEduardo Habkost         const char *p;
91*ca89f720SEduardo Habkost         char *e;
92*ca89f720SEduardo Habkost         int bad_card = 0;
93*ca89f720SEduardo Habkost 
94*ca89f720SEduardo Habkost         if (!strcmp(optarg, "all")) {
95*ca89f720SEduardo Habkost             for (c = soundhw; c->name; ++c) {
96*ca89f720SEduardo Habkost                 c->enabled = 1;
97*ca89f720SEduardo Habkost             }
98*ca89f720SEduardo Habkost             return;
99*ca89f720SEduardo Habkost         }
100*ca89f720SEduardo Habkost 
101*ca89f720SEduardo Habkost         p = optarg;
102*ca89f720SEduardo Habkost         while (*p) {
103*ca89f720SEduardo Habkost             e = strchr(p, ',');
104*ca89f720SEduardo Habkost             l = !e ? strlen(p) : (size_t) (e - p);
105*ca89f720SEduardo Habkost 
106*ca89f720SEduardo Habkost             for (c = soundhw; c->name; ++c) {
107*ca89f720SEduardo Habkost                 if (!strncmp(c->name, p, l) && !c->name[l]) {
108*ca89f720SEduardo Habkost                     c->enabled = 1;
109*ca89f720SEduardo Habkost                     break;
110*ca89f720SEduardo Habkost                 }
111*ca89f720SEduardo Habkost             }
112*ca89f720SEduardo Habkost 
113*ca89f720SEduardo Habkost             if (!c->name) {
114*ca89f720SEduardo Habkost                 if (l > 80) {
115*ca89f720SEduardo Habkost                     error_report("Unknown sound card name (too big to show)");
116*ca89f720SEduardo Habkost                 }
117*ca89f720SEduardo Habkost                 else {
118*ca89f720SEduardo Habkost                     error_report("Unknown sound card name `%.*s'",
119*ca89f720SEduardo Habkost                                  (int) l, p);
120*ca89f720SEduardo Habkost                 }
121*ca89f720SEduardo Habkost                 bad_card = 1;
122*ca89f720SEduardo Habkost             }
123*ca89f720SEduardo Habkost             p += l + (e != NULL);
124*ca89f720SEduardo Habkost         }
125*ca89f720SEduardo Habkost 
126*ca89f720SEduardo Habkost         if (bad_card) {
127*ca89f720SEduardo Habkost             goto show_valid_cards;
128*ca89f720SEduardo Habkost         }
129*ca89f720SEduardo Habkost     }
130*ca89f720SEduardo Habkost }
131*ca89f720SEduardo Habkost 
132*ca89f720SEduardo Habkost void audio_init(void)
133*ca89f720SEduardo Habkost {
134*ca89f720SEduardo Habkost     struct soundhw *c;
135*ca89f720SEduardo Habkost     ISABus *isa_bus = (ISABus *) object_resolve_path_type("", TYPE_ISA_BUS, NULL);
136*ca89f720SEduardo Habkost     PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL);
137*ca89f720SEduardo Habkost 
138*ca89f720SEduardo Habkost     for (c = soundhw; c->name; ++c) {
139*ca89f720SEduardo Habkost         if (c->enabled) {
140*ca89f720SEduardo Habkost             if (c->isa) {
141*ca89f720SEduardo Habkost                 if (!isa_bus) {
142*ca89f720SEduardo Habkost                     error_report("ISA bus not available for %s", c->name);
143*ca89f720SEduardo Habkost                     exit(1);
144*ca89f720SEduardo Habkost                 }
145*ca89f720SEduardo Habkost                 c->init.init_isa(isa_bus);
146*ca89f720SEduardo Habkost             } else {
147*ca89f720SEduardo Habkost                 if (!pci_bus) {
148*ca89f720SEduardo Habkost                     error_report("PCI bus not available for %s", c->name);
149*ca89f720SEduardo Habkost                     exit(1);
150*ca89f720SEduardo Habkost                 }
151*ca89f720SEduardo Habkost                 c->init.init_pci(pci_bus);
152*ca89f720SEduardo Habkost             }
153*ca89f720SEduardo Habkost         }
154*ca89f720SEduardo Habkost     }
155*ca89f720SEduardo Habkost }
156*ca89f720SEduardo Habkost 
157