[haiku-commits] r40272 - haiku/branches/developer/siarzhuk/sis7018

  • From: zharik@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 23 Jan 2011 17:20:35 +0100 (CET)

Author: siarzhuk
Date: 2011-01-23 17:20:35 +0100 (Sun, 23 Jan 2011)
New Revision: 40272
Changeset: http://dev.haiku-os.org/changeset/40272

Added:
   haiku/branches/developer/siarzhuk/sis7018/Mixer.cpp
   haiku/branches/developer/siarzhuk/sis7018/Mixer.h
Removed:
   haiku/branches/developer/siarzhuk/sis7018/AC97.cpp
   haiku/branches/developer/siarzhuk/sis7018/AC97.h
Modified:
   haiku/branches/developer/siarzhuk/sis7018/Device.cpp
   haiku/branches/developer/siarzhuk/sis7018/Device.h
   haiku/branches/developer/siarzhuk/sis7018/Driver.cpp
   haiku/branches/developer/siarzhuk/sis7018/Driver.h
   haiku/branches/developer/siarzhuk/sis7018/Jamfile
   haiku/branches/developer/siarzhuk/sis7018/Registers.h
   haiku/branches/developer/siarzhuk/sis7018/Settings.cpp
   haiku/branches/developer/siarzhuk/sis7018/Settings.h
   haiku/branches/developer/siarzhuk/sis7018/Stream.cpp
   haiku/branches/developer/siarzhuk/sis7018/Stream.h
   haiku/branches/developer/siarzhuk/sis7018/makefile
   haiku/branches/developer/siarzhuk/sis7018/sis7018.settings.sample
Log:
Rewriting of SiS7018 Audio driver to Haiku Multi-Audio API finished. It is 
ready to replace old R?\195?\1303 API one in the Haiku trunk.

Modified: haiku/branches/developer/siarzhuk/sis7018/Device.cpp
===================================================================
--- haiku/branches/developer/siarzhuk/sis7018/Device.cpp        2011-01-22 
22:12:21 UTC (rev 40271)
+++ haiku/branches/developer/siarzhuk/sis7018/Device.cpp        2011-01-23 
16:20:35 UTC (rev 40272)
@@ -1,115 +1,155 @@
 /*
- *     SiS 7018 Audio Driver.
- *     Copyright (c) 2002, 2008, 2009 S.Zharski <imker@xxxxxx>
+ *     SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver.
+ *     Copyright (c) 2002, 2008-2011 S.Zharski <imker@xxxxxx>
  *     Distributed under the terms of the MIT license.
  *
+ *     Copyright for ali5451 support:
+ *             (c) 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com).
  */
 
-#include <lock.h>
-#include "Driver.h"
-#include "Settings.h"
+
 #include "Device.h"
-#include "Registers.h"
 
-const uint16 TrCodecTimeout = 0xffff;
+#include <string.h>
 
-/*class SmartLock {
-       mutex &fMutex;
-public:
-       SmartLock(mutex &m):fMutex(m)
-                               { mutex_lock(&fMutex); }
-       ~SmartLock() { mutex_unlock(&fMutex); }
-};*/
+#include "Settings.h"
+#include "Registers.h"
 
+
 Device::Device(Device::Info &DeviceInfo, pci_info &PCIInfo)
-       :       fStatus(B_ERROR),
+               :       
+               fStatus(B_ERROR),
                fPCIInfo(PCIInfo),
                fInfo(DeviceInfo),
-               fAC97(this),
                fIOBase(0),
                fHWSpinlock(0),
