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 18int32 api_version = B_CUR_DRIVER_API_VERSION; 19 20size_t gNumCards = 0; 21Device *gDevices[MAX_DEVICES] = { 0 }; 22char *gDeviceNames[MAX_DEVICES + 1] = { 0 }; 23pci_module_info *gPCI = NULL; 24 25 26static Device::Info cardInfos[] = { 27 { SiS7018, "SiS 7018" }, 28 { ALi5451, "ALi M5451" }, 29 { TridentDX, "Trident DX" }, 30 { TridentNX, "Trident NX" } 31}; 32 33 34status_t 35init_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 < _countof(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 60status_t 61init_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 < _countof(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 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 120void 121uninit_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 139static status_t 140SiS7018_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 155static status_t 156SiS7018_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 163static status_t 164SiS7018_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 172static status_t 173SiS7018_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 180static status_t 181SiS7018_close(void *cookie) 182{ 183 Device *device = (Device *)cookie; 184 return device->Close(); 185} 186 187 188static status_t 189SiS7018_free(void *cookie) 190{ 191 Device *device = (Device *)cookie; 192 return device->Free(); 193} 194 195 196const char ** 197publish_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 211device_hooks * 212find_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