Author: janderwald
Date: Mon Jun 29 17:03:33 2015
New Revision: 68311
URL:
http://svn.reactos.org/svn/reactos?rev=68311&view=rev
Log:
[HDAUDBUS]
- start implementing HDAUDIO Bus driver
- based heavily on Haiku exellent driver
Added:
trunk/reactos/drivers/wdm/audio/hdaudbus/
trunk/reactos/drivers/wdm/audio/hdaudbus/CMakeLists.txt (with props)
trunk/reactos/drivers/wdm/audio/hdaudbus/driver.h (with props)
trunk/reactos/drivers/wdm/audio/hdaudbus/hda_codec_defs.h (with props)
trunk/reactos/drivers/wdm/audio/hdaudbus/hda_controller_defs.h (with props)
trunk/reactos/drivers/wdm/audio/hdaudbus/hdaudbus.cpp (with props)
trunk/reactos/drivers/wdm/audio/hdaudbus/hdaudbus.h (with props)
Modified:
trunk/reactos/drivers/wdm/audio/CMakeLists.txt
Modified: trunk/reactos/drivers/wdm/audio/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/CMakeLis…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/CMakeLists.txt [iso-8859-1] Mon Jun 29 17:03:33 2015
@@ -3,5 +3,6 @@
add_subdirectory(drivers)
add_subdirectory(drm)
add_subdirectory(filters)
+add_subdirectory(hdaudbus)
add_subdirectory(legacy)
add_subdirectory(sysaudio)
Added: trunk/reactos/drivers/wdm/audio/hdaudbus/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/hdaudbus…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/hdaudbus/CMakeLists.txt (added)
+++ trunk/reactos/drivers/wdm/audio/hdaudbus/CMakeLists.txt [iso-8859-1] Mon Jun 29
17:03:33 2015
@@ -0,0 +1,14 @@
+
+set_cpp()
+
+remove_definitions(-D_WIN32_WINNT=0x502)
+add_definitions(-D_WIN32_WINNT=0x600)
+
+list(APPEND SOURCE
+ hdaudbus.cpp)
+
+add_library(hdaudbus SHARED ${SOURCE})
+set_module_type(hdaudbus kernelmodedriver)
+target_link_libraries(hdaudbus libcntpr ${PSEH_LIB})
+add_importlibs(hdaudbus ntoskrnl hal)
+add_cd_file(TARGET hdaudbus DESTINATION reactos/system32/drivers FOR all)
Propchange: trunk/reactos/drivers/wdm/audio/hdaudbus/CMakeLists.txt
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/drivers/wdm/audio/hdaudbus/driver.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/hdaudbus…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/hdaudbus/driver.h (added)
+++ trunk/reactos/drivers/wdm/audio/hdaudbus/driver.h [iso-8859-1] Mon Jun 29 17:03:33
2015
@@ -0,0 +1,402 @@
+/*
+ * Copyright 2007-2012, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * Ithamar Adema, ithamar AT unet DOT nl
+ * Axel Dörfler, axeld(a)pinc-software.de
+ */
+#ifndef _HDA_H_
+#define _HDA_H_
+
+#ifndef __REACTOS__
+#include <KernelExport.h>
+#include <Drivers.h>
+#include <PCI.h>
+#include <PCI_x86.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef HAIKU_TARGET_PLATFORM_HAIKU
+# define DEVFS_PATH_FORMAT "audio/multi/hda/%lu"
+# include <multi_audio.h>
+#else
+# define DEVFS_PATH_FORMAT "audio/hmulti/hda/%lu"
+# include <hmulti_audio.h>
+#endif
+#endif
+
+#include "hda_controller_defs.h"
+#include "hda_codec_defs.h"
+
+#define MAX_CARDS 4
+
+/* values for the class_sub field for class_base = 0x04 (multimedia device) */
+#ifndef __HAIKU__
+# define PCI_hd_audio 3
+#endif
+
+#define HDA_MAX_AUDIO_GROUPS 15
+#define HDA_MAX_CODECS 15
+#define HDA_MAX_STREAMS 16
+#define MAX_CODEC_RESPONSES 16
+#define MAX_CODEC_UNSOL_RESPONSES 16
+#define MAX_INPUTS 32
+#define MAX_IO_WIDGETS 8
+#define MAX_ASSOCIATIONS 16
+#define MAX_ASSOCIATION_PINS 16
+
+#define STREAM_MAX_BUFFERS 10
+#define STREAM_MIN_BUFFERS 2
+
+
+enum {
+ STREAM_PLAYBACK,
+ STREAM_RECORD
+};
+
+struct hda_codec;
+struct hda_stream;
+struct hda_multi;
+
+/*! This structure describes a single HDA compliant
+ controller. It contains a list of available streams
+ for use by the codecs contained, and the messaging queue
+ (verb/response) buffers for communication.
+*/
+#ifndef __REACTOS__
+struct hda_controller {
+ struct pci_info pci_info;
+ int32 opened;
+ const char* devfs_path;
+
+ area_id regs_area;
+ vuint8* regs;
+ uint32 irq;
+ bool msi;
+ bool dma_snooping;
+
+ uint16 codec_status;
+ uint32 num_input_streams;
+ uint32 num_output_streams;
+ uint32 num_bidir_streams;
+
+ uint32 corb_length;
+ uint32 rirb_length;
+ uint32 rirb_read_pos;
+ uint32 corb_write_pos;
+ area_id corb_rirb_pos_area;
+ corb_t* corb;
+ rirb_t* rirb;
+ uint32* stream_positions;
+
+ hda_codec* codecs[HDA_MAX_CODECS + 1];
+ hda_codec* active_codec;
+ uint32 num_codecs;
+
+ hda_stream* streams[HDA_MAX_STREAMS];
+ sem_id buffer_ready_sem;
+
+ uint8 Read8(uint32 reg)
+ {
+ return *(regs + reg);
+ }
+
+ uint16 Read16(uint32 reg)
+ {
+ return *(vuint16*)(regs + reg);
+ }
+
+ uint32 Read32(uint32 reg)
+ {
+ return *(vuint32*)(regs + reg);
+ }
+
+ void Write8(uint32 reg, uint8 value)
+ {
+ *(regs + reg) = value;
+ }
+
+ void Write16(uint32 reg, uint16 value)
+ {
+ *(vuint16*)(regs + reg) = value;
+ }
+
+ void Write32(uint32 reg, uint32 value)
+ {
+ *(vuint32*)(regs + reg) = value;
+ }
+
+ void ReadModifyWrite8(uint32 reg, uint8 mask, uint8 value)
+ {
+ uint8 temp = Read8(reg);
+ temp &= ~mask;
+ temp |= value;
+ Write8(reg, temp);
+ }
+
+ void ReadModifyWrite16(uint32 reg, uint16 mask, uint16 value)
+ {
+ uint16 temp = Read16(reg);
+ temp &= ~mask;
+ temp |= value;
+ Write16(reg, temp);
+ }
+
+ void ReadModifyWrite32(uint32 reg, uint32 mask, uint32 value)
+ {
+ uint32 temp = Read32(reg);
+ temp &= ~mask;
+ temp |= value;
+ Write32(reg, temp);
+ }
+};
+
+/*! This structure describes a single stream of audio data,
+ which is can have multiple channels (for stereo or better).
+*/
+struct hda_stream {
+ uint32 id; /* HDA controller stream # */
+ uint32 offset; /* HDA I/O/B descriptor offset */
+ bool running;
+ spinlock lock; /* Write lock */
+ uint32 type;
+
+ hda_controller* controller;
+
+ uint32 pin_widget; /* PIN Widget ID */
+ uint32 io_widgets[MAX_IO_WIDGETS]; /* Input/Output Converter Widget ID */
+ uint32 num_io_widgets;
+
+ uint32 sample_rate;
+ uint32 sample_format;
+
+ uint32 num_buffers;
+ uint32 num_channels;
+ uint32 buffer_length; /* size of buffer in samples */
+ uint32 buffer_size; /* actual (aligned) size of buffer in bytes */
+ uint32 sample_size;
+ uint8* buffers[STREAM_MAX_BUFFERS];
+ /* Virtual addresses for buffer */
+ phys_addr_t physical_buffers[STREAM_MAX_BUFFERS];
+ /* Physical addresses for buffer */
+
+ volatile bigtime_t real_time;
+ volatile uint64 frames_count;
+ uint32 last_link_frame_position;
+ volatile int32 buffer_cycle;
+
+ uint32 rate, bps; /* Samplerate & bits per sample */
+
+ area_id buffer_area;
+ area_id buffer_descriptors_area;
+ phys_addr_t physical_buffer_descriptors; /* BDL physical address */
+
+ int32 incorrect_position_count;
+ bool use_dma_position;
+
+ uint8 Read8(uint32 reg)
+ {
+ return controller->Read8(HDAC_STREAM_BASE + offset + reg);
+ }
+
+ uint16 Read16(uint32 reg)
+ {
+ return controller->Read16(HDAC_STREAM_BASE + offset + reg);
+ }
+
+ uint32 Read32(uint32 reg)
+ {
+ return controller->Read32(HDAC_STREAM_BASE + offset + reg);
+ }
+
+ void Write8(uint32 reg, uint8 value)
+ {
+ *(controller->regs + HDAC_STREAM_BASE + offset + reg) = value;
+ }
+
+ void Write16(uint32 reg, uint16 value)
+ {
+ *(vuint16*)(controller->regs + HDAC_STREAM_BASE + offset + reg) = value;
+ }
+
+ void Write32(uint32 reg, uint32 value)
+ {
+ *(vuint32*)(controller->regs + HDAC_STREAM_BASE + offset + reg) = value;
+ }
+};
+
+struct hda_widget {
+ uint32 node_id;
+
+ uint32 num_inputs;
+ int32 active_input;
+ uint32 inputs[MAX_INPUTS];
+ uint32 flags;
+
+ hda_widget_type type;
+ uint32 pm;
+
+ struct {
+ uint32 audio;
+ uint32 output_amplifier;
+ uint32 input_amplifier;
+ } capabilities;
+
+ union {
+ struct {
+ uint32 formats;
+ uint32 rates;
+ } io;
+ struct {
+ } mixer;
+ struct {
+ uint32 capabilities;
+ uint32 config;
+ } pin;
+ } d;
+};
+
+struct hda_association {
+ uint32 index;
+ bool enabled;
+ uint32 pin_count;
+ uint32 pins[MAX_ASSOCIATION_PINS];
+};
+#endif
+
+#define WIDGET_FLAG_OUTPUT_PATH 0x01
+#define WIDGET_FLAG_INPUT_PATH 0x02
+#define WIDGET_FLAG_WIDGET_PATH 0x04
+
+/*! This structure describes a single Audio Function Group. An AFG
+ is a group of audio widgets which can be used to configure multiple
+ streams of audio either from the HDA Link to an output device (= playback)
+ or from an input device to the HDA link (= recording).
+*/
+#ifndef __REACTOS__
+struct hda_audio_group {
+ hda_codec* codec;
+ hda_widget widget;
+
+ /* Multi Audio API data */
+ hda_stream* playback_stream;
+ hda_stream* record_stream;
+
+ uint32 widget_start;
+ uint32 widget_count;
+
+ uint32 association_count;
+ uint32 gpio;
+
+ hda_widget* widgets;
+ hda_association associations[MAX_ASSOCIATIONS];
+
+ hda_multi* multi;
+};
+
+/*! This structure describes a single codec module in the
+ HDA compliant device. This is a discrete component, which
+ can contain both Audio Function Groups, Modem Function Groups,
+ and other customized (vendor specific) Function Groups.
+
+ NOTE: ATM, only Audio Function Groups are supported.
+*/
+struct hda_codec {
+ uint16 vendor_id;
+ uint16 product_id;
+ uint8 major;
+ uint8 minor;
+ uint8 revision;
+ uint8 stepping;
+ uint8 addr;
+
+ uint32 quirks;
+
+ sem_id response_sem;
+ uint32 responses[MAX_CODEC_RESPONSES];
+ uint32 response_count;
+
+ sem_id unsol_response_sem;
+ thread_id unsol_response_thread;
+ uint32 unsol_responses[MAX_CODEC_UNSOL_RESPONSES];
+ uint32 unsol_response_read, unsol_response_write;
+
+ hda_audio_group* audio_groups[HDA_MAX_AUDIO_GROUPS];
+ uint32 num_audio_groups;
+
+ struct hda_controller* controller;
+};
+
+
+#define MULTI_CONTROL_FIRSTID 1024
+#define MULTI_CONTROL_MASTERID 0
+#define MULTI_MAX_CONTROLS 128
+#define MULTI_MAX_CHANNELS 128
+
+struct hda_multi_mixer_control {
+ hda_multi *multi;
+ int32 nid;
+ int32 type;
+ bool input;
+ uint32 mute;
+ uint32 gain;
+ uint32 capabilities;
+ int32 index;
+ multi_mix_control mix_control;
+};
+
+
+struct hda_multi {
+ hda_audio_group *group;
+ hda_multi_mixer_control controls[MULTI_MAX_CONTROLS];
+ uint32 control_count;
+
+ multi_channel_info chans[MULTI_MAX_CHANNELS];
+ uint32 output_channel_count;
+ uint32 input_channel_count;
+ uint32 output_bus_channel_count;
+ uint32 input_bus_channel_count;
+ uint32 aux_bus_channel_count;
+};
+
+
+/* driver.c */
+extern device_hooks gDriverHooks;
+extern pci_module_info* gPci;
+extern pci_x86_module_info* gPCIx86Module;
+extern hda_controller gCards[MAX_CARDS];
+extern uint32 gNumCards;
+
+/* hda_codec.c */
+const char* get_widget_location(uint32 location);
+hda_widget* hda_audio_group_get_widget(hda_audio_group* audioGroup, uint32 nodeID);
+
+status_t hda_audio_group_get_widgets(hda_audio_group* audioGroup,
+ hda_stream* stream);
+hda_codec* hda_codec_new(hda_controller* controller, uint32 cad);
+void hda_codec_delete(hda_codec* codec);
+
+/* hda_multi_audio.c */
+status_t multi_audio_control(void* cookie, uint32 op, void* arg, size_t length);
+
+/* hda_controller.c: Basic controller support */
+status_t hda_hw_init(hda_controller* controller);
+void hda_hw_stop(hda_controller* controller);
+void hda_hw_uninit(hda_controller* controller);
+status_t hda_send_verbs(hda_codec* codec, corb_t* verbs, uint32* responses,
+ uint32 count);
+status_t hda_verb_write(hda_codec* codec, uint32 nid, uint32 vid, uint16 payload);
+status_t hda_verb_read(hda_codec* codec, uint32 nid, uint32 vid, uint32 *response);
+
+/* hda_controller.c: Stream support */
+hda_stream* hda_stream_new(hda_audio_group* audioGroup, int type);
+void hda_stream_delete(hda_stream* stream);
+status_t hda_stream_setup_buffers(hda_audio_group* audioGroup,
+ hda_stream* stream, const char* desc);
+status_t hda_stream_start(hda_controller* controller, hda_stream* stream);
+status_t hda_stream_stop(hda_controller* controller, hda_stream* stream);
+#endif
+
+#endif /* _HDA_H_ */
Propchange: trunk/reactos/drivers/wdm/audio/hdaudbus/driver.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/drivers/wdm/audio/hdaudbus/hda_codec_defs.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/hdaudbus…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/hdaudbus/hda_codec_defs.h (added)
+++ trunk/reactos/drivers/wdm/audio/hdaudbus/hda_codec_defs.h [iso-8859-1] Mon Jun 29
17:03:33 2015
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2007-2008, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * Ithamar Adema, ithamar AT unet DOT nl
+ * Axel Dörfler, axeld(a)pinc-software.de
+ */
+#ifndef HDA_CODEC_H
+#define HDA_CODEC_H
+
+enum hda_widget_type {
+ WT_AUDIO_OUTPUT = 0,
+ WT_AUDIO_INPUT = 1,
+ WT_AUDIO_MIXER = 2,
+ WT_AUDIO_SELECTOR = 3,
+ WT_PIN_COMPLEX = 4,
+ WT_POWER = 5,
+ WT_VOLUME_KNOB = 6,
+ WT_BEEP_GENERATOR = 7,
+ WT_VENDOR_DEFINED = 15
+};
+
+enum pin_connectivity_type {
+ PIN_CONN_JACK,
+ PIN_CONN_NONE,
+ PIN_CONN_FIXED,
+ PIN_CONN_BOTH
+};
+
+enum pin_dev_type {
+ PIN_DEV_LINE_OUT = 0,
+ PIN_DEV_SPEAKER,
+ PIN_DEV_HEAD_PHONE_OUT,
+ PIN_DEV_CD,
+ PIN_DEV_SPDIF_OUT,
+ PIN_DEV_DIGITAL_OTHER_OUT,
+ PIN_DEV_MODEM_LINE_SIDE,
+ PIN_DEV_MODEM_HAND_SIDE,
+ PIN_DEV_LINE_IN,
+ PIN_DEV_AUX,
+ PIN_DEV_MIC_IN,
+ PIN_DEV_TELEPHONY,
+ PIN_DEV_SPDIF_IN,
+ PIN_DEV_DIGITAL_OTHER_IN,
+ PIN_DEV_RESERVED,
+ PIN_DEV_OTHER
+};
+
+
+/* Verb Helper Macro */
+#define MAKE_VERB(cad, nid, vid, payload) \
+ (((cad) << 28) | ((nid) << 20) | (vid) | (payload))
+
+/* Verb IDs */
+#define VID_GET_PARAMETER 0xf0000
+#define VID_GET_CONNECTION_SELECT 0xf0100
+#define VID_SET_CONNECTION_SELECT 0x70100
+#define VID_GET_CONNECTION_LIST_ENTRY 0xf0200
+#define VID_GET_PROCESSING_STATE 0xf0300
+#define VID_SET_PROCESSING_STATE 0x70300
+#define VID_GET_COEFFICIENT_INDEX 0xd0000
+#define VID_SET_COEFFICIENT_INDEX 0x50000
+#define VID_GET_PROCESSING_COEFFICIENT 0xc0000
+#define VID_SET_PROCESSING_COEFFICIENT 0x40000
+#define VID_GET_AMPLIFIER_GAIN_MUTE 0xb0000
+#define VID_SET_AMPLIFIER_GAIN_MUTE 0x30000
+#define VID_GET_CONVERTER_FORMAT 0xa0000
+#define VID_SET_CONVERTER_FORMAT 0x20000
+#define VID_GET_CONVERTER_STREAM_CHANNEL 0xf0600
+#define VID_SET_CONVERTER_STREAM_CHANNEL 0x70600
+#define VID_GET_DIGITAL_CONVERTER_CONTROL 0xf0d00
+#define VID_SET_DIGITAL_CONVERTER_CONTROL1 0x70d00
+#define VID_SET_DIGITAL_CONVERTER_CONTROL2 0x70e00
+#define VID_GET_POWER_STATE 0xf0500
+#define VID_SET_POWER_STATE 0x70500
+#define VID_GET_SDI_SELECT 0xf0400
+#define VID_SET_SDI_SELECT 0x70400
+#define VID_GET_PIN_WIDGET_CONTROL 0xf0700
+#define VID_SET_PIN_WIDGET_CONTROL 0x70700
+#define VID_GET_UNSOLRESP 0xF0800
+#define VID_SET_UNSOLRESP 0x70800
+#define VID_GET_PINSENSE 0xF0900
+#define VID_SET_PINSENSE 0x70900
+#define VID_GET_EAPDBTL_EN 0xF0C00
+#define VID_SET_EAPDBTL_EN 0x70C00
+#define VID_GET_VOLUME_KNOB_CONTROL 0xF0F00
+#define VID_SET_VOLUME_KNOB_CONTROL 0x70F00
+#define VID_GET_GPIDATA 0xF1000
+#define VID_SET_GPIDATA 0x71000
+#define VID_GET_GPIWAKE_EN 0xF1100
+#define VID_SET_GPIWAKE_EN 0x71100
+#define VID_GET_GPIUNSOL 0xF1200
+#define VID_SET_GPIUNSOL 0x71200
+#define VID_GET_GPISTICKY 0xF1300
+#define VID_SET_GPISTICKY 0x71300
+#define VID_GET_GPO_DATA 0xF1400
+#define VID_SET_GPO_DATA 0x71400
+#define VID_GET_GPIO_DATA 0xF1500
+#define VID_SET_GPIO_DATA 0x71500
+#define VID_GET_GPIO_EN 0xF1600
+#define VID_SET_GPIO_EN 0x71600
+#define VID_GET_GPIO_DIR 0xF1700
+#define VID_SET_GPIO_DIR 0x71700
+#define VID_GET_GPIOWAKE_EN 0xF1800
+#define VID_SET_GPIOWAKE_EN 0x71800
+#define VID_GET_GPIOUNSOL_EN 0xF1900
+#define VID_SET_GPIOUNSOL_EN 0x71900
+#define VID_GET_GPIOSTICKY 0xF1A00
+#define VID_SET_GPIOSTICKY 0x71A00
+#define VID_GET_BEEPGEN 0xF0A00
+#define VID_SET_BEEPGEN 0x70A00
+#define VID_GET_VOLUME_KNOB 0xf0f00
+#define VID_SET_VOLUME_KNOB 0x70f00
+#define VID_GET_SUBSYSTEMID 0xF2000
+#define VID_SET_SUBSYSTEMID1 0x72000
+#define VID_SET_SUBSYSTEMID2 0x72100
+#define VID_SET_SUBSYSTEMID3 0x72200
+#define VID_SET_SUBSYSTEMID4 0x72300
+#define VID_GET_CONFIGURATION_DEFAULT 0xf1c00
+#define VID_SET_CONFIGURATION_DEFAULT1 0x71c00
+#define VID_SET_CONFIGURATION_DEFAULT2 0x71d00
+#define VID_SET_CONFIGURATION_DEFAULT3 0x71e00
+#define VID_SET_CONFIGURATION_DEFAULT4 0x71f00
+#define VID_GET_STRIPE_CONTROL 0xf2400
+#define VID_SET_STRIPE_CONTROL 0x72000
+#define VID_FUNCTION_RESET 0x7ff00
+/* later specification updates */
+#define VID_GET_EDID_LIKE_DATA 0xf2f00
+#define VID_GET_CONVERTER_CHANNEL_COUNT 0xf2d00
+#define VID_SET_CONVERTER_CHANNEL_COUNT 0x72d00
+#define VID_GET_DATA_ISLAND_PACKET_SIZE 0xf2e00
+#define VID_GET_DATA_ISLAND_PACKET_INDEX 0xf3000
+#define VID_SET_DATA_ISLAND_PACKET_INDEX 0x73000
+#define VID_GET_DATA_ISLAND_PACKET_DATA 0xf3100
+#define VID_SET_DATA_ISLAND_PACKET_DATA 0x73100
+#define VID_GET_DATA_ISLAND_PACKET_XMITCTRL 0xf3200
+#define VID_SET_DATA_ISLAND_PACKET_XMITCTRL 0x73200
+#define VID_GET_CONTENT_PROTECTION_CONTROL 0xf3300
+#define VID_SET_CONTENT_PROTECTION_CONTROL 0x73300
+#define VID_GET_ASP_CHANNEL_MAPPING 0xf3400
+#define VID_SET_ASP_CHANNEL_MAPPING 0x73400
+
+/* Parameter IDs */
+#define PID_VENDOR_ID 0x00
+#define PID_REVISION_ID 0x02
+#define PID_SUB_NODE_COUNT 0x04
+#define PID_FUNCTION_GROUP_TYPE 0x05
+#define PID_AUDIO_GROUP_CAP 0x08
+#define PID_AUDIO_WIDGET_CAP 0x09
+#define PID_PCM_SUPPORT 0x0a
+#define PID_STREAM_SUPPORT 0x0b
+#define PID_PIN_CAP 0x0c
+#define PID_INPUT_AMPLIFIER_CAP 0x0d
+#define PID_CONNECTION_LIST_LENGTH 0x0e
+#define PID_POWERSTATE_SUPPORT 0x0f
+#define PID_PROCESSING_CAP 0x10
+#define PID_GPIO_COUNT 0x11
+#define PID_OUTPUT_AMPLIFIER_CAP 0x12
+#define PID_VOLUME_KNOB_CAP 0x13
+
+/* Subordinate node count */
+#define SUB_NODE_COUNT_TOTAL_MASK 0x000000ff
+#define SUB_NODE_COUNT_TOTAL_SHIFT 0
+#define SUB_NODE_COUNT_START_MASK 0x00ff0000
+#define SUB_NODE_COUNT_START_SHIFT 16
+
+#define SUB_NODE_COUNT_TOTAL(c) ((c & SUB_NODE_COUNT_TOTAL_MASK) \
+ >> SUB_NODE_COUNT_TOTAL_SHIFT)
+#define SUB_NODE_COUNT_START(c) ((c & SUB_NODE_COUNT_START_MASK) \
+ >> SUB_NODE_COUNT_START_SHIFT)
+
+/* Function group type */
+#define FUNCTION_GROUP_NODETYPE_MASK 0x000000ff
+#define FUNCTION_GROUP_UNSOLCAPABLE_MASK 0x00000100
+
+#define FUNCTION_GROUP_NODETYPE_AUDIO 0x00000001
+#define FUNCTION_GROUP_NODETYPE_MODEM 0x00000002
+
+/* Audio Function group capabilities */
+#define AUDIO_GROUP_CAP_OUTPUT_DELAY_MASK 0x0000000f
+#define AUDIO_GROUP_CAP_OUTPUT_DELAY_SHIFT 0
+#define AUDIO_GROUP_CAP_INPUT_DELAY_MASK 0x00000f00
+#define AUDIO_GROUP_CAP_INPUT_DELAY_SHIFT 8
+#define AUDIO_GROUP_CAP_BEEPGEN_MASK 0x00010000
+#define AUDIO_GROUP_CAP_BEEPGEN_SHIFT 16
+
+#define AUDIO_GROUP_CAP_OUTPUT_DELAY(c) ((c & AUDIO_GROUP_CAP_OUTPUT_DELAY_MASK) \
+ >> AUDIO_GROUP_CAP_OUTPUT_DELAY_SHIFT)
+#define AUDIO_GROUP_CAP_INPUT_DELAY(c) ((c & AUDIO_GROUP_CAP_INPUT_DELAY_MASK) \
+ >> AUDIO_GROUP_CAP_INPUT_DELAY_SHIFT)
+#define AUDIO_GROUP_CAP_BEEPGEN(c) ((c & AUDIO_GROUP_CAP_BEEPGEN_MASK) \
+ >> AUDIO_GROUP_CAP_BEEPGEN_SHIFT)
+
+
+/* Audio widget capabilities */
+#define AUDIO_CAP_CHANNEL_COUNT_MASK 0x0000e000
+#define AUDIO_CAP_CHANNEL_COUNT_SHIFT 13
+#define AUDIO_CAP_DELAY_MASK 0x000f0000
+#define AUDIO_CAP_DELAY_SHIFT 16
+#define AUDIO_CAP_TYPE_MASK 0x00f00000
+#define AUDIO_CAP_TYPE_SHIFT 20
+
+#define AUDIO_CAP_STEREO (1L << 0)
+#define AUDIO_CAP_INPUT_AMPLIFIER (1L << 1)
+#define AUDIO_CAP_OUTPUT_AMPLIFIER (1L << 2)
+#define AUDIO_CAP_AMPLIFIER_OVERRIDE (1L << 3)
+#define AUDIO_CAP_FORMAT_OVERRIDE (1L << 4)
+#define AUDIO_CAP_STRIPE (1L << 5)
+#define AUDIO_CAP_PROCESSING_CONTROLS (1L << 6)
+#define AUDIO_CAP_UNSOLICITED_RESPONSES (1L << 7)
+#define AUDIO_CAP_CONNECTION_LIST (1L << 8)
+#define AUDIO_CAP_DIGITAL (1L << 9)
+#define AUDIO_CAP_POWER_CONTROL (1L << 10)
+#define AUDIO_CAP_LEFT_RIGHT_SWAP (1L << 11)
+#define AUDIO_CAP_CP_CAPS (1L << 12)
+
+#define AUDIO_CAP_CHANNEL_COUNT(c) \
+ (((c & AUDIO_CAP_CHANNEL_COUNT_MASK) >> (AUDIO_CAP_CHANNEL_COUNT_SHIFT - 1))
\
+ | AUDIO_CAP_STEREO)
+
+/* Amplifier capabilities */
+#define AMP_CAP_MUTE 0xf0000000
+#define AMP_CAP_STEP_SIZE_MASK 0x007f0000
+#define AMP_CAP_STEP_SIZE_SHIFT 16
+#define AMP_CAP_NUM_STEPS_MASK 0x00007f00
+#define AMP_CAP_NUM_STEPS_SHIFT 8
+#define AMP_CAP_OFFSET_MASK 0x0000007f
+
+#define AMP_CAP_STEP_SIZE(c) ((((c & AMP_CAP_STEP_SIZE_MASK) \
+ >> AMP_CAP_STEP_SIZE_SHIFT) + 1) / 4.0)
+#define AMP_CAP_NUM_STEPS(c) ((c & AMP_CAP_NUM_STEPS_MASK) \
+ >> AMP_CAP_NUM_STEPS_SHIFT)
+#define AMP_CAP_OFFSET(c) (c & AMP_CAP_OFFSET_MASK)
+
+/* Pin capabilities */
+#define PIN_CAP_IMP_SENSE (1L << 0)
+#define PIN_CAP_TRIGGER_REQ (1L << 1)
+#define PIN_CAP_PRES_DETECT (1L << 2)
+#define PIN_CAP_HP_DRIVE (1L << 3)
+#define PIN_CAP_OUTPUT (1L << 4)
+#define PIN_CAP_INPUT (1L << 5)
+#define PIN_CAP_BALANCE (1L << 6)
+#define PIN_CAP_HDMI (1L << 7)
+#define PIN_CAP_VREF_CTRL_HIZ (1L << 8)
+#define PIN_CAP_VREF_CTRL_50 (1L << 9)
+#define PIN_CAP_VREF_CTRL_GROUND (1L << 10)
+#define PIN_CAP_VREF_CTRL_80 (1L << 12)
+#define PIN_CAP_VREF_CTRL_100 (1L << 13)
+#define PIN_CAP_EAPD_CAP (1L << 16)
+#define PIN_CAP_DP (1L << 24)
+#define PIN_CAP_HBR (1L << 27)
+
+#define PIN_CAP_IS_PRES_DETECT_CAP(c) ((c & PIN_CAP_PRES_DETECT) != 0)
+#define PIN_CAP_IS_OUTPUT(c) ((c & PIN_CAP_OUTPUT) != 0)
+#define PIN_CAP_IS_INPUT(c) ((c & PIN_CAP_INPUT) != 0)
+#define PIN_CAP_IS_BALANCE(c) ((c & PIN_CAP_BALANCE) != 0)
+#define PIN_CAP_IS_HDMI(c) ((c & PIN_CAP_HDMI) != 0)
+#define PIN_CAP_IS_VREF_CTRL_50_CAP(c) ((c & PIN_CAP_VREF_CTRL_50) != 0)
+#define PIN_CAP_IS_VREF_CTRL_80_CAP(c) ((c & PIN_CAP_VREF_CTRL_80) != 0)
+#define PIN_CAP_IS_VREF_CTRL_100_CAP(c) ((c & PIN_CAP_VREF_CTRL_100) != 0)
+#define PIN_CAP_IS_EAPD_CAP(c) ((c & PIN_CAP_EAPD_CAP) != 0)
+#define PIN_CAP_IS_DP(c) ((c & PIN_CAP_DP) != 0)
+#define PIN_CAP_IS_HBR(c) ((c & PIN_CAP_HBR) != 0)
+
+/* PCM support */
+#define PCM_8_BIT (1L << 16)
+#define PCM_16_BIT (1L << 17)
+#define PCM_20_BIT (1L << 18)
+#define PCM_24_BIT (1L << 19)
+#define PCM_32_BIT (1L << 20)
+
+/* stream support */
+#define STREAM_AC3 0x00000004
+#define STREAM_FLOAT 0x00000002
+#define STREAM_PCM 0x00000001
+
+/* Amplifier Gain/Mute */
+#define AMP_GET_OUTPUT (1L << 15)
+#define AMP_GET_INPUT (0L << 15)
+#define AMP_GET_LEFT_CHANNEL (1L << 13)
+#define AMP_GET_RIGHT_CHANNEL (0L << 13)
+#define AMP_GET_INPUT_INDEX_MASK 0x0000000f
+#define AMP_GET_INPUT_INDEX_SHIFT 0
+
+#define AMP_GET_INPUT_INDEX(x) ((x << AMP_GET_INPUT_INDEX_SHIFT) &
AMP_GET_INPUT_INDEX_MASK)
+
+#define AMP_SET_OUTPUT (1L << 15)
+#define AMP_SET_INPUT (1L << 14)
+#define AMP_SET_LEFT_CHANNEL (1L << 13)
+#define AMP_SET_RIGHT_CHANNEL (1L << 12)
+#define AMP_SET_INPUT_INDEX_MASK 0x00000f00
+#define AMP_SET_INPUT_INDEX_SHIFT 8
+
+#define AMP_SET_INPUT_INDEX(x) ((x << AMP_SET_INPUT_INDEX_SHIFT) &
AMP_SET_INPUT_INDEX_MASK)
+
+#define AMP_GAIN_MASK 0x0000007f
+#define AMP_MUTE (1L << 7)
+
+/* Pin Widget Control */
+#define PIN_ENABLE_HEAD_PHONE (1L << 7)
+#define PIN_ENABLE_OUTPUT (1L << 6)
+#define PIN_ENABLE_INPUT (1L << 5)
+#define PIN_ENABLE_VREF_HIZ 0
+#define PIN_ENABLE_VREF_50 1
+#define PIN_ENABLE_VREF_GROUND 2
+#define PIN_ENABLE_VREF_80 4
+#define PIN_ENABLE_VREF_100 5
+
+/* Unsolicited Response */
+#define UNSOLRESP_ENABLE (1L << 7)
+#define UNSOLRESP_TAG_MASK 0x0000003f
+#define UNSOLRESP_TAG_SHIFT 0
+
+/* Pin sense */
+#define PIN_SENSE_PRESENCE_DETECT (1L << 31)
+#define PIN_SENSE_ELD_VALID (1L << 30)
+#define PIN_SENSE_IMPEDANCE_MASK 0x7fffffff
+#define PIN_SENSE_IMPEDANCE_SHIFT 0
+
+#define PIN_SENSE_IMPEDANCE_INVALID 0x7fffffff
+#define PIN_SENSE_SET_CHANNEL_LEFT 0
+#define PIN_SENSE_SET_CHANNEL_RIGHT 1
+
+/* Supported power states */
+#define POWER_STATE_D0 (1L << 0)
+#define POWER_STATE_D1 (1L << 1)
+#define POWER_STATE_D2 (1L << 2)
+#define POWER_STATE_D3 (1L << 3)
+#define POWER_STATE_D3COLD (1L << 4)
+#define POWER_STATE_S3D3COLD (1L << 29)
+#define POWER_STATE_CLKSTOP (1L << 30)
+#define POWER_STATE_EPSS (1L << 31)
+
+/* Configuration default */
+#define CONF_DEFAULT_SEQUENCE_MASK 0x0000000f
+#define CONF_DEFAULT_SEQUENCE_SHIFT 0
+#define CONF_DEFAULT_ASSOCIATION_MASK 0x000000f0
+#define CONF_DEFAULT_ASSOCIATION_SHIFT 4
+#define CONF_DEFAULT_MISC_MASK 0x00000f00
+#define CONF_DEFAULT_MISC_SHIFT 8
+#define CONF_DEFAULT_COLOR_MASK 0x0000f000
+#define CONF_DEFAULT_COLOR_SHIFT 12
+#define CONF_DEFAULT_CONNTYPE_MASK 0x000f0000
+#define CONF_DEFAULT_CONNTYPE_SHIFT 16
+#define CONF_DEFAULT_DEVICE_MASK 0x00f00000
+#define CONF_DEFAULT_DEVICE_SHIFT 20
+#define CONF_DEFAULT_LOCATION_MASK 0x3f000000
+#define CONF_DEFAULT_LOCATION_SHIFT 24
+#define CONF_DEFAULT_CONNECTIVITY_MASK 0xc0000000
+#define CONF_DEFAULT_CONNECTIVITY_SHIFT 30
+
+#define CONF_DEFAULT_SEQUENCE(c) ((c & CONF_DEFAULT_SEQUENCE_MASK) >>
CONF_DEFAULT_SEQUENCE_SHIFT)
+#define CONF_DEFAULT_ASSOCIATION(c) ((c & CONF_DEFAULT_ASSOCIATION_MASK) >>
CONF_DEFAULT_ASSOCIATION_SHIFT)
+#define CONF_DEFAULT_MISC(c) ((c & CONF_DEFAULT_MISC_MASK) >>
CONF_DEFAULT_MISC_SHIFT)
+#define CONF_DEFAULT_COLOR(c) ((c & CONF_DEFAULT_COLOR_MASK) >>
CONF_DEFAULT_COLOR_SHIFT)
+#define CONF_DEFAULT_CONNTYPE(c) ((c & CONF_DEFAULT_CONNTYPE_MASK) >>
CONF_DEFAULT_CONNTYPE_SHIFT)
+#define CONF_DEFAULT_DEVICE(c) ((c & CONF_DEFAULT_DEVICE_MASK) >>
CONF_DEFAULT_DEVICE_SHIFT)
+#define CONF_DEFAULT_LOCATION(c) ((c & CONF_DEFAULT_LOCATION_MASK) >>
CONF_DEFAULT_LOCATION_SHIFT)
+#define CONF_DEFAULT_CONNECTIVITY(c) ((c & CONF_DEFAULT_CONNECTIVITY_MASK) >>
CONF_DEFAULT_CONNECTIVITY_SHIFT)
+
+/* EAPD/BTL enable */
+#define EAPDBTL_ENABLE_BTL 0x1
+#define EAPDBTL_ENABLE_EAPD 0x2
+#define EAPDBTL_ENABLE_LRSWAP 0x4
+
+/* GP I/O count */
+#define GPIO_COUNT_NUM_GPIO_MASK 0x000000ff
+#define GPIO_COUNT_NUM_GPIO_SHIFT 0
+#define GPIO_COUNT_NUM_GPO_MASK 0x0000ff00
+#define GPIO_COUNT_NUM_GPO_SHIFT 8
+#define GPIO_COUNT_NUM_GPI_MASK 0x00ff0000
+#define GPIO_COUNT_NUM_GPI_SHIFT 16
+#define GPIO_COUNT_GPIUNSOL_MASK 0x40000000
+#define GPIO_COUNT_GPIUNSOL_SHIFT 30
+#define GPIO_COUNT_GPIWAKE_MASK 0x80000000
+#define GPIO_COUNT_GPIWAKE_SHIFT 31
+
+#define GPIO_COUNT_NUM_GPIO(c) ((c & GPIO_COUNT_NUM_GPIO_MASK) >>
GPIO_COUNT_NUM_GPIO_SHIFT)
+#define GPIO_COUNT_NUM_GPO(c) ((c & GPIO_COUNT_NUM_GPO_MASK) >>
GPIO_COUNT_NUM_GPO_SHIFT)
+#define GPIO_COUNT_NUM_GPI(c) ((c & GPIO_COUNT_NUM_GPI_MASK) >>
GPIO_COUNT_NUM_GPI_SHIFT)
+#define GPIO_COUNT_GPIUNSOL(c) ((c & GPIO_COUNT_GPIUNSOL_MASK) >>
GPIO_COUNT_GPIUNSOL_SHIFT)
+#define GPIO_COUNT_GPIWAKE(c) ((c & GPIO_COUNT_GPIWAKE_MASK) >>
GPIO_COUNT_GPIWAKE_SHIFT)
+
+
+#endif /* HDA_CODEC_H */
Propchange: trunk/reactos/drivers/wdm/audio/hdaudbus/hda_codec_defs.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/drivers/wdm/audio/hdaudbus/hda_controller_defs.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/hdaudbus…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/hdaudbus/hda_controller_defs.h (added)
+++ trunk/reactos/drivers/wdm/audio/hdaudbus/hda_controller_defs.h [iso-8859-1] Mon Jun 29
17:03:33 2015
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2007-2012, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * Ithamar Adema, ithamar AT unet DOT nl
+ * Axel Dörfler, axeld(a)pinc-software.de
+ */
+#ifndef HDAC_REGS_H
+#define HDAC_REGS_H
+
+#ifndef __REACTOS__
+#include <SupportDefs.h>
+#endif
+
+/* Controller register definitions */
+#define HDAC_GLOBAL_CAP 0x00 // 16bits, GCAP
+#define GLOBAL_CAP_OUTPUT_STREAMS(cap) (((cap) >> 12) & 15)
+#define GLOBAL_CAP_INPUT_STREAMS(cap) (((cap) >> 8) & 15)
+#define GLOBAL_CAP_BIDIR_STREAMS(cap) (((cap) >> 3) & 15)
+#define GLOBAL_CAP_NUM_SDO(cap) ((((cap) >> 1) & 3) ? (cap & 6) : 1)
+#define GLOBAL_CAP_64BIT(cap) (((cap) & 1) != 0)
+
+#define HDAC_VERSION_MINOR 0x02 // 8bits, VMIN
+#define HDAC_VERSION_MAJOR 0x03 // 8bits, VMAJ
+
+#define HDAC_GLOBAL_CONTROL 0x08 // 32bits, GCTL
+#define GLOBAL_CONTROL_UNSOLICITED (1 << 8)
+ // accept unsolicited responses
+#define GLOBAL_CONTROL_FLUSH (1 << 1)
+#define GLOBAL_CONTROL_RESET (1 << 0)
+
+#define HDAC_WAKE_ENABLE 0x0c // 16bits, WAKEEN
+#define HDAC_WAKE_ENABLE_MASK 0x7fff
+#define HDAC_STATE_STATUS 0x0e // 16bits, STATESTS
+
+#define HDAC_INTR_CONTROL 0x20 // 32bits, INTCTL
+#define INTR_CONTROL_GLOBAL_ENABLE (1U << 31)
+#define INTR_CONTROL_CONTROLLER_ENABLE (1 << 30)
+
+#define HDAC_INTR_STATUS 0x24 // 32bits, INTSTS
+#define INTR_STATUS_GLOBAL (1U << 31)
+#define INTR_STATUS_CONTROLLER (1 << 30)
+#define INTR_STATUS_STREAM_MASK 0x3fffffff
+
+#define HDAC_CORB_BASE_LOWER 0x40 // 32bits, CORBLBASE
+#define HDAC_CORB_BASE_UPPER 0x44 // 32bits, CORBUBASE
+#define HDAC_CORB_WRITE_POS 0x48 // 16bits, CORBWP
+#define HDAC_CORB_WRITE_POS_MASK 0xff
+
+#define HDAC_CORB_READ_POS 0x4a // 16bits, CORBRP
+#define CORB_READ_POS_RESET (1 << 15)
+
+#define HDAC_CORB_CONTROL 0x4c // 8bits, CORBCTL
+#define HDAC_CORB_CONTROL_MASK 0x3
+#define CORB_CONTROL_RUN (1 << 1)
+#define CORB_CONTROL_MEMORY_ERROR_INTR (1 << 0)
+
+#define HDAC_CORB_STATUS 0x4d // 8bits, CORBSTS
+#define CORB_STATUS_MEMORY_ERROR (1 << 0)
+
+#define HDAC_CORB_SIZE 0x4e // 8bits, CORBSIZE
+#define HDAC_CORB_SIZE_MASK 0x3
+#define CORB_SIZE_CAP_2_ENTRIES (1 << 4)
+#define CORB_SIZE_CAP_16_ENTRIES (1 << 5)
+#define CORB_SIZE_CAP_256_ENTRIES (1 << 6)
+#define CORB_SIZE_2_ENTRIES 0x00 // 8 byte
+#define CORB_SIZE_16_ENTRIES 0x01 // 64 byte
+#define CORB_SIZE_256_ENTRIES 0x02 // 1024 byte
+
+#define HDAC_RIRB_BASE_LOWER 0x50 // 32bits, RIRBLBASE
+#define HDAC_RIRB_BASE_UPPER 0x54 // 32bits, RIRBUBASE
+
+#define HDAC_RIRB_WRITE_POS 0x58 // 16bits, RIRBWP
+#define RIRB_WRITE_POS_RESET (1 << 15)
+
+#define HDAC_RESPONSE_INTR_COUNT 0x5a // 16bits, RINTCNT
+#define HDAC_RESPONSE_INTR_COUNT_MASK 0xff
+
+#define HDAC_RIRB_CONTROL 0x5c // 8bits, RIRBCTL
+#define HDAC_RIRB_CONTROL_MASK 0x7
+#define RIRB_CONTROL_OVERRUN_INTR (1 << 2)
+#define RIRB_CONTROL_DMA_ENABLE (1 << 1)
+#define RIRB_CONTROL_RESPONSE_INTR (1 << 0)
+
+#define HDAC_RIRB_STATUS 0x5d // 8bits, RIRBSTS
+#define RIRB_STATUS_OVERRUN (1 << 2)
+#define RIRB_STATUS_RESPONSE (1 << 0)
+
+#define HDAC_RIRB_SIZE 0x5e // 8bits, RIRBSIZE
+#define HDAC_RIRB_SIZE_MASK 0x3
+#define RIRB_SIZE_CAP_2_ENTRIES (1 << 4)
+#define RIRB_SIZE_CAP_16_ENTRIES (1 << 5)
+#define RIRB_SIZE_CAP_256_ENTRIES (1 << 6)
+#define RIRB_SIZE_2_ENTRIES 0x00
+#define RIRB_SIZE_16_ENTRIES 0x01
+#define RIRB_SIZE_256_ENTRIES 0x02
+
+#define HDAC_DMA_POSITION_BASE_LOWER 0x70 // 32bits, DPLBASE
+#define HDAC_DMA_POSITION_BASE_UPPER 0x74 // 32bits, DPUBASE
+#define DMA_POSITION_ENABLED 1
+
+/* Stream Descriptor Registers */
+#define HDAC_STREAM_BASE 0x80
+#define HDAC_STREAM_SIZE 0x20
+
+#define HDAC_STREAM_CONTROL0 0x00 // 8bits, CTL0
+#define CONTROL0_RESET (1 << 0)
+#define CONTROL0_RUN (1 << 1)
+#define CONTROL0_BUFFER_COMPLETED_INTR (1 << 2)
+#define CONTROL0_FIFO_ERROR_INTR (1 << 3)
+#define CONTROL0_DESCRIPTOR_ERROR_INTR (1 << 4)
+#define HDAC_STREAM_CONTROL1 0x01 // 8bits, CTL1
+#define HDAC_STREAM_CONTROL2 0x02 // 8bits, CTL2
+#define CONTROL2_STREAM_MASK 0xf0
+#define CONTROL2_STREAM_SHIFT 4
+#define CONTROL2_BIDIR (1 << 3)
+#define CONTROL2_TRAFFIC_PRIORITY (1 << 2)
+#define CONTROL2_STRIPE_SDO_MASK 0x03
+#define HDAC_STREAM_STATUS 0x03 // 8bits, STS
+#define STATUS_BUFFER_COMPLETED (1 << 2)
+#define STATUS_FIFO_ERROR (1 << 3)
+#define STATUS_DESCRIPTOR_ERROR (1 << 4)
+#define STATUS_FIFO_READY (1 << 5)
+#define HDAC_STREAM_POSITION 0x04 // 32bits, LPIB
+#define HDAC_STREAM_BUFFER_SIZE 0x08 // 32bits, CBL
+#define HDAC_STREAM_LAST_VALID 0x0c // 16bits, LVI
+#define HDAC_STREAM_FIFO_SIZE 0x10 // 16bits, FIFOS
+#define HDAC_STREAM_FORMAT 0x12 // 16bits, FMT
+#define FORMAT_8BIT (0 << 4)
+#define FORMAT_16BIT (1 << 4)
+#define FORMAT_20BIT (2 << 4)
+#define FORMAT_24BIT (3 << 4)
+#define FORMAT_32BIT (4 << 4)
+#define FORMAT_44_1_BASE_RATE (1 << 14)
+#define FORMAT_MULTIPLY_RATE_SHIFT 11
+#define FORMAT_DIVIDE_RATE_SHIFT 8
+#define HDAC_STREAM_BUFFERS_BASE_LOWER 0x18 // 32bits, BDPL
+#define HDAC_STREAM_BUFFERS_BASE_UPPER 0x1c // 32bits, BDPU
+
+/* PCI space register definitions */
+#define PCI_HDA_TCSEL 0x44
+#define PCI_HDA_TCSEL_MASK 0xf8
+
+#define ATI_HDA_MISC_CNTR2 0x42
+#define ATI_HDA_MISC_CNTR2_MASK 0xf8
+#define ATI_HDA_ENABLE_SNOOP 0x02
+#define NVIDIA_HDA_OSTRM_COH 0x4c
+#define NVIDIA_HDA_ISTRM_COH 0x4d
+#define NVIDIA_HDA_ENABLE_COHBIT 0x01
+#define NVIDIA_HDA_TRANSREG 0x4e
+#define NVIDIA_HDA_TRANSREG_MASK 0xf0
+#define NVIDIA_HDA_ENABLE_COHBITS 0x0f
+#define INTEL_SCH_HDA_DEVC 0x78
+#define INTEL_SCH_HDA_DEVC_SNOOP 0x800
+
+
+#ifndef __REACTOS__
+typedef uint32 corb_t;
+typedef struct {
+ uint32 response;
+ uint32 flags;
+} rirb_t;
+#endif
+
+#define RESPONSE_FLAGS_CODEC_MASK 0x0000000f
+#define RESPONSE_FLAGS_UNSOLICITED (1 << 4)
+
+#ifndef __REACTOS__
+typedef struct {
+ uint32 lower;
+ uint32 upper;
+ uint32 length;
+ uint32 ioc;
+} bdl_entry_t;
+#endif
+
+#endif /* HDAC_REGS_H */
Propchange: trunk/reactos/drivers/wdm/audio/hdaudbus/hda_controller_defs.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/drivers/wdm/audio/hdaudbus/hdaudbus.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/hdaudbus…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/hdaudbus/hdaudbus.cpp (added)
+++ trunk/reactos/drivers/wdm/audio/hdaudbus/hdaudbus.cpp [iso-8859-1] Mon Jun 29 17:03:33
2015
@@ -0,0 +1,1051 @@
+/*
+* COPYRIGHT: See COPYING in the top level directory
+* PROJECT: ReactOS Kernel Streaming
+* FILE: drivers/wdm/audio/hdaudbus/hdaudbus.cpp
+* PURPOSE: HDA Driver Entry
+* PROGRAMMER: Johannes Anderwald
+*/
+
+
+#include "hdaudbus.h"
+
+
+PVOID
+AllocateItem(
+IN POOL_TYPE PoolType,
+IN SIZE_T NumberOfBytes)
+{
+ PVOID Item = ExAllocatePoolWithTag(PoolType, NumberOfBytes, TAG_HDA);
+ if (!Item)
+ return Item;
+
+ RtlZeroMemory(Item, NumberOfBytes);
+ return Item;
+}
+
+VOID
+FreeItem(
+ IN PVOID Item)
+{
+ ExFreePool(Item);
+}
+
+BOOLEAN
+NTAPI
+HDA_InterruptService(
+IN PKINTERRUPT Interrupt,
+IN PVOID ServiceContext)
+{
+ PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
+ ULONG InterruptStatus, Response, ResponseFlags, Cad;
+ UCHAR RirbStatus, CorbStatus;
+ USHORT WritePos;
+ PHDA_CODEC_ENTRY Codec;
+
+ /* get device extension */
+ DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)ServiceContext;
+
+ // Check if this interrupt is ours
+ InterruptStatus = READ_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase +
HDAC_INTR_STATUS));
+
+ DPRINT1("HDA_InterruptService %lx\n", InterruptStatus);
+ if ((InterruptStatus & INTR_STATUS_GLOBAL) == 0)
+ return FALSE;
+
+ // Controller or stream related?
+ if (InterruptStatus & INTR_STATUS_CONTROLLER) {
+ RirbStatus = READ_REGISTER_UCHAR(DeviceExtension->RegBase +
HDAC_RIRB_STATUS);
+ CorbStatus = READ_REGISTER_UCHAR(DeviceExtension->RegBase +
HDAC_CORB_STATUS);
+
+ // Check for incoming responses
+ if (RirbStatus) {
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_RIRB_STATUS,
RirbStatus);
+
+ if ((RirbStatus & RIRB_STATUS_RESPONSE) != 0) {
+ WritePos = (READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_RIRB_WRITE_POS)) + 1) % DeviceExtension->RirbLength;
+
+ for (; DeviceExtension->RirbReadPos != WritePos;
DeviceExtension->RirbReadPos = (DeviceExtension->RirbReadPos + 1) %
DeviceExtension->RirbLength)
+ {
+
+ Response =
DeviceExtension->RirbBase[DeviceExtension->RirbReadPos].response;
+ ResponseFlags =
DeviceExtension->RirbBase[DeviceExtension->RirbReadPos].flags;
+ Cad = ResponseFlags & RESPONSE_FLAGS_CODEC_MASK;
+ DPRINT1("Response %lx ResponseFlags %lx Cad %lx\n",
Response, ResponseFlags, Cad);
+
+ /* get codec */
+ Codec = DeviceExtension->Codecs[Cad];
+ if (Codec == NULL)
+ {
+ DPRINT1("hda: response for unknown codec %x Response %x
ResponseFlags %x\n", Cad, Response, ResponseFlags);
+ continue;
+ }
+
+ /* check response count */
+ if (Codec->ResponseCount >= MAX_CODEC_RESPONSES)
+ {
+ DPRINT1("too many responses for codec %x Response %x
ResponseFlags %x\n", Cad, Response, ResponseFlags);
+ continue;
+ }
+
+ // FIXME handle unsolicited responses
+ ASSERT((ResponseFlags & RESPONSE_FLAGS_UNSOLICITED) == 0);
+
+ /* store response */
+ Codec->Responses[Codec->ResponseCount] = Response;
+ Codec->ResponseCount++;
+ }
+ }
+
+ if ((RirbStatus & RIRB_STATUS_OVERRUN) != 0)
+ DPRINT1("hda: RIRB Overflow\n");
+ }
+
+ // Check for sending errors
+ if (CorbStatus) {
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_CORB_STATUS,
CorbStatus);
+
+ if ((CorbStatus & CORB_STATUS_MEMORY_ERROR) != 0)
+ DPRINT1("hda: CORB Memory Error!\n");
+ }
+ }
+#if 0
+ if ((intrStatus & INTR_STATUS_STREAM_MASK) != 0) {
+ for (uint32 index = 0; index < HDA_MAX_STREAMS; index++) {
+ if ((intrStatus & (1 << index)) != 0) {
+ if (controller->streams[index]) {
+ if (stream_handle_interrupt(controller,
+ controller->streams[index], index)) {
+ handled = B_INVOKE_SCHEDULER;
+ }
+ }
+ else {
+ dprintf("hda: Stream interrupt for unconfigured stream "
+ "%ld!\n", index);
+ }
+ }
+ }
+ }
+#endif
+ return TRUE;
+}
+
+VOID
+HDA_SendVerbs(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PHDA_CODEC_ENTRY Codec,
+ IN PULONG Verbs,
+ OUT PULONG Responses,
+ IN ULONG Count)
+{
+ PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
+ ULONG Sent = 0, ReadPosition, WritePosition, Queued;
+
+ /* get device extension */
+ DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* reset response count */
+ Codec->ResponseCount = 0;
+
+ while (Sent < Count) {
+ ReadPosition = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_CORB_READ_POS));
+
+ Queued = 0;
+
+ while (Sent < Count) {
+ WritePosition = (DeviceExtension->CorbWritePos + 1) %
DeviceExtension->CorbLength;
+
+ if (WritePosition == ReadPosition) {
+ // There is no space left in the ring buffer; execute the
+ // queued commands and wait until
+ break;
+ }
+
+ DeviceExtension->CorbBase[WritePosition] = Verbs[Sent++];
+ DeviceExtension->CorbWritePos = WritePosition;
+
+ // FIXME HACK
+ // do proper synchronization
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_CORB_WRITE_POS), DeviceExtension->CorbWritePos);
+ KeStallExecutionProcessor(30);
+ Queued++;
+ }
+
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_CORB_WRITE_POS), DeviceExtension->CorbWritePos);
+ }
+
+ if (Responses != NULL) {
+ memcpy(Responses, Codec->Responses, Codec->ResponseCount * sizeof(ULONG));
+ }
+}
+
+NTSTATUS
+HDA_InitCodec(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG codecAddress)
+{
+ PHDA_CODEC_ENTRY Entry;
+ ULONG verbs[3];
+ PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
+ CODEC_RESPONSE Response;
+ ULONG NodeId, GroupType;
+ NTSTATUS Status;
+ PHDA_CODEC_AUDIO_GROUP AudioGroup;
+ PHDA_PDO_DEVICE_EXTENSION ChildDeviceExtension;
+
+ /* lets allocate the entry */
+ Entry = (PHDA_CODEC_ENTRY)AllocateItem(NonPagedPool, sizeof(HDA_CODEC_ENTRY));
+ if (!Entry)
+ {
+ DPRINT1("hda: failed to allocate memory");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* init codec */
+ Entry->Addr = codecAddress;
+
+ /* get device extension */
+ DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* store codec */
+ DeviceExtension->Codecs[codecAddress] = Entry;
+
+ verbs[0] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_VENDOR_ID);
+ verbs[1] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_REVISION_ID);
+ verbs[2] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_SUB_NODE_COUNT);
+
+ /* get basic info */
+ HDA_SendVerbs(DeviceObject, Entry, verbs, (PULONG)&Response, 3);
+
+ /* store codec details */
+ Entry->Major = Response.major;
+ Entry->Minor = Response.minor;
+ Entry->ProductId = Response.device;
+ Entry->Revision = Response.revision;
+ Entry->Stepping = Response.stepping;
+ Entry->VendorId = Response.vendor;
+
+ DPRINT1("hda Codec %ld Vendor: %04lx Product: %04lx, Revision: %lu.%lu.%lu.%lu
NodeStart %u NodeCount %u \n", codecAddress, Response.vendor,
+ Response.device, Response.major, Response.minor, Response.revision,
Response.stepping, Response.start, Response.count);
+
+ for (NodeId = Response.start; NodeId < Response.start + Response.count; NodeId++)
{
+
+ /* get function type */
+ verbs[0] = MAKE_VERB(codecAddress, NodeId, VID_GET_PARAMETER,
PID_FUNCTION_GROUP_TYPE);
+
+ HDA_SendVerbs(DeviceObject, Entry, verbs, &GroupType, 1);
+ DPRINT1("NodeId %u GroupType %x\n", NodeId, GroupType);
+
+ if ((GroupType & FUNCTION_GROUP_NODETYPE_MASK) ==
FUNCTION_GROUP_NODETYPE_AUDIO) {
+
+ AudioGroup = (PHDA_CODEC_AUDIO_GROUP)AllocateItem(NonPagedPool,
sizeof(HDA_CODEC_AUDIO_GROUP));
+ if (!AudioGroup)
+ {
+ DPRINT1("hda: insufficient memory\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* init audio group */
+ AudioGroup->NodeId = NodeId;
+ AudioGroup->FunctionGroup = FUNCTION_GROUP_NODETYPE_AUDIO;
+
+ // Found an Audio Function Group!
+ DPRINT1("NodeId %x found an audio function group!\n");
+
+ Status = IoCreateDevice(DeviceObject->DriverObject,
sizeof(HDA_PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_SOUND, 0, FALSE,
&AudioGroup->ChildPDO);
+ if (!NT_SUCCESS(Status))
+ {
+ FreeItem(AudioGroup);
+ DPRINT1("hda failed to create device object %x\n", Status);
+ return Status;
+ }
+
+ /* init child pdo*/
+ ChildDeviceExtension =
(PHDA_PDO_DEVICE_EXTENSION)AudioGroup->ChildPDO->DeviceExtension;
+ ChildDeviceExtension->IsFDO = FALSE;
+ ChildDeviceExtension->Codec = Entry;
+ ChildDeviceExtension->AudioGroup = AudioGroup;
+
+ /* setup flags */
+ AudioGroup->ChildPDO->Flags |= DO_POWER_PAGABLE;
+ AudioGroup->ChildPDO->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ /* add audio group*/
+ Entry->AudioGroups[Entry->AudioGroupCount] = AudioGroup;
+ Entry->AudioGroupCount++;
+ }
+ }
+ return STATUS_SUCCESS;
+
+}
+
+NTSTATUS
+NTAPI
+HDA_InitCorbRirbPos(
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
+ UCHAR corbSize, value, rirbSize;
+ PHYSICAL_ADDRESS HighestPhysicalAddress, CorbPhysicalAddress;
+ ULONG Index;
+ USHORT corbReadPointer, rirbWritePointer, interruptValue, corbControl, rirbControl;
+
+ /* get device extension */
+ DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ // Determine and set size of CORB
+ corbSize = READ_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_CORB_SIZE);
+ if ((corbSize & CORB_SIZE_CAP_256_ENTRIES) != 0) {
+ DeviceExtension->CorbLength = 256;
+
+ value = READ_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_CORB_SIZE) &
HDAC_CORB_SIZE_MASK;
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_CORB_SIZE, value |
CORB_SIZE_256_ENTRIES);
+ }
+ else if (corbSize & CORB_SIZE_CAP_16_ENTRIES) {
+ DeviceExtension->CorbLength = 16;
+
+ value = READ_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_CORB_SIZE) &
HDAC_CORB_SIZE_MASK;
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_CORB_SIZE, value |
CORB_SIZE_16_ENTRIES);
+ }
+ else if (corbSize & CORB_SIZE_CAP_2_ENTRIES) {
+ DeviceExtension->CorbLength = 2;
+
+ value = READ_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_CORB_SIZE) &
HDAC_CORB_SIZE_MASK;
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_CORB_SIZE, value |
CORB_SIZE_2_ENTRIES);
+ }
+
+ // Determine and set size of RIRB
+ rirbSize = READ_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_RIRB_SIZE);
+ if (rirbSize & RIRB_SIZE_CAP_256_ENTRIES) {
+ DeviceExtension->RirbLength = 256;
+
+ value = READ_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_RIRB_SIZE) &
HDAC_RIRB_SIZE_MASK;
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_RIRB_SIZE, value |
RIRB_SIZE_256_ENTRIES);
+ }
+ else if (rirbSize & RIRB_SIZE_CAP_16_ENTRIES) {
+ DeviceExtension->RirbLength = 16;
+
+ value = READ_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_RIRB_SIZE) &
HDAC_RIRB_SIZE_MASK;
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_RIRB_SIZE, value |
RIRB_SIZE_16_ENTRIES);
+ }
+ else if (rirbSize & RIRB_SIZE_CAP_2_ENTRIES) {
+ DeviceExtension->RirbLength = 2;
+
+ value = READ_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_RIRB_SIZE) &
HDAC_RIRB_SIZE_MASK;
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_RIRB_SIZE, value |
RIRB_SIZE_2_ENTRIES);
+ }
+
+ /* init corb */
+ HighestPhysicalAddress.QuadPart = 0x00000000FFFFFFFF;
+ DeviceExtension->CorbBase = (PULONG)MmAllocateContiguousMemory(PAGE_SIZE * 3,
HighestPhysicalAddress);
+
+ // FIXME align rirb 128bytes
+ ASSERT(DeviceExtension->CorbLength == 256);
+ ASSERT(DeviceExtension->RirbLength == 256);
+
+ CorbPhysicalAddress = MmGetPhysicalAddress(DeviceExtension->CorbBase);
+
+ // Program CORB/RIRB for these locations
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase + HDAC_CORB_BASE_LOWER),
CorbPhysicalAddress.LowPart);
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase + HDAC_CORB_BASE_UPPER),
CorbPhysicalAddress.HighPart);
+
+ DeviceExtension->RirbBase =
(PRIRB_RESPONSE)((ULONG_PTR)DeviceExtension->CorbBase + PAGE_SIZE);
+ CorbPhysicalAddress.QuadPart += PAGE_SIZE;
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase + HDAC_RIRB_BASE_LOWER),
CorbPhysicalAddress.LowPart);
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase + HDAC_RIRB_BASE_UPPER),
CorbPhysicalAddress.HighPart);
+
+ // Program DMA position update
+ DeviceExtension->StreamPositions = (PVOID)((ULONG_PTR)DeviceExtension->RirbBase
+ PAGE_SIZE);
+ CorbPhysicalAddress.QuadPart += PAGE_SIZE;
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase +
HDAC_DMA_POSITION_BASE_LOWER), CorbPhysicalAddress.LowPart);
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase +
HDAC_DMA_POSITION_BASE_UPPER), CorbPhysicalAddress.HighPart);
+
+ value = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_CORB_WRITE_POS)) & HDAC_CORB_WRITE_POS_MASK;
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase + HDAC_CORB_WRITE_POS),
value);
+
+ // Reset CORB read pointer. Preseve bits marked as RsvdP.
+ // After setting the reset bit, we must wait for the hardware
+ // to acknowledge it, then manually unset it and wait for that
+ // to be acknowledged as well.
+ corbReadPointer = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_CORB_READ_POS));
+
+ corbReadPointer |= CORB_READ_POS_RESET;
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase + HDAC_CORB_READ_POS),
corbReadPointer);
+
+ for (Index = 0; Index < 100; Index++) {
+ KeStallExecutionProcessor(10);
+ corbReadPointer = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_CORB_READ_POS));
+ if ((corbReadPointer & CORB_READ_POS_RESET) != 0)
+ break;
+ }
+ if ((corbReadPointer & CORB_READ_POS_RESET) == 0) {
+ DPRINT1("hda: CORB read pointer reset not acknowledged\n");
+
+ // According to HDA spec v1.0a ch3.3.21, software must read the
+ // bit as 1 to verify that the reset completed. However, at least
+ // some nVidia HDA controllers do not update the bit after reset.
+ // Thus don't fail here on nVidia controllers.
+ //if (controller->pci_info.vendor_id != PCI_VENDOR_NVIDIA)
+ // return B_BUSY;
+ }
+
+ corbReadPointer &= ~CORB_READ_POS_RESET;
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase + HDAC_CORB_READ_POS),
corbReadPointer);
+ for (Index = 0; Index < 10; Index++) {
+ KeStallExecutionProcessor(10);
+ corbReadPointer = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_CORB_READ_POS));
+ if ((corbReadPointer & CORB_READ_POS_RESET) == 0)
+ break;
+ }
+ if ((corbReadPointer & CORB_READ_POS_RESET) != 0) {
+ DPRINT1("hda: CORB read pointer reset failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Reset RIRB write pointer
+ rirbWritePointer = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_RIRB_WRITE_POS)) & RIRB_WRITE_POS_RESET;
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase + HDAC_RIRB_WRITE_POS),
rirbWritePointer | RIRB_WRITE_POS_RESET);
+
+ // Generate interrupt for every response
+ interruptValue = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_RESPONSE_INTR_COUNT)) & HDAC_RESPONSE_INTR_COUNT_MASK;
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_RESPONSE_INTR_COUNT), interruptValue | 1);
+
+ // Setup cached read/write indices
+ DeviceExtension->RirbReadPos = 1;
+ DeviceExtension->CorbWritePos = 0;
+
+ // Gentlemen, start your engines...
+ corbControl = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_CORB_CONTROL)) &HDAC_CORB_CONTROL_MASK;
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase + HDAC_CORB_CONTROL),
corbControl | CORB_CONTROL_RUN | CORB_CONTROL_MEMORY_ERROR_INTR);
+
+ rirbControl = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_RIRB_CONTROL)) & HDAC_RIRB_CONTROL_MASK;
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase + HDAC_RIRB_CONTROL),
rirbControl | RIRB_CONTROL_DMA_ENABLE | RIRB_CONTROL_OVERRUN_INTR |
RIRB_CONTROL_RESPONSE_INTR);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+HDA_ResetController(
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ USHORT ValCapabilities;
+ ULONG Index;
+ PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
+ ULONG InputStreams, OutputStreams, BiDirStreams, Control;
+ UCHAR corbControl, rirbControl;
+
+ /* get device extension */
+ DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* read caps */
+ ValCapabilities = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_GLOBAL_CAP));
+
+ InputStreams = GLOBAL_CAP_INPUT_STREAMS(ValCapabilities);
+ OutputStreams = GLOBAL_CAP_OUTPUT_STREAMS(ValCapabilities);
+ BiDirStreams = GLOBAL_CAP_BIDIR_STREAMS(ValCapabilities);
+
+ DPRINT1("NumInputStreams %u\n", InputStreams);
+ DPRINT1("NumOutputStreams %u\n", OutputStreams);
+ DPRINT1("NumBiDirStreams %u\n", BiDirStreams);
+
+ /* stop all streams */
+ for (Index = 0; Index < InputStreams; Index++)
+ {
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_STREAM_CONTROL0 +
HDAC_STREAM_BASE + HDAC_INPUT_STREAM_OFFSET(Index), 0);
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_STREAM_STATUS +
HDAC_STREAM_BASE + HDAC_INPUT_STREAM_OFFSET(Index), 0);
+ }
+
+ for (Index = 0; Index < OutputStreams; Index++) {
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_STREAM_CONTROL0 +
HDAC_STREAM_BASE + HDAC_OUTPUT_STREAM_OFFSET(InputStreams, Index), 0);
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_STREAM_STATUS +
HDAC_STREAM_BASE + HDAC_OUTPUT_STREAM_OFFSET(InputStreams, Index), 0);
+ }
+
+ for (Index = 0; Index < BiDirStreams; Index++) {
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_STREAM_CONTROL0 +
HDAC_STREAM_BASE + HDAC_BIDIR_STREAM_OFFSET(InputStreams, OutputStreams, Index), 0);
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_STREAM_STATUS +
HDAC_STREAM_BASE + HDAC_BIDIR_STREAM_OFFSET(InputStreams, OutputStreams, Index), 0);
+ }
+
+ // stop DMA
+ Control = READ_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_CORB_CONTROL) &
HDAC_CORB_CONTROL_MASK;
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_CORB_CONTROL, Control);
+
+ Control = READ_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_RIRB_CONTROL) &
HDAC_RIRB_CONTROL_MASK;
+ WRITE_REGISTER_UCHAR(DeviceExtension->RegBase + HDAC_RIRB_CONTROL, Control);
+
+ for (int timeout = 0; timeout < 10; timeout++) {
+ KeStallExecutionProcessor(10);
+
+ corbControl = READ_REGISTER_UCHAR(DeviceExtension->RegBase +
HDAC_CORB_CONTROL);
+ rirbControl = READ_REGISTER_UCHAR(DeviceExtension->RegBase +
HDAC_RIRB_CONTROL);
+ if (corbControl == 0 && rirbControl == 0)
+ break;
+ }
+ if (corbControl != 0 || rirbControl != 0) {
+ DPRINT1("hda: unable to stop dma\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // reset DMA position buffer
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase +
HDAC_DMA_POSITION_BASE_LOWER), 0);
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase +
HDAC_DMA_POSITION_BASE_UPPER), 0);
+
+ // Set reset bit - it must be asserted for at least 100us
+ Control = READ_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase +
HDAC_GLOBAL_CONTROL));
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase + HDAC_GLOBAL_CONTROL),
Control & ~GLOBAL_CONTROL_RESET);
+
+ for (int timeout = 0; timeout < 10; timeout++) {
+ KeStallExecutionProcessor(10);
+
+ Control = READ_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase +
HDAC_GLOBAL_CONTROL));
+ if ((Control & GLOBAL_CONTROL_RESET) == 0)
+ break;
+ }
+ if ((Control & GLOBAL_CONTROL_RESET) != 0)
+ {
+ DPRINT1("hda: unable to reset controller\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Unset reset bit
+ Control = READ_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase +
HDAC_GLOBAL_CONTROL));
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase + HDAC_GLOBAL_CONTROL),
Control | GLOBAL_CONTROL_RESET);
+
+ for (int timeout = 0; timeout < 10; timeout++) {
+ KeStallExecutionProcessor(10);
+
+ Control = READ_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase +
HDAC_GLOBAL_CONTROL));
+ if ((Control & GLOBAL_CONTROL_RESET) != 0)
+ break;
+ }
+ if ((Control & GLOBAL_CONTROL_RESET) == 0) {
+ DPRINT1("hda: unable to exit reset\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Wait for codecs to finish their own reset (apparently needs more
+ // time than documented in the specs)
+ KeStallExecutionProcessor(100);
+
+ // Enable unsolicited responses
+ Control = READ_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase +
HDAC_GLOBAL_CONTROL));
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase + HDAC_GLOBAL_CONTROL),
Control | GLOBAL_CONTROL_UNSOLICITED);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+HDA_QueryId(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ WCHAR DeviceName[200];
+ PHDA_PDO_DEVICE_EXTENSION DeviceExtension;
+ ULONG Length;
+ LPWSTR Device;
+
+ /* get device extension */
+ DeviceExtension = (PHDA_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ASSERT(DeviceExtension->IsFDO == FALSE);
+
+ /* get current irp stack location */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID)
+ {
+ UNIMPLEMENTED;
+
+ // FIXME
+ swprintf(DeviceName, L"%08x", 1);
+ Length = wcslen(DeviceName) + 20;
+
+ /* allocate result buffer*/
+ Device = (LPWSTR)AllocateItem(PagedPool, Length * sizeof(WCHAR));
+ if (!Device)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ swprintf(Device, L"%08x", 1);
+
+ DPRINT1("ID: %S\n", Device);
+ /* store result */
+ Irp->IoStatus.Information = (ULONG_PTR)Device;
+ return STATUS_SUCCESS;
+ }
+ else if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID ||
+ IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
+ {
+
+ /* calculate size */
+ swprintf(DeviceName,
L"HDAUDIO\\FUNC_%02X&VEN_%04X&DEV_%04X&SUBSYS_%08X",
DeviceExtension->AudioGroup->FunctionGroup, DeviceExtension->Codec->VendorId,
DeviceExtension->Codec->ProductId, DeviceExtension->Codec->VendorId <<
16 | DeviceExtension->Codec->ProductId);
+ Length = wcslen(DeviceName) + 20;
+
+ /* allocate result buffer*/
+ Device = (LPWSTR)AllocateItem(PagedPool, Length * sizeof(WCHAR));
+ if (!Device)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ swprintf(Device,
L"HDAUDIO\\FUNC_%02X&VEN_%04X&DEV_%04X&SUBSYS_%08X",
DeviceExtension->AudioGroup->FunctionGroup, DeviceExtension->Codec->VendorId,
DeviceExtension->Codec->ProductId, DeviceExtension->Codec->VendorId <<
16 | DeviceExtension->Codec->ProductId);
+
+ DPRINT1("ID: %S\n", Device);
+ /* store result */
+ Irp->IoStatus.Information = (ULONG_PTR)Device;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ DPRINT1("QueryID Type %x not implemented\n",
IoStack->Parameters.QueryId.IdType);
+ return Irp->IoStatus.Status;
+ }
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+HDA_StartDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
+ PCM_RESOURCE_LIST Resources;
+ ULONG Index;
+ USHORT Value;
+
+ /* get current irp stack location */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ /* get device extension */
+ DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ASSERT(DeviceExtension->IsFDO == TRUE);
+
+ Resources = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
+ for (Index = 0; Index < Resources->List[0].PartialResourceList.Count; Index++)
+ {
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor =
&Resources->List[0].PartialResourceList.PartialDescriptors[Index];
+
+ if (Descriptor->Type == CmResourceTypeMemory)
+ {
+ DeviceExtension->RegBase =
(PUCHAR)MmMapIoSpace(Descriptor->u.Memory.Start, Descriptor->u.Memory.Length,
MmNonCached);
+ if (DeviceExtension->RegBase == NULL)
+ {
+ DPRINT1("[HDAB] Failed to map registers\n");
+ Status = STATUS_UNSUCCESSFUL;
+ break;
+ }
+ }
+ else if (Descriptor->Type == CmResourceTypeInterrupt)
+ {
+ Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
+ HDA_InterruptService,
+ (PVOID)DeviceExtension,
+ NULL,
+ Descriptor->u.Interrupt.Vector,
+ Descriptor->u.Interrupt.Level,
+ Descriptor->u.Interrupt.Level,
+ (KINTERRUPT_MODE)(Descriptor->Flags &
CM_RESOURCE_INTERRUPT_LATCHED),
+ (Descriptor->ShareDisposition !=
CmResourceShareDeviceExclusive),
+ Descriptor->u.Interrupt.Affinity,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("[HDAB] Failed to connect interrupt\n");
+ break;
+ }
+
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ // Get controller into valid state
+ Status = HDA_ResetController(DeviceObject);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ // Setup CORB/RIRB/DMA POS
+ Status = HDA_InitCorbRirbPos(DeviceObject);
+ if (!NT_SUCCESS(Status)) return Status;
+
+
+ // Don't enable codec state change interrupts. We don't handle
+ // them, as we want to use the STATE_STATUS register to identify
+ // available codecs. We'd have to clear that register in the interrupt
+ // handler to 'ack' the codec change.
+ Value = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_WAKE_ENABLE)) & HDAC_WAKE_ENABLE_MASK;
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase + HDAC_WAKE_ENABLE),
Value);
+
+ // Enable controller interrupts
+ WRITE_REGISTER_ULONG((PULONG)(DeviceExtension->RegBase + HDAC_INTR_CONTROL),
INTR_CONTROL_GLOBAL_ENABLE | INTR_CONTROL_CONTROLLER_ENABLE);
+
+ KeStallExecutionProcessor(100);
+
+ Value = READ_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase +
HDAC_STATE_STATUS));
+ if (!Value) {
+ DPRINT1("hda: bad codec status\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+ WRITE_REGISTER_USHORT((PUSHORT)(DeviceExtension->RegBase + HDAC_STATE_STATUS),
Value);
+
+ // Create codecs
+ DPRINT1("Codecs %lx\n", Value);
+ for (Index = 0; Index < HDA_MAX_CODECS; Index++) {
+ if ((Value & (1 << Index)) != 0) {
+ HDA_InitCodec(DeviceObject, Index);
+ }
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+HDA_QueryBusRelations(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ ULONG DeviceCount, CodecIndex, AFGIndex;
+ PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
+ PHDA_CODEC_ENTRY Codec;
+ PDEVICE_RELATIONS DeviceRelations;
+
+ /* get device extension */
+ DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ASSERT(DeviceExtension->IsFDO == TRUE);
+
+ DeviceCount = 0;
+ for (CodecIndex = 0; CodecIndex < HDA_MAX_CODECS; CodecIndex++)
+ {
+ if (DeviceExtension->Codecs[CodecIndex] == NULL)
+ continue;
+
+ Codec = DeviceExtension->Codecs[CodecIndex];
+ DeviceCount += Codec->AudioGroupCount;
+ }
+
+ if (DeviceCount == 0)
+ return STATUS_UNSUCCESSFUL;
+
+ DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(NonPagedPool,
sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? sizeof(PDEVICE_OBJECT) * (DeviceCount -
1) : 0));
+ if (!DeviceRelations)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ DeviceCount = 0;
+ for (CodecIndex = 0; CodecIndex < HDA_MAX_CODECS; CodecIndex++)
+ {
+ if (DeviceExtension->Codecs[CodecIndex] == NULL)
+ continue;
+
+ Codec = DeviceExtension->Codecs[CodecIndex];
+ for (AFGIndex = 0; AFGIndex < Codec->AudioGroupCount; AFGIndex++)
+ {
+ DeviceRelations->Objects[DeviceRelations->Count] =
Codec->AudioGroups[AFGIndex]->ChildPDO;
+ ObReferenceObject(Codec->AudioGroups[AFGIndex]->ChildPDO);
+ DeviceRelations->Count++;
+ }
+ }
+
+ /* FIXME handle existing device relations */
+ ASSERT(Irp->IoStatus.Information == 0);
+
+ /* store device relations */
+ Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+ /* done */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+HDA_QueryBusInformation(
+ IN PIRP Irp)
+{
+ PPNP_BUS_INFORMATION BusInformation;
+
+ /* allocate bus information */
+ BusInformation = (PPNP_BUS_INFORMATION)AllocateItem(PagedPool,
sizeof(PNP_BUS_INFORMATION));
+
+ if (!BusInformation)
+ {
+ /* no memory */
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* return info */
+ BusInformation->BusNumber = 0;
+ BusInformation->LegacyBusType = PCIBus;
+ RtlMoveMemory(&BusInformation->BusTypeGuid, &GUID_HDAUDIO_BUS_INTERFACE,
sizeof(GUID));
+
+ /* store result */
+ Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
+
+ /* done */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+HDA_QueryBusDeviceCapabilities(
+ IN PIRP Irp)
+{
+ PDEVICE_CAPABILITIES Capabilities;
+ PIO_STACK_LOCATION IoStack;
+
+ /* get stack location */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ /* get capabilities */
+ Capabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
+
+ RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
+
+ /* setup capabilities */
+ Capabilities->UniqueID = TRUE;
+ Capabilities->SilentInstall = TRUE;
+ Capabilities->SurpriseRemovalOK = TRUE;
+ Capabilities->Address = 0;
+ Capabilities->UINumber = 0;
+ Capabilities->SystemWake = PowerSystemWorking; /* FIXME common device extension
*/
+ Capabilities->DeviceWake = PowerDeviceD0;
+
+ /* done */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+HDA_QueryBusDevicePnpState(
+ IN PIRP Irp)
+{
+ /* set device flags */
+ Irp->IoStatus.Information = PNP_DEVICE_DONT_DISPLAY_IN_UI |
PNP_DEVICE_NOT_DISABLEABLE;
+
+ /* done */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+HDA_PdoHandleQueryDeviceText(
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ LPWSTR Buffer;
+ static WCHAR DeviceText[] = L"Audio Device on High Definition Audio Bus";
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ if (IoStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription)
+ {
+ DPRINT("HDA_PdoHandleQueryDeviceText DeviceTextDescription\n");
+
+ Buffer = (LPWSTR)AllocateItem(PagedPool, sizeof(DeviceText));
+ if (!Buffer)
+ {
+ Irp->IoStatus.Information = 0;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ wcscpy(Buffer, DeviceText);
+
+ Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ DPRINT("HDA_PdoHandleQueryDeviceText
DeviceTextLocationInformation\n");
+
+ Buffer = (LPWSTR)AllocateItem(PagedPool, sizeof(DeviceText));
+ if (!Buffer)
+ {
+ Irp->IoStatus.Information = 0;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ wcscpy(Buffer, DeviceText);
+
+ /* save result */
+ Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+ return STATUS_SUCCESS;
+ }
+
+}
+
+NTSTATUS
+NTAPI
+HDA_Pnp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status = STATUS_NOT_SUPPORTED;
+ PIO_STACK_LOCATION IoStack;
+ PDEVICE_RELATIONS DeviceRelation;
+ PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension;
+ PHDA_PDO_DEVICE_EXTENSION ChildDeviceExtension;
+
+ FDODeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ChildDeviceExtension = (PHDA_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ DPRINT1("HDA_Pnp Minor: %u IsFDO%d\n", IoStack->MinorFunction,
FDODeviceExtension->IsFDO);
+
+ if (FDODeviceExtension->IsFDO)
+ {
+ if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
+ {
+ DPRINT1("IRP_MN_START_DEVICE\n");
+ Status = HDA_StartDevice(DeviceObject, Irp);
+ }
+ else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS)
+ {
+ DPRINT1("IRP_MN_QUERY_DEVICE_RELATIONS\n");
+ /* handle bus device relations */
+ if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
+ {
+ Status = HDA_QueryBusRelations(DeviceObject, Irp);
+ }
+ else
+ {
+ Status = Irp->IoStatus.Status;
+ }
+ }
+ else
+ {
+ /* get default status */
+ Status = Irp->IoStatus.Status;
+ }
+ }
+ else
+ {
+ if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
+ {
+ DPRINT1("IRP_MN_START_DEVICE\n");
+ /* no op for pdo */
+ Status = STATUS_SUCCESS;
+ }
+ else if (IoStack->MinorFunction == IRP_MN_QUERY_BUS_INFORMATION)
+ {
+ DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n");
+ /* query bus information */
+ Status = HDA_QueryBusInformation(Irp);
+ }
+ else if (IoStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
+ {
+ DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
+ /* query pnp state */
+ Status = HDA_QueryBusDevicePnpState(Irp);
+ }
+ else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS)
+ {
+ DPRINT1("IRP_MN_QUERY_DEVICE_RELATIONS\n");
+ if (IoStack->Parameters.QueryDeviceRelations.Type ==
TargetDeviceRelation)
+ {
+ /* handle target device relations */
+ ASSERT(IoStack->Parameters.QueryDeviceRelations.Type ==
TargetDeviceRelation);
+ ASSERT(Irp->IoStatus.Information == 0);
+
+ /* allocate device relation */
+ DeviceRelation = (PDEVICE_RELATIONS)AllocateItem(PagedPool,
sizeof(DEVICE_RELATIONS));
+ if (DeviceRelation)
+ {
+ DeviceRelation->Count = 1;
+ DeviceRelation->Objects[0] = DeviceObject;
+
+ /* reference self */
+ ObReferenceObject(DeviceObject);
+
+ /* store result */
+ Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
+
+ /* done */
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ /* no memory */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ }
+ else if (IoStack->MinorFunction == IRP_MN_QUERY_CAPABILITIES)
+ {
+ DPRINT1("IRP_MN_QUERY_CAPABILITIES\n");
+ /* query capabilities */
+ Status = HDA_QueryBusDeviceCapabilities(Irp);
+ }
+ else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS)
+ {
+ DPRINT1("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
+ /* no op */
+ Status = STATUS_SUCCESS;
+ }
+ else if (IoStack->MinorFunction == IRP_MN_QUERY_ID)
+ {
+ DPRINT1("IRP_MN_QUERY_ID\n");
+ Status = HDA_QueryId(DeviceObject, Irp);
+ }
+ else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_TEXT)
+ {
+ DPRINT1("IRP_MN_QUERY_DEVICE_TEXT\n");
+ Status = HDA_PdoHandleQueryDeviceText(Irp);
+ }
+ else
+ {
+ /* get default status */
+ Status = Irp->IoStatus.Status;
+ }
+ }
+
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+
+ return Status;
+}
+
+
+//PDRIVER_ADD_DEVICE HDA_AddDevice;
+
+NTSTATUS
+NTAPI
+HDA_AddDevice(
+IN PDRIVER_OBJECT DriverObject,
+IN PDEVICE_OBJECT PhysicalDeviceObject)
+{
+ PDEVICE_OBJECT DeviceObject;
+ PHDA_FDO_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+
+ /* create device object */
+ Status = IoCreateDevice(DriverObject, sizeof(HDA_FDO_DEVICE_EXTENSION), NULL,
FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &DeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ /* failed */
+ return Status;
+ }
+
+ /* get device extension*/
+ DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* init device extension*/
+ DeviceExtension->IsFDO = TRUE;
+ DeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject,
PhysicalDeviceObject);
+ RtlZeroMemory(DeviceExtension->Codecs, sizeof(PHDA_CODEC_ENTRY) * (HDA_MAX_CODECS
+ 1));
+
+
+ /* set device flags */
+ DeviceObject->Flags |= DO_POWER_PAGABLE;
+
+ return Status;
+}
+extern "C"
+{
+NTSTATUS
+NTAPI
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPathName)
+{
+ DriverObject->DriverExtension->AddDevice = HDA_AddDevice;
+ DriverObject->MajorFunction[IRP_MJ_PNP] = HDA_Pnp;
+
+ return STATUS_SUCCESS;
+}
+
+}
Propchange: trunk/reactos/drivers/wdm/audio/hdaudbus/hdaudbus.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/drivers/wdm/audio/hdaudbus/hdaudbus.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/hdaudbus…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/hdaudbus/hdaudbus.h (added)
+++ trunk/reactos/drivers/wdm/audio/hdaudbus/hdaudbus.h [iso-8859-1] Mon Jun 29 17:03:33
2015
@@ -0,0 +1,103 @@
+#pragma once
+
+#define YDEBUG
+#include <ntddk.h>
+#include <debug.h>
+#include <initguid.h>
+#include <hdaudio.h>
+#include <stdio.h>
+
+#define TAG_HDA 'bADH'
+
+
+// include Haiku headers
+#include "driver.h"
+
+#define MAKE_RATE(base, multiply, divide) \
+ ((base == 44100 ? FORMAT_44_1_BASE_RATE : 0) \
+ | ((multiply - 1) << FORMAT_MULTIPLY_RATE_SHIFT) \
+ | ((divide - 1) << FORMAT_DIVIDE_RATE_SHIFT))
+
+#define HDAC_INPUT_STREAM_OFFSET(index) \
+ ((index) * HDAC_STREAM_SIZE)
+#define HDAC_OUTPUT_STREAM_OFFSET(num_input_streams, index) \
+ ((num_input_streams + (index)) * HDAC_STREAM_SIZE)
+#define HDAC_BIDIR_STREAM_OFFSET(num_input_streams, num_output_streams, index) \
+ ((num_input_streams + num_output_streams \
+ + (index)) * HDAC_STREAM_SIZE)
+
+#define ALIGN(size, align) (((size) + align - 1) & ~(align - 1))
+
+
+typedef struct {
+ ULONG response;
+ ULONG flags;
+}RIRB_RESPONSE, *PRIRB_RESPONSE;
+
+typedef struct
+{
+ PDEVICE_OBJECT ChildPDO;
+ ULONG FunctionGroup;
+ ULONG NodeId;
+}HDA_CODEC_AUDIO_GROUP, *PHDA_CODEC_AUDIO_GROUP;
+
+typedef struct
+{
+ USHORT VendorId;
+ USHORT ProductId;
+ UCHAR Major;
+ UCHAR Minor;
+ UCHAR Revision;
+ UCHAR Stepping;
+ UCHAR Addr;
+
+ ULONG Responses[MAX_CODEC_RESPONSES];
+ ULONG ResponseCount;
+
+ PHDA_CODEC_AUDIO_GROUP AudioGroups[HDA_MAX_AUDIO_GROUPS];
+ ULONG AudioGroupCount;
+
+}HDA_CODEC_ENTRY, *PHDA_CODEC_ENTRY;
+
+
+typedef struct
+{
+ BOOLEAN IsFDO;
+ PDEVICE_OBJECT LowerDevice;
+
+ PUCHAR RegBase;
+ PKINTERRUPT Interrupt;
+
+ ULONG CorbLength;
+ PULONG CorbBase;
+ ULONG RirbLength;
+ PRIRB_RESPONSE RirbBase;
+ ULONG RirbReadPos;
+ ULONG CorbWritePos;
+ PVOID StreamPositions;
+
+ PHDA_CODEC_ENTRY Codecs[HDA_MAX_CODECS + 1];
+
+}HDA_FDO_DEVICE_EXTENSION, *PHDA_FDO_DEVICE_EXTENSION;
+
+typedef struct
+{
+ BOOLEAN IsFDO;
+ PHDA_CODEC_ENTRY Codec;
+ PHDA_CODEC_AUDIO_GROUP AudioGroup;
+}HDA_PDO_DEVICE_EXTENSION, *PHDA_PDO_DEVICE_EXTENSION;
+
+
+typedef struct {
+ ULONG device : 16;
+ ULONG vendor : 16;
+ ULONG stepping : 8;
+ ULONG revision : 8;
+ ULONG minor : 4;
+ ULONG major : 4;
+ ULONG _reserved0 : 8;
+ ULONG count : 8;
+ ULONG _reserved1 : 8;
+ ULONG start : 8;
+ ULONG _reserved2 : 8;
+}CODEC_RESPONSE, *PCODEC_RESPONSE;
Propchange: trunk/reactos/drivers/wdm/audio/hdaudbus/hdaudbus.h
------------------------------------------------------------------------------
svn:eol-style = native