1 /*
2     ReactOS Sound System
3     Sound Blaster DSP support
4     General I/O
5 
6     Author:
7         Andrew Greenwood (silverblade@reactos.org)
8 
9     History:
10         2 July 2008 - Created (split from sbdsp.c)
11 
12     Notes:
13         Functions documented in sbdsp.h
14 */
15 
16 #include "precomp.h"
17 
18 NTSTATUS
19 SbDspReset(
20     IN  PUCHAR BasePort,
21     IN  ULONG Timeout)
22 {
23     ULONG Expiry;
24     BOOLEAN DataAvailable = FALSE;
25 
26     /* Should be called from DriverEntry with this IRQL */
27     ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
28 
29     WRITE_SB_DSP_RESET(BasePort, 0x01);
30     SleepMs(50);   /* Should be enough */
31     WRITE_SB_DSP_RESET(BasePort, 0x00);
32 
33     Expiry = QuerySystemTimeMs() + Timeout;
34 
35     /* Wait for data to be available */
36     while ( (QuerySystemTimeMs() < Expiry) || ( Timeout == 0) )
37     {
38         if ( SB_DSP_DATA_AVAILABLE(BasePort) )
39         {
40             DataAvailable = TRUE;
41             break;
42         }
43     }
44 
45     if ( ! DataAvailable )
46     {
47         return STATUS_TIMEOUT;
48     }
49 
50     /* Data is available - wait for the "DSP ready" code */
51     while ( (QuerySystemTimeMs() < Expiry) || ( Timeout == 0) )
52     {
53         if ( READ_SB_DSP_DATA(BasePort) == SB_DSP_READY )
54         {
55             return STATUS_SUCCESS;
56         }
57     }
58 
59     return STATUS_TIMEOUT;
60 }
61 
62 NTSTATUS
63 SbDspWaitToWrite(
64     IN  PUCHAR BasePort,
65     IN  ULONG Timeout)
66 {
67     ULONG Expiry = QuerySystemTimeMs() + Timeout;
68 
69     while ( (QuerySystemTimeMs() < Expiry) || (Timeout == 0) )
70     {
71         if ( SB_DSP_CLEAR_TO_SEND(BasePort) )
72         {
73             return STATUS_SUCCESS;
74         }
75     }
76 
77     return STATUS_TIMEOUT;
78 }
79 
80 NTSTATUS
81 SbDspWaitToRead(
82     IN  PUCHAR BasePort,
83     IN  ULONG Timeout)
84 {
85     ULONG Expiry = QuerySystemTimeMs() + Timeout;
86 
87     while ( (QuerySystemTimeMs() < Expiry) || (Timeout == 0) )
88     {
89         if ( SB_DSP_DATA_AVAILABLE(BasePort) )
90         {
91             return STATUS_SUCCESS;
92         }
93     }
94 
95     return STATUS_TIMEOUT;
96 }
97 
98 NTSTATUS
99 SbDspWrite(
100     IN  PUCHAR BasePort,
101     IN  UCHAR DataByte,
102     IN  ULONG Timeout)
103 {
104     NTSTATUS Status;
105 
106     Status = SbDspWaitToWrite(BasePort, Timeout);
107 
108     if ( Status != STATUS_SUCCESS )
109     {
110         return Status;
111     }
112 
113     DbgPrint("SBDSP - Writing %02x\n", DataByte);
114     WRITE_SB_DSP_DATA(BasePort, DataByte);
115 
116     return STATUS_SUCCESS;
117 }
118 
119 NTSTATUS
120 SbDspRead(
121     IN  PUCHAR BasePort,
122     OUT PUCHAR DataByte,
123     IN  ULONG Timeout)
124 {
125     NTSTATUS Status;
126 
127     if ( ! DataByte )
128     {
129         return STATUS_INVALID_PARAMETER_2;
130     }
131 
132     Status = SbDspWaitToRead(BasePort, Timeout);
133 
134     if ( Status != STATUS_SUCCESS )
135     {
136         return Status;
137     }
138 
139     *DataByte = READ_SB_DSP_DATA(BasePort);
140     DbgPrint("SBDSP - Read %02x\n", *DataByte);
141 
142     return STATUS_SUCCESS;
143 }
144