-               fPlaybackStream(this, false, 0),
-               fRecordStream(this, 10),
-               fInterruptsNest(0)
-                /*fOpen(false),
-               fDevice(device),
-               fNonBlocking(false),            
-               fNotifyWriteSem(-1),
-               */
+               fInterruptsNest(0),
+               fBuffersReadySem(-1),
+               fMixer(this),
+               fPlaybackStream(this, false),
+               fRecordStream(this, true)
 {
-//     mutex_init(&fInitMutex, "Init_"DRIVER_NAME);
-       //SmartLock lock(fInitMutex);
        fStatus = _ReserveDeviceOnBus(true);
        if (fStatus != B_OK)
-               return; // InitCheck will handle the rest       
+               return; // InitCheck will handle the rest
 
-       uint32 cmdRegister = gPCIModule->read_pci_config(PCIInfo.bus,
+       uint32 cmdRegister = gPCI->read_pci_config(PCIInfo.bus,
                                                        PCIInfo.device, 
PCIInfo.function, PCI_command, 2);
-       TRACE_ALWAYS("cmdRegister:%#010x\n", cmdRegister);
+       TRACE("cmdRegister:%#010x\n", cmdRegister);
        cmdRegister |= PCI_command_io | PCI_command_memory | PCI_command_master;
-       gPCIModule->write_pci_config(PCIInfo.bus, PCIInfo.device,
+       gPCI->write_pci_config(PCIInfo.bus, PCIInfo.device,
                                                        PCIInfo.function, 
PCI_command, 2, cmdRegister);
 
        fIOBase = PCIInfo.u.h0.base_registers[0];
-       TRACE_ALWAYS("fIOBase:%#010x\n", fIOBase);
+       TRACE("fIOBase:%#010x\n", fIOBase);
        
-       cpu_status cp = disable_interrupts();
-       acquire_spinlock(&fHWSpinlock);
-
-       switch (fInfo.Id()) {
-               case SiS7018:
-                       WritePCI32(0x4c, 0x00000000);
-                       WritePCI32(SiSCodecStatusReg, 0x000f0000);
-                       break;
-               case TridentDX:
-                       WritePCI32(TDXCodecStatusReg, 0x2|0x4); // DAC on | ADC 
on
-                       break;
-               case TridentNX:
-                       WritePCI32(TNXCodecStatusReg, 0x2|0x8); // DAC on | ADC 
on
-                       break;
-       }
-       
-       WritePCI32(TrChIndexReg, 0x1000 | 0x2000 | 0x10000); // end | mid INT 
enable 64-ch mode
-
-       release_spinlock(&fHWSpinlock);
-       restore_interrupts(cp);
-
-       fPlaybackStream.Init();
-       fRecordStream.Init();
-
-       fBuffersReadySem = create_sem(0, DRIVER_NAME "_buffers_ready");
-       
-       fStatus = fAC97.Init();
+       fStatus = B_OK;
 }
 
 
 Device::~Device()
 {
-//     mutex_destroy(&fInitMutex);
+       fMixer.Free();
        _ReserveDeviceOnBus(false);
-       
+
        if (fBuffersReadySem > B_OK) {
                delete_sem(fBuffersReadySem);
-       }       
+       }
 }
 
 
+void
+Device::_ResetCard(uint32 resetMask, uint32 releaseMask)
+{
+       // disable Legacy Control
+       gPCI->write_pci_config(fPCIInfo.bus, fPCIInfo.device,
+                                               fPCIInfo.function, 0x40, 4, 0);
+       uint32 cmdReg = gPCI->read_pci_config(fPCIInfo.bus, fPCIInfo.device,
+                                               fPCIInfo.function, 0x44, 4);
+       gPCI->write_pci_config(fPCIInfo.bus, fPCIInfo.device,
+                                               fPCIInfo.function, 0x44, 4, 
cmdReg & 0xffff0000);
+       snooze(100);
+
+       // audio engine reset
+       cmdReg = gPCI->read_pci_config(fPCIInfo.bus, fPCIInfo.device,
+                                               fPCIInfo.function, 0x44, 4);
+       gPCI->write_pci_config(fPCIInfo.bus, fPCIInfo.device,
+                                               fPCIInfo.function, 0x44, 4, 
cmdReg | resetMask);
+       snooze(100);
+
+       // release reset
+       cmdReg = gPCI->read_pci_config(fPCIInfo.bus, fPCIInfo.device,
+                                               fPCIInfo.function, 0x44, 4);
+       gPCI->write_pci_config(fPCIInfo.bus, fPCIInfo.device,
+                                               fPCIInfo.function, 0x44, 4, 
cmdReg & ~releaseMask);
+       snooze(100);
+}
+
+
 status_t
-Device::_ReserveDeviceOnBus(bool reserve)
+Device::Setup()
 {
-       status_t result = B_NO_INIT;
-       if (reserve) {
-               result = gPCIModule->reserve_device(fPCIInfo.bus, 
fPCIInfo.device,
-                                                       fPCIInfo.function, 
DRIVER_NAME, this);
-               if (result != B_OK)
-                       TRACE_ALWAYS("Unable to reserve PCI device %d:%d:%d on 
bus:%#010x\n",
-                                       fPCIInfo.bus, fPCIInfo.device, 
fPCIInfo.function, result);
-       } else {
-               result = gPCIModule->unreserve_device(fPCIInfo.bus, 
fPCIInfo.device,
-                                                       fPCIInfo.function, 
DRIVER_NAME, this);
+       cpu_status cp = 0;
+       uint32 channelsIndex = ChIndexMidEna | ChIndexEndEna;
+
+       switch (HardwareId()) {
+               case SiS7018:
+                       _ResetCard(0x000c0000, 0x00040000);
+
+                       cp = Lock();
+
+                       WritePCI32(RegSiSCodecGPIO, 0x00000000); 
+                       WritePCI32(RegSiSCodecStatus, SiSCodecResetOff);
+                       channelsIndex |= ChIndexSiSEnaB;
+
+                       Unlock(cp);
+                       break;
+
+               case ALi5451:
+                       _ResetCard(0x000c0000, 0x00040000);
+
+                       cp = Lock();
+                       WritePCI32(RegALiDigiMixer, ALiDigiMixerPCMIn); 
+                       WritePCI32(RegALiVolumeA, 0);
+                       Unlock(cp);
+                       break;
+
+               case TridentNX:
+                       _ResetCard(0x00010000, 0x00010000);
+
+                       cp = Lock();
+                       WritePCI32(RegNXCodecStatus, NXCodecStatusDAC1ON); 
+                       Unlock(cp);
+                       break;
+
+               case TridentDX:
+                       _ResetCard(0x00040000, 0x00040000);
+
+                       cp = Lock();
+                       WritePCI32(RegCodecStatus, CodecStatusDACON);
+                       Unlock(cp);
+                       break;
        }
 
-       return result;
+       // clear channels status
+       WritePCI32(RegStopA, 0xffffffff);
+       WritePCI32(RegStopB, 0xffffffff);
+
+       // disable channels interrupt
+       WritePCI32(RegEnaINTA, 0x00000000);
+       WritePCI32(RegEnaINTB, 0x00000000);
+
+       // enable loop interrupts
+       WritePCI32(RegChIndex, channelsIndex);
+
+       fRecordStream.Init();
+       fPlaybackStream.Init();
+
+       fBuffersReadySem = create_sem(0, DRIVER_NAME "_buffers_ready");
+
+       fMixer.Init();
+       
+       return B_OK;
 }
 
 
@@ -117,30 +157,25 @@
 Device::Open(uint32 flags)
 {
        TRACE("flags:%x\n", flags);
-/*     if (fOpen)
-               return B_BUSY;
-       
-       fNonBlocking = (flags & O_NONBLOCK) == O_NONBLOCK;
-       fOpen = true;
-       return result; */
-       
+
        if (atomic_add(&fInterruptsNest, 1) == 0) {
                install_io_interrupt_handler(fPCIInfo.u.h0.interrupt_line,
-                                                                               
                        InterruptHandler, this, 0);
+                                                                               
                InterruptHandler, this, 0);
                TRACE("Interrupt handler installed at line %d.\n",
-                                                                               
                        fPCIInfo.u.h0.interrupt_line);
+                                                                               
                fPCIInfo.u.h0.interrupt_line);
        }
 
-       status_t status = fPlaybackStream.Start();
+       status_t status = fRecordStream.Start();
        if (status != B_OK) {
-               TRACE_ALWAYS("Error of starting playback stream:%#010x\n", 
status);
+               ERROR("Error of starting record stream:%#010x\n", status);
        }
 
-       status = fRecordStream.Start();
+       status = fPlaybackStream.Start();
        if (status != B_OK) {
-               TRACE_ALWAYS("Error of starting record stream:%#010x\n", 
status);
+               ERROR("Error of starting playback stream:%#010x\n", status);
        }
 
+
        return B_OK;
 }
 
