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