1 /* 2 * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. 3 * Copyright (c) 2002, 2008-2011 S.Zharski <imker@gmx.li> 4 * Distributed under the terms of the MIT license. 5 * 6 */ 7 8 9 #include "Driver.h" 10 11 #include <kernel_cpp.h> 12 #include <string.h> 13 14 #include "Device.h" 15 #include "Settings.h" 16 17 18 int32 api_version = B_CUR_DRIVER_API_VERSION; 19 20 size_t gNumCards = 0; 21 Device *gDevices[MAX_DEVICES] = { 0 }; 22 char *gDeviceNames[MAX_DEVICES + 1] = { 0 }; 23 pci_module_info *gPCI = NULL; 24 25 26 static Device::Info cardInfos[] = { 27 { SiS7018, "SiS 7018" }, 28 { ALi5451, "ALi M5451" }, 29 { TridentDX, "Trident DX" }, 30 { TridentNX, "Trident NX" } 31 }; 32 33 34 status_t 35 init_hardware() 36 { 37 dprintf("sis7018:init_hardware:ver:%s\n", kVersion); 38 status_t result = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI); 39 if (result < B_OK) { 40 return ENOSYS; 41 } 42 43 pci_info info = {0}; 44 for (long i = 0; B_OK == (*gPCI->get_nth_pci_info)(i, &info); i++) { 45 for (size_t idx = 0; idx < B_COUNT_OF(cardInfos); idx++) { 46 if (info.vendor_id == cardInfos[idx].VendorId() && 47 info.device_id == cardInfos[idx].DeviceId()) 48 { 49 put_module(B_PCI_MODULE_NAME); 50 return B_OK; 51 } 52 } 53 } 54 55 put_module(B_PCI_MODULE_NAME); 56 return ENODEV; 57 } 58 59 60 status_t 61 init_driver() 62 { 63 status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI); 64 if (status < B_OK) { 65 return ENOSYS; 66 } 67 68 load_settings(); 69 70 pci_info info = { 0 }; 71 for (long i = 0; B_OK == (*gPCI->get_nth_pci_info)(i, &info); i++) { 72 for (size_t idx = 0; idx < B_COUNT_OF(cardInfos); idx++) { 73 if (info.vendor_id == cardInfos[idx].VendorId() && 74 info.device_id == cardInfos[idx].DeviceId()) 75 { 76 if (gNumCards == MAX_DEVICES) { 77 ERROR("Skipped:%s [%#06x:%#06x]\n", cardInfos[idx].Name(), 78 cardInfos[idx].VendorId(), cardInfos[idx].DeviceId()); 79 break; 80 } 81 82 Device* device = new(std::nothrow) Device(cardInfos[idx], info); 83 if (device == 0) { 84 return ENODEV; 85 } 86 87 status_t status = device->InitCheck(); 88 if (status < B_OK) { 89 delete device; 90 break; 91 } 92 93 status = device->Setup(); 94 if (status < B_OK) { 95 delete device; 96 break; 97 } 98 99 char name[32] = {0}; 100 sprintf(name, "audio/hmulti/%s/%ld", 101 cardInfos[idx].Name(), gNumCards); 102 gDeviceNames[gNumCards] = strdup(name); 103 gDevices[gNumCards++] = device; 104 105 TRACE("Found:%s [%#06x:%#06x]\n", cardInfos[idx].Name(), 106 cardInfos[idx].VendorId(), cardInfos[idx].DeviceId()); 107 } 108 } 109 } 110 111 if (gNumCards == 0) { 112 put_module(B_PCI_MODULE_NAME); 113 return ENODEV; 114 } 115 116 return B_OK; 117 } 118 119 120 void 121 uninit_driver() 122 { 123 for (size_t i = 0; i < MAX_DEVICES; i++) { 124 if (gDevices[i]) { 125 delete gDevices[i]; 126 gDevices[i] = NULL; 127 } 128 129 free(gDeviceNames[i]); 130 gDeviceNames[i] = NULL; 131 } 132 133 put_module(B_PCI_MODULE_NAME); 134 135 release_settings(); 136 } 137 138 139 static status_t 140 SiS7018_open(const char *name, uint32 flags, void **cookie) 141 { 142 status_t status = ENODEV; 143 *cookie = NULL; 144 for (size_t i = 0; i < MAX_DEVICES; i++) { 145 if (gDeviceNames[i] && !strcmp(gDeviceNames[i], name)) { 146 status = gDevices[i]->Open(flags); 147 *cookie = gDevices[i]; 148 } 149 } 150 151 return status; 152 } 153 154 155 static status_t 156 SiS7018_read(void *cookie, off_t position, void *buffer, size_t *numBytes) 157 { 158 Device *device = (Device *)cookie; 159 return device->Read((uint8 *)buffer, numBytes); 160 } 161 162 163 static status_t 164 SiS7018_write(void *cookie, off_t position, 165 const void *buffer, size_t *numBytes) 166 { 167 Device *device = (Device *)cookie; 168 return device->Write((const uint8 *)buffer, numBytes); 169 } 170 171 172 static status_t 173 SiS7018_control(void *cookie, uint32 op, void *buffer, size_t length) 174 { 175 Device *device = (Device *)cookie; 176 return device->Control(op, buffer, length); 177 } 178 179 180 static status_t 181 SiS7018_close(void *cookie) 182 { 183 Device *device = (Device *)cookie; 184 return device->Close(); 185 } 186 187 188 static status_t 189 SiS7018_free(void *cookie) 190 { 191 Device *device = (Device *)cookie; 192 return device->Free(); 193 } 194 195 196 const char ** 197 publish_devices() 198 { 199 for (size_t i = 0; i < MAX_DEVICES; i++) { 200 if (gDevices[i] == NULL) 201 continue; 202 203 if (gDeviceNames[i]) 204 TRACE("%s\n", gDeviceNames[i]); 205 } 206 207 return (const char **)&gDeviceNames[0]; 208 } 209 210 211 device_hooks * 212 find_device(const char *name) 213 { 214 static device_hooks deviceHooks = { 215 SiS7018_open, 216 SiS7018_close, 217 SiS7018_free, 218 SiS7018_control, 219 SiS7018_read, 220 SiS7018_write, 221 NULL, // select 222 NULL // deselect 223 }; 224 225 return &deviceHooks; 226 } 227 228