@@ -149,33 +184,24 @@
 Device::Close()
 {
        TRACE("closed!\n");
-       
+
        status_t status = fPlaybackStream.Stop();
        if (status != B_OK) {
-               TRACE_ALWAYS("Error of stopping playback stream:%#010x\n", 
status);
+               ERROR("Error of stopping playback stream:%#010x\n", status);
        }
 
        status = fRecordStream.Stop();
        if (status != B_OK) {
-               TRACE_ALWAYS("Error of stopping record stream:%#010x\n", 
status);
+               ERROR("Error of stopping record stream:%#010x\n", status);
        }
-       
+
        if (atomic_add(&fInterruptsNest, -1) == 1) {
                remove_io_interrupt_handler(fPCIInfo.u.h0.interrupt_line,
-                                                                               
                        InterruptHandler, this);
+                                                                               
                InterruptHandler, this);
                TRACE("Interrupt handler at line %d uninstalled.\n",
-                                                                               
                        fPCIInfo.u.h0.interrupt_line);
+                                                                               
                fPCIInfo.u.h0.interrupt_line);
        }
 
-/*     if (fRemoved) {
-               fOpen = false;
-               return B_OK;
-       }
-
-       fOpen = false;
-       
-       return StopDevice();*/
-
        return B_OK;
 }
 
@@ -214,12 +240,15 @@
                case B_MULTI_GET_EVENT_INFO:
                        TRACE(("B_MULTI_GET_EVENT_INFO\n"));
                        return B_ERROR;
+
                case B_MULTI_SET_EVENT_INFO:
                        TRACE(("B_MULTI_SET_EVENT_INFO\n"));
                        return B_ERROR;
+
                case B_MULTI_GET_EVENT:
                        TRACE(("B_MULTI_GET_EVENT\n"));
                        return B_ERROR;
+
                case B_MULTI_GET_ENABLED_CHANNELS:
                        return 
_MultiGetEnabledChannels((multi_channel_enable*)buffer);
 
@@ -235,9 +264,11 @@
                case B_MULTI_GET_CHANNEL_FORMATS:
                        TRACE(("B_MULTI_GET_CHANNEL_FORMATS\n"));
                        return B_ERROR;
-               case B_MULTI_SET_CHANNEL_FORMATS:       /* only implemented if 
possible */
+
+               case B_MULTI_SET_CHANNEL_FORMATS:
                        TRACE(("B_MULTI_SET_CHANNEL_FORMATS\n"));
                        return B_ERROR;
+
                case B_MULTI_GET_MIX:
                        return _MultiGetMix((multi_mix_value_info *)buffer);
 
@@ -246,30 +277,35 @@
 
                case B_MULTI_LIST_MIX_CHANNELS:
                        TRACE(("B_MULTI_LIST_MIX_CHANNELS\n"));
-                       return B_ERROR;//auich_list_mix_channels(card, 
(multi_mix_channel_info *)data);
+                       return B_ERROR;
+
                case B_MULTI_LIST_MIX_CONTROLS:
                        return 
_MultiListMixControls((multi_mix_control_info*)buffer);
 
                case B_MULTI_LIST_MIX_CONNECTIONS:
                        TRACE(("B_MULTI_LIST_MIX_CONNECTIONS\n"));
-                       return B_ERROR;//auich_list_mix_connections(card, 
(multi_mix_connection_info *)data);
-               case B_MULTI_GET_BUFFERS:                       /* Fill out the 
struct for the first time; doesn't start anything. */
+                       return B_ERROR;
+
+               case B_MULTI_GET_BUFFERS:
                        return _MultiGetBuffers((multi_buffer_list*)buffer);
 
-               case B_MULTI_SET_BUFFERS:                       /* Set what 
buffers to use, if the driver supports soft buffers. */
+               case B_MULTI_SET_BUFFERS:
                        TRACE(("B_MULTI_SET_BUFFERS\n"));
-                       return B_ERROR; /* we do not support soft buffers */
-               case B_MULTI_SET_START_TIME:                    /* When to 
actually start */
+                       return B_ERROR;
+
+               case B_MULTI_SET_START_TIME:
                        TRACE(("B_MULTI_SET_START_TIME\n"));
                        return B_ERROR;
-               case B_MULTI_BUFFER_EXCHANGE:           /* stop and go are 
derived from this being called */
+
+               case B_MULTI_BUFFER_EXCHANGE:
                        return _MultiBufferExchange((multi_buffer_info*)buffer);
 
-               case B_MULTI_BUFFER_FORCE_STOP:         /* force stop of 
playback, nothing in data */
+               case B_MULTI_BUFFER_FORCE_STOP:
                        TRACE(("B_MULTI_BUFFER_FORCE_STOP\n"));
-                       return B_ERROR;//auich_buffer_force_stop(card);
+                       return B_ERROR;
+
                default:
-                       TRACE_ALWAYS("Unhandled IOCTL catched: %#010x\n", op);
+                       ERROR("Unhandled IOCTL catched: %#010x\n", op);
        }
 
        return B_DEV_INVALID_IOCTL;
@@ -277,177 +313,6 @@
 
 
 status_t
-Device::SetupDevice()
-{
-       return B_OK;
-}
-
-
-void
-Device::TeardownDevice()
-{
-       
-}
-
-
-uint16
-Device::ReadCodec(uint8 cdcReg)
-{
-       uint8 rdReg = SiSCodecReadReg;
-       uint32 statusRW = 0x00008000;
-       switch (fInfo.Id()) {
-               case SiS7018:
-                       break;
-               case TridentDX:
-                       rdReg = TDXCodecReadReg;
-                       statusRW = 0x00008000;
-                       break;
-               case TridentNX:
-                       // TODO !!!!
-                       rdReg = TNXCodecReadReg;
-                       statusRW = 0x00000c00;
-                       break;
-               case ALi5451:
-                       // TODO !!!!
-                       rdReg = TDXCodecReadReg;
-                       statusRW = 0x00008000;
-                       break;
-       }
-
-       // TODO for Ali!!
-       cpu_status cp = disable_interrupts();
-       acquire_spinlock(&fHWSpinlock);
-       
-       cdcReg &= 0x7f;
-       
-       WritePCI32(rdReg, cdcReg | statusRW);
-       
-       uint32 status = statusRW;
-       uint16 TO = TrCodecTimeout;
-       for (; TO > 0 && (status & statusRW); TO--) {
-               status = ReadPCI32(rdReg);
-       }
-
-       release_spinlock(&fHWSpinlock);
-       restore_interrupts(cp);
-       
-       if (TO == 0) {
-               TRACE_ALWAYS("Timed out reg:%#04x.\n", cdcReg);
-       }
-
-       return (status >> 16) & 0xffff;
-}
-
-
-status_t
-Device::WriteCodec(uint8 cdcReg, uint16 value)
-{
-       uint8 wrReg = SiSCodecWriteReg;
-       uint32 statusRW = 0x00008000;
-       switch (fInfo.Id()) {
-               case SiS7018:
-                       break;
-               case TridentDX:
-                       wrReg = TDXCodecWriteReg;
-                       statusRW = 0x00008000;
-                       break;
-               case TridentNX:
-                       // TODO !!!!
-                       wrReg = TNXCodecWriteReg;
-                       statusRW = 0x00000c00;
-                       break;
-               case ALi5451:
-                       // TODO !!!!
-                       wrReg = TDXCodecWriteReg;
-                       statusRW = 0x00008000;
-                       break;
-       }
-
-       // TODO for Ali!!
-       cpu_status cp = disable_interrupts();
-       acquire_spinlock(&fHWSpinlock);
-       
-       cdcReg &= 0x7f;
-       uint32 status = statusRW;
-               
-       uint16 TO = TrCodecTimeout;
-       for (; TO > 0 && (status & statusRW); TO--) {
-               status = ReadPCI32(wrReg);
-       }
-       
-       WritePCI32(wrReg, (value << 16) | cdcReg | statusRW);
-
-       release_spinlock(&fHWSpinlock);
-       restore_interrupts(cp);
-       
-       if (TO == 0) {
-               TRACE_ALWAYS("Timed out reg:%#04x.\n", cdcReg);
-       }
-
-       return (TO > 0) ? B_OK : B_TIMED_OUT;
-}
-
-       
-uint8
-Device::ReadPCI8(int offset)
-{
-       return gPCIModule->read_io_8(fIOBase + offset);
-}
-
-
-uint16
-Device::ReadPCI16(int offset)
-{
-       return gPCIModule->read_io_16(fIOBase + offset);
-}
-
-
-uint32
-Device::ReadPCI32(int offset)
-{
-       return gPCIModule->read_io_32(fIOBase + offset);
-}
-
-
-void
-Device::WritePCI8(int offset, uint8 value)
-{
-       gPCIModule->write_io_8(fIOBase + offset, value);
-}
-
-
-void
-Device::WritePCI16(int offset, uint16 value)
-{
-       gPCIModule->write_io_16(fIOBase + offset, value);
-}
-
-
-void
-Device::WritePCI32(int offset, uint32 value)
-{
-       gPCIModule->write_io_32(fIOBase + offset, value);
-}
-
-
-cpu_status
-Device::Lock()
-{
-       cpu_status st = disable_interrupts();
-       acquire_spinlock(&fHWSpinlock);
-       return st;
-}
-
-
-void
-Device::Unlock(cpu_status st)
-{
-       release_spinlock(&fHWSpinlock);
-       restore_interrupts(st);
-}
-
-
-status_t
 Device::_MultiGetDescription(multi_description *multiDescription)
 {
        multi_channel_info channel_descriptions[] = {
@@ -455,39 +320,45 @@
                { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | 
B_CHANNEL_STEREO_BUS, 0 },
                { 2, B_MULTI_INPUT_CHANNEL,      B_CHANNEL_LEFT | 
B_CHANNEL_STEREO_BUS,  0 },
                { 3, B_MULTI_INPUT_CHANNEL,      B_CHANNEL_RIGHT | 
B_CHANNEL_STEREO_BUS, 0 },
-               { 4, B_MULTI_OUTPUT_BUS,         B_CHANNEL_LEFT | 
B_CHANNEL_STEREO_BUS,  B_CHANNEL_MINI_JACK_STEREO },
-               { 5, B_MULTI_OUTPUT_BUS,         B_CHANNEL_RIGHT | 
B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
-               { 6, B_MULTI_INPUT_BUS,          B_CHANNEL_LEFT | 
B_CHANNEL_STEREO_BUS,  B_CHANNEL_MINI_JACK_STEREO },
-               { 7, B_MULTI_INPUT_BUS,          B_CHANNEL_RIGHT | 
B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
+               { 4, B_MULTI_OUTPUT_BUS,         B_CHANNEL_LEFT | 
B_CHANNEL_STEREO_BUS,
+                                                                               
B_CHANNEL_MINI_JACK_STEREO },
+               { 5, B_MULTI_OUTPUT_BUS,         B_CHANNEL_RIGHT | 
B_CHANNEL_STEREO_BUS,
+                                                                               
B_CHANNEL_MINI_JACK_STEREO },
+               { 6, B_MULTI_INPUT_BUS,          B_CHANNEL_LEFT | 
B_CHANNEL_STEREO_BUS,
+                                                                               
B_CHANNEL_MINI_JACK_STEREO },
+               { 7, B_MULTI_INPUT_BUS,          B_CHANNEL_RIGHT | 
B_CHANNEL_STEREO_BUS,
+                                                                               
B_CHANNEL_MINI_JACK_STEREO },
        };
 
        multi_description Description;
-       if (user_memcpy(&Description, multiDescription, 
sizeof(multi_description)) != B_OK)
+       if (user_memcpy(&Description,
+                       multiDescription, sizeof(multi_description)) != B_OK)
                return B_BAD_ADDRESS;
-       
+
        Description.interface_version = B_CURRENT_INTERFACE_VERSION;
        Description.interface_minimum = B_CURRENT_INTERFACE_VERSION;
 
        strncpy(Description.friendly_name, fInfo.Name(),
                                                                        
sizeof(Description.friendly_name));
-       
-       strncpy(Description.vendor_info, "S.Zharski",
+
+       strncpy(Description.vendor_info, "Haiku.Inc.",
                                                                        
sizeof(Description.vendor_info));
-       
+
        Description.output_channel_count                = 2;
        Description.input_channel_count                 = 2;
        Description.output_bus_channel_count    = 2;
        Description.input_bus_channel_count             = 2;
        Description.aux_bus_channel_count               = 0;
 
-       Description.output_rates        = B_SR_48000;
-       Description.input_rates         = B_SR_48000;
+       Description.output_rates        = fMixer.OutputRates();
+       Description.input_rates         = fMixer.InputRates();
 
-       Description.min_cvsr_rate = 0;
-       Description.max_cvsr_rate = 0;
+       Description.output_formats      = fMixer.OutputFormats();
+       Description.input_formats       = fMixer.InputFormats();
 
-       Description.output_formats = B_FMT_16BIT;
-       Description.input_formats = B_FMT_16BIT;
+       Description.min_cvsr_rate       = 0;
+       Description.max_cvsr_rate       = 0;
+
        Description.lock_sources = B_MULTI_LOCK_INTERNAL;
        Description.timecode_sources = 0;
        Description.interface_flags
@@ -496,12 +367,12 @@
 
        Description.control_panel[0] = '\0';
 
-       if (user_memcpy(multiDescription, &Description, 
sizeof(multi_description)) != B_OK)
+       if (user_memcpy(multiDescription,
+                       &Description, sizeof(multi_description)) != B_OK)
                return B_BAD_ADDRESS;
 
        if (Description.request_channel_count
-                       >= (int)(sizeof(channel_descriptions) / 
sizeof(channel_descriptions[0]))) 
-       {
+                       >= (int)(_countof(channel_descriptions))) {
                if (user_memcpy(multiDescription->channels,
                                        &channel_descriptions, 
sizeof(channel_descriptions)) != B_OK)
                        return B_BAD_ADDRESS;
@@ -510,6 +381,7 @@
        return B_OK;
 }
 
+
 status_t
 Device::_MultiGetEnabledChannels(multi_channel_enable *Enable)
 {
@@ -521,6 +393,7 @@
        return B_OK;
 }
 
+
 status_t
 Device::_MultiSetEnabledChannels(multi_channel_enable *Enable)
 {
@@ -535,14 +408,9 @@
 status_t
 Device::_MultiGetGlobalFormat(multi_format_info *Format)
 {
-       Format->output_latency = 0;
-       Format->input_latency = 0;
-       Format->timecode_kind = 0;
+       fPlaybackStream.GetFormat(Format);
+       fRecordStream.GetFormat(Format);
 
-       Format->output.rate     = Format->input.rate = B_SR_48000;
-       Format->output.cvsr     = Format->input.cvsr = 48000;
-       Format->output.format = Format->input.format = B_FMT_16BIT;
-
        return B_OK;
 }
 
@@ -550,28 +418,34 @@
 status_t
 Device::_MultiSetGlobalFormat(multi_format_info *Format)
 {
-       return B_OK;
+       status_t status = fPlaybackStream.SetFormat(Format->output, 
+                                                       fMixer.OutputFormats(), 
fMixer.OutputRates());
+       if (status != B_OK)
+               return status;
+
+       return fRecordStream.SetFormat(Format->input,
+                               fMixer.InputFormats(), fMixer.InputRates());
 }
 
 
 status_t
-Device::_MultiGetMix(multi_mix_value_info *Info)
+Device::_MultiListMixControls(multi_mix_control_info* Info)
 {
-       return fAC97.GetMix(Info);
+       return fMixer.ListMixControls(Info);
 }
 
 
 status_t
-Device::_MultiSetMix(multi_mix_value_info *Info)
+Device::_MultiGetMix(multi_mix_value_info *Info)
 {
-       return fAC97.SetMix(Info);
+       return fMixer.GetMix(Info);
 }
 
 
 status_t
-Device::_MultiListMixControls(multi_mix_control_info* Info)
+Device::_MultiSetMix(multi_mix_value_info *Info)
 {
-       return fAC97.ListMixControls(Info);
+       return fMixer.SetMix(Info);
 }
 
 
@@ -592,33 +466,45 @@
 status_t
 Device::_MultiBufferExchange(multi_buffer_info* bufferInfo)
 {
-       status_t status = acquire_sem_etc(fBuffersReadySem, 1,
-                                                               
B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000);
-       if (status == B_TIMED_OUT) {
-               TRACE_ALWAYS("Timeout during buffers exchange.\n");
-       }
-
        multi_buffer_info BufferInfo;
        if (user_memcpy(&BufferInfo, bufferInfo, sizeof(multi_buffer_info)) != 
B_OK) {
                return B_BAD_ADDRESS;
        }
 
+       status_t status = B_NO_INIT;
+
+       if (!fRecordStream.IsActive()) {
+               status = fRecordStream.Start();
+               if (status != B_OK) {
+                       ERROR("Error of starting record stream:%#010x\n", 
status);
+                       return status;
+               }
+       }
+
+       if (!fPlaybackStream.IsActive()) {
+               status = fPlaybackStream.Start();
+               if (status != B_OK) {
+                       ERROR("Error of starting playback stream:%#010x\n", 
status);
+                       return status;
+               }
+       }
+
+       status = acquire_sem_etc(fBuffersReadySem, 1,
+                                       B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 
50000);
+       if (status == B_TIMED_OUT) {
+               ERROR("Timeout during buffers exchange.\n");
+       }
+
        cpu_status cst = Lock();
 
+       fRecordStream.ExchangeBuffers(BufferInfo.recorded_real_time,
+                       BufferInfo.recorded_frames_count, 
BufferInfo.record_buffer_cycle);
+
        fPlaybackStream.ExchangeBuffers(BufferInfo.played_real_time,
-                                       BufferInfo.played_frames_count, 
BufferInfo.playback_buffer_cycle);
+                       BufferInfo.played_frames_count, 
BufferInfo.playback_buffer_cycle);
 
-       fRecordStream.ExchangeBuffers(BufferInfo.recorded_real_time,
-                                       BufferInfo.recorded_frames_count, 
BufferInfo.record_buffer_cycle);
-       
        Unlock(cst);
 
-//     TRACE("rt:%lld; fc:%lld; bc:%d; csp:%#010x\n", Info->played_real_time,
-//                                     Info->played_frames_count, 
Info->playback_buffer_cycle, fPlaybackStream.fCSP);
-
-       TRACE("rt:%lld; fc:%lld; bc:%d\n", BufferInfo.recorded_real_time,
-                                       BufferInfo.recorded_frames_count, 
BufferInfo.record_buffer_cycle);
-
        if (user_memcpy(bufferInfo, &BufferInfo, sizeof(multi_buffer_info)) != 
B_OK) {
                return B_BAD_ADDRESS;
        }
@@ -626,35 +512,114 @@
        return B_OK;
 }
 
-       
+
 int32
-Device::InterruptHandler(void *InterruptParam)
+Device::InterruptHandler(void *interruptParam)
 {
-       Device *device = (Device*)InterruptParam;
+       Device *device = reinterpret_cast<Device*>(interruptParam);
        if (device == 0) {
-               TRACE_ALWAYS("Invalid parameter in the interrupt handler.\n");
+               ERROR("Invalid parameter in the interrupt handler.\n");
                return B_HANDLED_INTERRUPT;
        }
 
-       int32 result = B_UNHANDLED_INTERRUPT;
+       bool wasHandled = false;
 
        acquire_spinlock(&device->fHWSpinlock);
 
-       uint32 mask = device->ReadPCI32(TrMiscINTReg);
+       uint32 mask = device->ReadPCI32(RegMiscINT);
        if (mask & 0x00000020) {
-               uint32 SignaledChannelsMask = 
device->ReadPCI32(TrAddressINTBReg);
-               
-               result = 
device->fPlaybackStream.InterruptHandler(SignaledChannelsMask);
-
-               if (result == B_UNHANDLED_INTERRUPT)
-                       result = 
device->fRecordStream.InterruptHandler(SignaledChannelsMask);
-               
-               device->WritePCI32(TrAddressINTBReg, SignaledChannelsMask);
-               //result = B_HANDLED_INTERRUPT;
+               wasHandled = device->fRecordStream.InterruptHandler();
+               wasHandled = device->fPlaybackStream.InterruptHandler() || 
wasHandled;
        }
 
        release_spinlock(&device->fHWSpinlock);
-       
+
+       return wasHandled ? B_INVOKE_SCHEDULER : B_UNHANDLED_INTERRUPT;
+}
+
+
+void
+Device::SignalReadyBuffers()
+{
+       release_sem_etc(fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE);
+}
+
+
+status_t
+Device::_ReserveDeviceOnBus(bool reserve)
+{
+       status_t result = B_NO_INIT;
+       if (reserve) {
+               result = gPCI->reserve_device(fPCIInfo.bus, fPCIInfo.device,
+                                                       fPCIInfo.function, 
DRIVER_NAME, this);
+               if (result != B_OK)
+                       ERROR("Unable to reserve PCI device %d:%d:%d on 
bus:%#010x\n",
+                                       fPCIInfo.bus, fPCIInfo.device, 
fPCIInfo.function, result);
+       } else {
+               result = gPCI->unreserve_device(fPCIInfo.bus, fPCIInfo.device,
+                                                       fPCIInfo.function, 
DRIVER_NAME, this);
+       }
+
        return result;
 }
 
+
+uint8
+Device::ReadPCI8(int offset)
+{
+       return gPCI->read_io_8(fIOBase + offset);
+}
+
+
+uint16
+Device::ReadPCI16(int offset)
+{
+       return gPCI->read_io_16(fIOBase + offset);
+}
+
+
+uint32
+Device::ReadPCI32(int offset)
+{
+       return gPCI->read_io_32(fIOBase + offset);
+}
+
+
+void
+Device::WritePCI8(int offset, uint8 value)
+{
+       gPCI->write_io_8(fIOBase + offset, value);
+}
+
+
+void
+Device::WritePCI16(int offset, uint16 value)
+{
+       gPCI->write_io_16(fIOBase + offset, value);
+}
+
+
+void
+Device::WritePCI32(int offset, uint32 value)
+{
+       gPCI->write_io_32(fIOBase + offset, value);
+}
+
+
+cpu_status
+Device::Lock()
+{
+       cpu_status st = disable_interrupts();
+       acquire_spinlock(&fHWSpinlock);
+       return st;
+}
+
+
+void
+Device::Unlock(cpu_status st)
+{
+       release_spinlock(&fHWSpinlock);
+       restore_interrupts(st);
+}
+
+

Modified: haiku/branches/developer/siarzhuk/sis7018/Device.h
===================================================================
--- haiku/branches/developer/siarzhuk/sis7018/Device.h  2011-01-22 22:12:21 UTC 
(rev 40271)
+++ haiku/branches/developer/siarzhuk/sis7018/Device.h  2011-01-23 16:20:35 UTC 
(rev 40272)
@@ -1,20 +1,21 @@
 /*
  *     SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver.
- *     Copyright (c) 2002, 2008 S.Zharski <imker@xxxxxx>
+ *     Copyright (c) 2002, 2008-2011 S.Zharski <imker@xxxxxx>
  *     Distributed under the terms of the MIT license.
  *
  */
-
 #ifndef _SiS7018_DEVICE_H_
 #define _SiS7018_DEVICE_H_
 
-//#include <lock.h>
+
+#include <KernelExport.h>
+
 #include "Driver.h"
-#include "AC97.h"
+#include "Mixer.h"
+#include "Registers.h"
+#include "Settings.h"
 #include "Stream.h"
-//#include "hmulti_audio.h"
 
-//#include <lock.h>
 
 // card ids for supported audio hardware
 const uint32 SiS7018   = 0x70181039;
@@ -23,55 +24,53 @@
 const uint32 TridentNX = 0x20011023;
 
 
-class Device : public Codec {
+class Device {
+
 public:
                class Info {
                public: 
                        const uint32            fId;
                        const char*                     fName;
-       //                                                      Info(const 
uint32 Id, const char* Name)
-       //                                                                      
: fId(Id), fName(Name) { }
                        inline const char*      Name()          { return fName; 
}
                        inline uint16           DeviceId()      { return (fId 
>> 16) & 0xffff; }
                        inline uint16           VendorId()      { return (fId) 
& 0xffff; }
                        inline uint32           Id()            { return fId; }
                };
 
+               uint32                          HardwareId() { return 
fInfo.Id(); }
+               pci_info&                       PCIInfo() { return fPCIInfo; }
+
+
                                                        Device(Info 
&DeviceInfo, pci_info &PCIInfo);
-               virtual                         ~Device();
+                                                       ~Device();
 
+               status_t                        Setup();
                status_t                        InitCheck() { return fStatus; };
 
                status_t                        Open(uint32 flags);
-//             bool                            IsOpen() { return fOpen; };
-
-               status_t                        Close();
-               status_t                        Free();
-
                status_t                        Read(uint8 *buffer, size_t 
*numBytes);
                status_t                        Write(const uint8 *buffer, 
size_t *numBytes);
                status_t                        Control(uint32 op, void 
*buffer, size_t length);
-               
-               status_t                        SetupDevice();
-               void                            TeardownDevice();
+               status_t                        Close();
+               status_t                        Free();
 
+static int32                           InterruptHandler(void *interruptParam);
+               void                            SignalReadyBuffers();
+
+               cpu_status                      Lock();
+               void                            Unlock(cpu_status st);
+
                uint8                           ReadPCI8(int offset);
                uint16                          ReadPCI16(int offset);
                uint32                          ReadPCI32(int offset);
                void                            WritePCI8(int offset, uint8 
value);
                void                            WritePCI16(int offset, uint16 
value);

[... truncated: 2074 lines follow ...]

Other related posts:

  • » [haiku-commits] r40272 - haiku/branches/developer/siarzhuk/sis7018 - zharik