Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
53268a54
Commit
53268a54
authored
May 16, 2002
by
Christian Costa
Committed by
Alexandre Julliard
May 16, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added DMA and SoundBlaster emulation.
parent
a60d05b4
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
869 additions
and
1 deletion
+869
-1
Makefile.in
dlls/winedos/Makefile.in
+3
-1
dma.c
dlls/winedos/dma.c
+381
-0
dosexe.h
dlls/winedos/dosexe.h
+9
-0
ioports.c
dlls/winedos/ioports.c
+93
-0
soundblaster.c
dlls/winedos/soundblaster.c
+383
-0
No files found.
dlls/winedos/Makefile.in
View file @
53268a54
...
...
@@ -7,8 +7,9 @@ IMPORTS = user32 kernel32 ntdll
LDIMPORTS
=
user32.dll kernel32.dll ntdll.dll
C_SRCS
=
\
dosaspi.c
\
devices.c
\
dma.c
\
dosaspi.c
\
dosvm.c
\
int09.c
\
int10.c
\
...
...
@@ -23,6 +24,7 @@ C_SRCS = \
int67.c
\
ioports.c
\
module.c
\
soundblaster.c
\
vga.c
\
xms.c
...
...
dlls/winedos/dma.c
0 → 100644
View file @
53268a54
/*
* DMA Emulation
*
* Copyright 2002 Christian Costa
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "windef.h"
#include "dosexe.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dma
);
/* Internal registers of the 2 DMA chips wich control 8 DMA channels */
static
DWORD
DMA_BaseAddress
[
8
];
static
WORD
DMA_ByteCount
[
8
];
static
DWORD
DMA_CurrentBaseAddress
[
8
];
static
WORD
DMA_CurrentByteCount
[
8
];
static
BYTE
DMA_Command
[
8
];
static
BYTE
DMA_Mask
[
2
]
=
{
0x0F
,
0x0F
};
static
BYTE
DMA_Status
[
2
]
=
{
0x00
,
0x00
};
static
BOOL
DMA_Toggle
[
2
]
=
{
FALSE
,
FALSE
};
/*
* DMA_Transfer : Try to perform a transfer of reqlen elements (8 or 16 bits)
* on the specified channel and return the elements transferred
*/
int
DMA_Transfer
(
int
channel
,
int
reqlen
,
void
*
buffer
)
{
int
i
,
size
,
ret
=
0
;
int
opmode
,
increment
,
autoinit
,
trmode
,
dmachip
;
int
regmode
=
DMA_Command
[
channel
];
char
*
p
,
*
dmabuf
;
dmabuf
=
buffer
;
dmachip
=
(
channel
<
4
)
?
0
:
1
;
TRACE
(
"DMA_Command = %x reqlen=%d
\n
"
,
regmode
,
reqlen
);
/* Exit if channel is masked */
if
(
DMA_Mask
[
dmachip
]
&
(
1
<<
(
channel
&
3
)))
return
0
;
opmode
=
(
regmode
&
0xC0
)
>>
6
;
increment
=
!
(
regmode
&
0x20
);
autoinit
=
regmode
&
0x10
;
trmode
=
(
regmode
&
0x0C
)
>>
2
;
/* Transfer size : 8 bits for channels 0..3, 16 bits for channels 4..7 */
size
=
(
channel
<
4
)
?
1
:
2
;
/* Process operating mode */
switch
(
opmode
)
{
case
0
:
/* Request mode */
FIXME
(
"Request Mode - Not Implemented
\n
"
);
return
0
;
case
1
:
/* Single Mode */
break
;
case
2
:
/* Request mode */
FIXME
(
"Block Mode - Not Implemented
\n
"
);
return
0
;
case
3
:
/* Cascade Mode */
ERR
(
"Cascade Mode should not be used by regular apps
\n
"
);
return
0
;
}
/* Perform one the 4 transfer modes */
if
(
trmode
==
4
)
{
/* Illegal */
ERR
(
"DMA Transfer Type Illegal
\n
"
);
return
0
;
}
ret
=
min
(
DMA_CurrentByteCount
[
channel
],
reqlen
);
/* Update DMA registers */
DMA_CurrentByteCount
[
channel
]
-=
ret
;
if
(
increment
)
DMA_CurrentBaseAddress
[
channel
]
+=
ret
*
size
;
else
DMA_CurrentBaseAddress
[
channel
]
-=
ret
*
size
;
switch
(
trmode
)
{
case
0
:
/* Verification (no real transfer)*/
TRACE
(
"Verification DMA operation
\n
"
);
break
;
case
1
:
/* Write */
TRACE
(
"Perform Write transfer of %d bytes at %lx with count %x
\n
"
,
ret
,
DMA_CurrentBaseAddress
[
channel
],
DMA_CurrentByteCount
[
channel
]);
if
(
increment
)
memcpy
((
void
*
)
DMA_CurrentBaseAddress
[
channel
],
dmabuf
,
ret
*
size
);
else
for
(
i
=
0
,
p
=
(
char
*
)
DMA_CurrentBaseAddress
[
channel
];
i
<
ret
*
size
;
i
++
)
/* FIXME: possible endianness issue for 16 bits DMA */
*
(
p
-
i
)
=
dmabuf
[
i
];
break
;
case
2
:
/* Read */
TRACE
(
"Perform Read transfer of %d bytes at %lx with count %x
\n
"
,
ret
,
DMA_CurrentBaseAddress
[
channel
],
DMA_CurrentByteCount
[
channel
]);
if
(
increment
)
memcpy
(
dmabuf
,(
void
*
)
DMA_CurrentBaseAddress
[
channel
],
ret
*
size
);
else
for
(
i
=
0
,
p
=
(
char
*
)
DMA_CurrentBaseAddress
[
channel
];
i
<
ret
*
size
;
i
++
)
/* FIXME: possible endianness issue for 16 bits DMA */
dmabuf
[
i
]
=
*
(
p
-
i
);
break
;
}
/* Check for end of transfer */
if
(
DMA_CurrentByteCount
[
channel
]
==
0
)
{
TRACE
(
"DMA buffer empty
\n
"
);
/* Update status register of the DMA chip corresponding to the channel */
DMA_Status
[
dmachip
]
|=
1
<<
(
channel
&
0x3
);
/* Mark transfer as finished */
DMA_Status
[
dmachip
]
&=
~
(
1
<<
((
channel
&
0x3
)
+
4
));
/* Reset soft request if any */
if
(
autoinit
)
{
/* Reload Current* register to their initial values */
DMA_CurrentBaseAddress
[
channel
]
=
DMA_BaseAddress
[
channel
];
DMA_CurrentByteCount
[
channel
]
=
DMA_ByteCount
[
channel
];
}
}
return
ret
;
}
void
DMA_ioport_out
(
WORD
port
,
BYTE
val
)
{
int
channel
,
dmachip
;
switch
(
port
)
{
case
0x00
:
case
0x02
:
case
0x04
:
case
0x06
:
case
0xC0
:
case
0xC4
:
case
0xC8
:
case
0xCC
:
/* Base Address*/
channel
=
(
port
&
0xC0
)
?
((
port
-
0xC0
)
>>
2
)
:
(
port
>>
1
);
dmachip
=
(
channel
<
4
)
?
0
:
1
;
if
(
!
DMA_Toggle
[
dmachip
])
DMA_BaseAddress
[
channel
]
=
(
DMA_BaseAddress
[
channel
]
&
~
0xFF
)
|
(
val
&
0xFF
);
else
{
DMA_BaseAddress
[
channel
]
=
(
DMA_BaseAddress
[
channel
]
&
(
~
(
0xFF
<<
8
)))
|
((
val
&
0xFF
)
<<
8
);
DMA_CurrentBaseAddress
[
channel
]
=
DMA_BaseAddress
[
channel
];
TRACE
(
"Write Base Address = %lx
\n
"
,
DMA_BaseAddress
[
channel
]);
}
DMA_Toggle
[
dmachip
]
=
!
DMA_Toggle
[
dmachip
];
break
;
case
0x01
:
case
0x03
:
case
0x05
:
case
0x07
:
case
0xC2
:
case
0xC6
:
case
0xCA
:
case
0xCE
:
/* Count*/
channel
=
((
port
-
1
)
&
0xC0
)
?
(((
port
-
1
)
-
0xC0
)
>>
2
)
:
(
port
>>
1
);
dmachip
=
(
channel
<
4
)
?
0
:
1
;
if
(
!
DMA_Toggle
[
dmachip
])
DMA_ByteCount
[
channel
]
=
(
DMA_ByteCount
[
channel
]
&
~
0xFF
)
|
((
val
+
1
)
&
0xFF
);
else
{
DMA_ByteCount
[
channel
]
=
(
DMA_ByteCount
[
channel
]
&
(
~
(
0xFF
<<
8
)))
|
(((
val
+
1
)
&
0xFF
)
<<
8
);
DMA_CurrentByteCount
[
channel
]
=
DMA_ByteCount
[
channel
];
TRACE
(
"Write Count = %x.
\n
"
,
DMA_ByteCount
[
channel
]);
}
DMA_Toggle
[
dmachip
]
=
!
DMA_Toggle
[
dmachip
];
break
;
/* Low Page Base Address */
case
0x87
:
DMA_BaseAddress
[
0
]
=
(
DMA_BaseAddress
[
0
]
&
(
~
0xFF
<<
16
))
|
((
val
&
0xFF
)
<<
16
);
break
;
case
0x83
:
DMA_BaseAddress
[
1
]
=
(
DMA_BaseAddress
[
1
]
&
(
~
0xFF
<<
16
))
|
((
val
&
0xFF
)
<<
16
);
break
;
case
0x81
:
DMA_BaseAddress
[
2
]
=
(
DMA_BaseAddress
[
2
]
&
(
~
0xFF
<<
16
))
|
((
val
&
0xFF
)
<<
16
);
break
;
case
0x82
:
DMA_BaseAddress
[
3
]
=
(
DMA_BaseAddress
[
3
]
&
(
~
0xFF
<<
16
))
|
((
val
&
0xFF
)
<<
16
);
break
;
case
0x8B
:
DMA_BaseAddress
[
5
]
=
(
DMA_BaseAddress
[
5
]
&
(
~
0xFF
<<
16
))
|
((
val
&
0xFF
)
<<
16
);
break
;
case
0x89
:
DMA_BaseAddress
[
6
]
=
(
DMA_BaseAddress
[
6
]
&
(
~
0xFF
<<
16
))
|
((
val
&
0xFF
)
<<
16
);
break
;
case
0x8A
:
DMA_BaseAddress
[
7
]
=
(
DMA_BaseAddress
[
7
]
&
(
~
0xFF
<<
16
))
|
((
val
&
0xFF
)
<<
16
);
break
;
/* Low Page Base Address (only 4 lower bits are significant) */
case
0x487
:
DMA_BaseAddress
[
0
]
=
(
DMA_BaseAddress
[
0
]
&
(
~
0xFF
<<
24
))
|
((
val
&
0x0F
)
<<
24
);
break
;
case
0x483
:
DMA_BaseAddress
[
1
]
=
(
DMA_BaseAddress
[
1
]
&
(
~
0xFF
<<
24
))
|
((
val
&
0x0F
)
<<
24
);
break
;
case
0x481
:
DMA_BaseAddress
[
2
]
=
(
DMA_BaseAddress
[
2
]
&
(
~
0xFF
<<
24
))
|
((
val
&
0x0F
)
<<
24
);
break
;
case
0x482
:
DMA_BaseAddress
[
3
]
=
(
DMA_BaseAddress
[
3
]
&
(
~
0xFF
<<
24
))
|
((
val
&
0x0F
)
<<
24
);
break
;
case
0x48B
:
DMA_BaseAddress
[
5
]
=
(
DMA_BaseAddress
[
5
]
&
(
~
0xFF
<<
24
))
|
((
val
&
0x0F
)
<<
24
);
break
;
case
0x489
:
DMA_BaseAddress
[
6
]
=
(
DMA_BaseAddress
[
6
]
&
(
~
0xFF
<<
24
))
|
((
val
&
0x0F
)
<<
24
);
break
;
case
0x48A
:
DMA_BaseAddress
[
7
]
=
(
DMA_BaseAddress
[
7
]
&
(
~
0xFF
<<
24
))
|
((
val
&
0x0F
)
<<
24
);
break
;
case
0x08
:
case
0xD0
:
/* Command */
FIXME
(
"Write Command (%x) - Not Implemented
\n
"
,
val
);
break
;
case
0x0B
:
case
0xD6
:
/* Mode */
TRACE
(
"Write Mode (%x)
\n
"
,
val
);
DMA_Command
[((
port
==
0xD6
)
?
4
:
0
)
+
(
val
&
0x3
)]
=
val
;
switch
(
val
>>
6
)
{
case
0
:
/* Request mode */
FIXME
(
"Request Mode - Not Implemented
\n
"
);
break
;
case
1
:
/* Single Mode */
break
;
case
2
:
/* Block mode */
FIXME
(
"Block Mode - Not Implemented
\n
"
);
break
;
case
3
:
/* Cascade Mode */
ERR
(
"Cascade Mode should not be used by regular apps
\n
"
);
break
;
}
break
;
case
0x0A
:
case
0xD4
:
/* Write Single Mask Bit */
TRACE
(
"Write Single Mask Bit (%x)
\n
"
,
val
);
dmachip
=
(
port
==
0x0A
)
?
0
:
1
;
if
(
val
&
4
)
DMA_Mask
[
dmachip
]
|=
1
<<
(
val
&
3
);
else
DMA_Mask
[
dmachip
]
&=
~
(
1
<<
(
val
&
3
));
break
;
case
0x0F
:
case
0xDE
:
/* Write All Mask Bits (only 4 lower bits are significant */
FIXME
(
"Write All Mask Bits (%x)
\n
"
,
val
);
dmachip
=
(
port
==
0x0F
)
?
0
:
1
;
DMA_Mask
[
dmachip
]
=
val
&
0x0F
;
break
;
case
0x09
:
case
0xD2
:
/* Software DRQx Request */
FIXME
(
"Software DRQx Request (%x) - Not Implemented
\n
"
,
val
);
break
;
case
0x0C
:
case
0xD8
:
/* Reset DMA Pointer Flip-Flop */
TRACE
(
"Reset Flip-Flop
\n
"
);
DMA_Toggle
[
port
==
0xD8
]
=
FALSE
;
break
;
case
0x0D
:
case
0xDA
:
/* Master Reset */
TRACE
(
"Master Reset
\n
"
);
dmachip
=
(
port
==
0x0D
)
?
0
:
1
;
/* Reset DMA Pointer Flip-Flop */
DMA_Toggle
[
dmachip
]
=
FALSE
;
/* Mask all channels */
DMA_Mask
[
dmachip
]
=
0x0F
;
break
;
case
0x0E
:
case
0xDC
:
/* Reset Mask Register */
FIXME
(
"Reset Mask Register
\n
"
);
dmachip
=
(
port
==
0x0E
)
?
0
:
1
;
/* Unmask all channels */
DMA_Mask
[
dmachip
]
=
0x00
;
break
;
}
}
BYTE
DMA_ioport_in
(
WORD
port
)
{
int
channel
,
dmachip
;
BYTE
res
=
0
;
switch
(
port
)
{
case
0x00
:
case
0x02
:
case
0x04
:
case
0x06
:
case
0xC0
:
case
0xC4
:
case
0xC8
:
case
0xCC
:
/* Base Address*/
channel
=
(
port
&
0xC0
)
?
((
port
-
0xC0
)
>>
2
)
:
(
port
>>
1
);
dmachip
=
(
channel
<
4
)
?
0
:
1
;
if
(
!
DMA_Toggle
[
dmachip
])
res
=
DMA_CurrentBaseAddress
[
channel
]
&
0xFF
;
else
{
res
=
(
DMA_CurrentBaseAddress
[
channel
]
&
(
0xFF
<<
8
))
>>
8
;
TRACE
(
"Read Current Base Address = %lx
\n
"
,
DMA_CurrentBaseAddress
[
channel
]);
}
DMA_Toggle
[
dmachip
]
=
!
DMA_Toggle
[
dmachip
];
break
;
case
0x01
:
case
0x03
:
case
0x05
:
case
0x07
:
case
0xC2
:
case
0xC6
:
case
0xCA
:
case
0xCE
:
/* Count*/
channel
=
((
port
-
1
)
&
0xC0
)
?
(((
port
-
1
)
-
0xC0
)
>>
2
)
:
(
port
>>
1
);
dmachip
=
(
channel
<
4
)
?
0
:
1
;
if
(
!
DMA_Toggle
[
dmachip
])
res
=
DMA_CurrentByteCount
[
channel
]
&
0xFF
;
else
{
res
=
(
DMA_CurrentByteCount
[
channel
]
&
(
0xFF
<<
8
))
>>
8
;
TRACE
(
"Read Current Count = %x.
\n
"
,
DMA_CurrentByteCount
[
channel
]);
}
DMA_Toggle
[
dmachip
]
=
!
DMA_Toggle
[
dmachip
];
break
;
/* Low Page Base Address */
case
0x87
:
res
=
(
DMA_BaseAddress
[
0
]
&
(
0xFF
<<
16
))
>>
16
;
break
;
case
0x83
:
res
=
(
DMA_BaseAddress
[
1
]
&
(
0xFF
<<
16
))
>>
16
;
break
;
case
0x81
:
res
=
(
DMA_BaseAddress
[
2
]
&
(
0xFF
<<
16
))
>>
16
;
break
;
case
0x82
:
res
=
(
DMA_BaseAddress
[
3
]
&
(
0xFF
<<
16
))
>>
16
;
break
;
case
0x8B
:
res
=
(
DMA_BaseAddress
[
5
]
&
(
0xFF
<<
16
))
>>
16
;
break
;
case
0x89
:
res
=
(
DMA_BaseAddress
[
6
]
&
(
0xFF
<<
16
))
>>
16
;
break
;
case
0x8A
:
res
=
(
DMA_BaseAddress
[
7
]
&
(
0xFF
<<
16
))
>>
16
;
break
;
/* High Page Base Address */
case
0x487
:
res
=
(
DMA_BaseAddress
[
0
]
&
(
0xFF
<<
24
))
>>
24
;
break
;
case
0x483
:
res
=
(
DMA_BaseAddress
[
1
]
&
(
0xFF
<<
24
))
>>
24
;
break
;
case
0x481
:
res
=
(
DMA_BaseAddress
[
2
]
&
(
0xFF
<<
24
))
>>
24
;
break
;
case
0x482
:
res
=
(
DMA_BaseAddress
[
3
]
&
(
0xFF
<<
24
))
>>
24
;
break
;
case
0x48B
:
res
=
(
DMA_BaseAddress
[
5
]
&
(
0xFF
<<
24
))
>>
24
;
break
;
case
0x489
:
res
=
(
DMA_BaseAddress
[
6
]
&
(
0xFF
<<
24
))
>>
24
;
break
;
case
0x48A
:
res
=
(
DMA_BaseAddress
[
7
]
&
(
0xFF
<<
24
))
>>
24
;
break
;
case
0x08
:
case
0xD0
:
/* Status */
TRACE
(
"Status Register Read
\n
"
);
res
=
DMA_Status
[(
port
==
0x08
)
?
0
:
1
];
case
0x0D
:
case
0xDA
:
/* Temporary */
FIXME
(
"Temporary Register Read- Not Implemented
\n
"
);
break
;
}
return
res
;
}
dlls/winedos/dosexe.h
View file @
53268a54
...
...
@@ -72,6 +72,11 @@ extern int DOSDEV_Write(DWORD dev, DWORD buf, int buflen, int verify);
extern
int
DOSDEV_IoctlRead
(
DWORD
dev
,
DWORD
buf
,
int
buflen
);
extern
int
DOSDEV_IoctlWrite
(
DWORD
dev
,
DWORD
buf
,
int
buflen
);
/* dma.c */
extern
int
DMA_Transfer
(
int
channel
,
int
reqlength
,
void
*
buffer
);
extern
void
DMA_ioport_out
(
WORD
port
,
BYTE
val
);
extern
BYTE
DMA_ioport_in
(
WORD
port
);
/* int09.c */
extern
void
WINAPI
DOSVM_Int09Handler
(
CONTEXT86
*
);
extern
void
WINAPI
DOSVM_Int09SendScan
(
BYTE
scan
,
BYTE
ascii
);
...
...
@@ -113,6 +118,10 @@ extern void WINAPI DOSVM_Int33Console(MOUSE_EVENT_RECORD*);
extern
void
WINAPI
DOSVM_Int67Handler
(
CONTEXT86
*
);
extern
void
WINAPI
EMS_Ioctl_Handler
(
CONTEXT86
*
);
/* soundblaster.c */
extern
void
SB_ioport_out
(
WORD
port
,
BYTE
val
);
extern
BYTE
SB_ioport_in
(
WORD
port
);
/* xms.c */
extern
void
WINAPI
XMS_Handler
(
CONTEXT86
*
);
...
...
dlls/winedos/ioports.c
View file @
53268a54
...
...
@@ -36,10 +36,51 @@ BOOL WINAPI DOSVM_inport( int port, int size, DWORD *res )
case
0x60
:
*
res
=
DOSVM_Int09ReadScan
(
NULL
);
break
;
case
0x22a
:
case
0x22c
:
case
0x22e
:
*
res
=
(
DWORD
)
SB_ioport_in
(
port
);
break
;
case
0x3ba
:
case
0x3da
:
*
res
=
(
DWORD
)
VGA_ioport_in
(
port
);
break
;
case
0x00
:
case
0x01
:
case
0x02
:
case
0x03
:
case
0x04
:
case
0x05
:
case
0x06
:
case
0x07
:
case
0xC0
:
case
0xC2
:
case
0xC4
:
case
0xC6
:
case
0xC8
:
case
0xCA
:
case
0xCC
:
case
0xCE
:
case
0x87
:
case
0x83
:
case
0x81
:
case
0x82
:
case
0x8B
:
case
0x89
:
case
0x8A
:
case
0x487
:
case
0x483
:
case
0x481
:
case
0x482
:
case
0x48B
:
case
0x489
:
case
0x48A
:
case
0x08
:
case
0xD0
:
case
0x0D
:
case
0xDA
:
*
res
=
(
DWORD
)
DMA_ioport_in
(
port
);
break
;
default:
return
FALSE
;
/* not handled */
}
...
...
@@ -57,10 +98,62 @@ BOOL WINAPI DOSVM_outport( int port, int size, DWORD value )
case
0x20
:
DOSVM_PIC_ioport_out
(
port
,
(
BYTE
)
value
);
break
;
case
0x226
:
case
0x22c
:
SB_ioport_out
(
port
,
(
BYTE
)
value
);
break
;
case
0x3c8
:
case
0x3c9
:
VGA_ioport_out
(
port
,
(
BYTE
)
value
);
break
;
case
0x00
:
case
0x01
:
case
0x02
:
case
0x03
:
case
0x04
:
case
0x05
:
case
0x06
:
case
0x07
:
case
0xC0
:
case
0xC2
:
case
0xC4
:
case
0xC6
:
case
0xC8
:
case
0xCA
:
case
0xCC
:
case
0xCE
:
case
0x87
:
case
0x83
:
case
0x81
:
case
0x82
:
case
0x8B
:
case
0x89
:
case
0x8A
:
case
0x487
:
case
0x483
:
case
0x481
:
case
0x482
:
case
0x48B
:
case
0x489
:
case
0x48A
:
case
0x08
:
case
0xD0
:
case
0x0B
:
case
0xD6
:
case
0x0A
:
case
0xD4
:
case
0x0F
:
case
0xDE
:
case
0x09
:
case
0xD2
:
case
0x0C
:
case
0xD8
:
case
0x0D
:
case
0xDA
:
case
0x0E
:
case
0xDC
:
DMA_ioport_out
(
port
,
(
BYTE
)
value
);
break
;
default:
return
FALSE
;
/* not handled */
}
...
...
dlls/winedos/soundblaster.c
0 → 100644
View file @
53268a54
/*
* Soundblaster Emulation
*
* Copyright 2002 Christian Costa
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "windef.h"
#include "dosexe.h"
#include "wine/debug.h"
#include "dsound.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
sblaster
);
/* Board Configuration */
/* FIXME: Should be in a config file */
#define SB_IRQ 5
#define SB_IRQ_PRI 11
#define SB_DMA 1
/* Soundblaster state */
static
int
SampleMode
;
/* Mono / Stereo */
static
int
SampleRate
;
static
int
SamplesCount
;
static
BYTE
DSP_Command
[
256
];
/* Store param numbers in bytes for each command */
static
BYTE
DSP_InBuffer
[
10
];
/* Store DSP command bytes parameters from host */
static
int
InSize
;
/* Nb of bytes in InBuffer */
static
BYTE
DSP_OutBuffer
[
10
];
/* Store DSP information bytes to host */
static
int
OutSize
;
/* Nb of bytes in InBuffer */
static
int
command
;
/* Current command */
static
int
end_sound_loop
=
0
;
static
int
dma_enable
=
0
;
/* The maximum size of a dma transfer can be 65536 */
#define DMATRFSIZE 1024
/* DMA can perform 8 or 16-bit transfer */
static
BYTE
dma_buffer
[
DMATRFSIZE
*
2
];
/* Direct Sound buffer config */
#define DSBUFLEN 4096
/* FIXME: Only this value seems to work */
/* Direct Sound playback stuff */
static
HMODULE
hmodule
;
typedef
HRESULT
(
WINAPI
*
fnDirectSoundCreate
)
(
LPGUID
,
LPDIRECTSOUND
*
,
LPUNKNOWN
);
fnDirectSoundCreate
lpDirectSoundCreate
;
static
LPDIRECTSOUND
lpdsound
;
static
LPDIRECTSOUNDBUFFER
lpdsbuf
;
static
DSBUFFERDESC
buf_desc
;
static
WAVEFORMATEX
wav_fmt
;
static
HANDLE
SB_Thread
;
static
UINT
buf_off
;
extern
HWND
vga_hwnd
;
/* SB_Poll performs DMA transfers and fills the Direct Sound Buffer */
static
DWORD
CALLBACK
SB_Poll
(
void
*
dummy
)
{
HRESULT
result
;
LPBYTE
lpbuf1
=
NULL
;
LPBYTE
lpbuf2
=
NULL
;
DWORD
dwsize1
=
0
;
DWORD
dwsize2
=
0
;
DWORD
dwbyteswritten1
=
0
;
DWORD
dwbyteswritten2
=
0
;
int
size
;
/* FIXME: this loop must be improved */
while
(
!
end_sound_loop
)
{
Sleep
(
10
);
if
(
dma_enable
)
{
size
=
DMA_Transfer
(
SB_DMA
,
min
(
DMATRFSIZE
,
SamplesCount
),
dma_buffer
);
}
else
continue
;
result
=
IDirectSoundBuffer_Lock
(
lpdsbuf
,
buf_off
,
size
,
&
lpbuf1
,
&
dwsize1
,
&
lpbuf2
,
&
dwsize2
,
0
);
if
(
result
!=
DS_OK
)
{
ERR
(
"Unable to lock sound buffer !
\n
"
);
continue
;
}
dwbyteswritten1
=
min
(
size
,
dwsize1
);
memcpy
(
lpbuf1
,
dma_buffer
,
dwbyteswritten1
);
if
(
size
>
dwsize1
)
{
dwbyteswritten2
=
min
(
size
-
dwbyteswritten1
,
dwsize2
);
memcpy
(
lpbuf2
,
dma_buffer
+
dwbyteswritten1
,
dwbyteswritten2
);
}
buf_off
=
(
buf_off
+
dwbyteswritten1
+
dwbyteswritten2
)
%
DSBUFLEN
;
result
=
IDirectSoundBuffer_Unlock
(
lpdsbuf
,
lpbuf1
,
dwbyteswritten1
,
lpbuf2
,
dwbyteswritten2
);
if
(
result
!=
DS_OK
)
ERR
(
"Unable to unlock sound buffer !
\n
"
);
SamplesCount
-=
size
;
if
(
!
SamplesCount
)
{
DOSVM_QueueEvent
(
SB_IRQ
,
SB_IRQ_PRI
,
NULL
,
NULL
);
dma_enable
=
0
;
}
}
return
0
;
}
BOOL
SB_Init
()
{
HRESULT
result
;
if
(
!
lpdsound
)
{
hmodule
=
LoadLibraryA
(
"dsound.dll"
);
if
(
!
hmodule
)
{
ERR
(
"Can't load dsound.dll !
\n
"
);
return
0
;
}
lpDirectSoundCreate
=
(
fnDirectSoundCreate
)
GetProcAddress
(
hmodule
,
"DirectSoundCreate"
);
if
(
!
lpDirectSoundCreate
)
{
/* CloseHandle(hmodule); */
ERR
(
"Can't find DirectSoundCreate function !
\n
"
);
return
0
;
}
result
=
(
*
lpDirectSoundCreate
)(
NULL
,
&
lpdsound
,
NULL
);
if
(
result
!=
DS_OK
)
{
ERR
(
"Unable to initialize Sound Subsystem err = %lx !
\n
"
,
result
);
return
0
;
}
/* FIXME: To uncomment when :
- SetCooperative level is correctly implemented
- an always valid and non changing handle to a windows (vga_hwnd) is available
(this surely needs some work in vga.c)
result = IDirectSound_SetCooperativeLevel(lpdsound,vga_hwnd,DSSCL_EXCLUSIVE|DSSCL_PRIORITY);
if (result != DS_OK) {
ERR("Can't set cooperative level !\n");
return 0;
}
*/
/* Default format */
wav_fmt
.
wFormatTag
=
WAVE_FORMAT_PCM
;
wav_fmt
.
nChannels
=
1
;
wav_fmt
.
nSamplesPerSec
=
22050
;
wav_fmt
.
nAvgBytesPerSec
=
22050
;
wav_fmt
.
nBlockAlign
=
1
;
wav_fmt
.
wBitsPerSample
=
8
;
wav_fmt
.
cbSize
=
0
;
memset
(
&
buf_desc
,
0
,
sizeof
(
DSBUFFERDESC
));
buf_desc
.
dwSize
=
sizeof
(
DSBUFFERDESC
);
buf_desc
.
dwBufferBytes
=
DSBUFLEN
;
buf_desc
.
lpwfxFormat
=
&
wav_fmt
;
result
=
IDirectSound_CreateSoundBuffer
(
lpdsound
,
&
buf_desc
,
&
lpdsbuf
,
NULL
);
if
(
result
!=
DS_OK
)
{
ERR
(
"Can't create sound buffer !
\n
"
);
return
0
;
}
result
=
IDirectSoundBuffer_Play
(
lpdsbuf
,
0
,
0
,
DSBPLAY_LOOPING
);
if
(
result
!=
DS_OK
)
{
ERR
(
"Can't start playing !
\n
"
);
return
0
;
}
buf_off
=
0
;
end_sound_loop
=
0
;
SB_Thread
=
CreateThread
(
NULL
,
0
,
SB_Poll
,
NULL
,
0
,
NULL
);
TRACE
(
"thread
\n
"
);
if
(
!
SB_Thread
)
{
ERR
(
"Can't create thread !
\n
"
);
return
0
;
}
}
return
1
;
}
void
SB_Reset
()
{
int
i
;
for
(
i
=
0
;
i
<
256
;
i
++
)
DSP_Command
[
i
]
=
0
;
/* Set Time Constant */
DSP_Command
[
0x40
]
=
1
;
/* Generate IRQ */
DSP_Command
[
0xF2
]
=
0
;
/* DMA DAC 8-bits */
DSP_Command
[
0x14
]
=
2
;
/* Generic DAC/ADC DMA (16-bit, 8-bit) */
for
(
i
=
0xB0
;
i
<=
0xCF
;
i
++
)
DSP_Command
[
i
]
=
3
;
/* DSP Indentification */
DSP_Command
[
0xE0
]
=
1
;
/* Clear command and input buffer */
command
=
-
1
;
InSize
=
0
;
/* Put a garbage value in the output buffer */
OutSize
=
1
;
if
(
SB_Init
())
/* All right, let's put the magic value for autodetection */
DSP_OutBuffer
[
0
]
=
0xaa
;
else
/* Something is wrong, put 0 to failed audetection */
DSP_OutBuffer
[
0
]
=
0x00
;
}
/* Find a standard sampling rate for DirectSound */
int
SB_StdSampleRate
(
int
SampleRate
)
{
if
(
SampleRate
>
((
44100
+
48000
)
/
2
))
return
48000
;
if
(
SampleRate
>
((
32000
+
44100
)
/
2
))
return
44100
;
if
(
SampleRate
>
((
24000
+
32000
)
/
2
))
return
32000
;
if
(
SampleRate
>
((
22050
+
24000
)
/
2
))
return
24000
;
if
(
SampleRate
>
((
16000
+
22050
)
/
2
))
return
22050
;
if
(
SampleRate
>
((
12000
+
16000
)
/
2
))
return
16000
;
if
(
SampleRate
>
((
11025
+
12000
)
/
2
))
return
12000
;
if
(
SampleRate
>
((
8000
+
11025
)
/
2
))
return
11025
;
return
8000
;
}
void
SB_ioport_out
(
WORD
port
,
BYTE
val
)
{
switch
(
port
)
{
/* DSP - Reset */
case
0x226
:
TRACE
(
"Resetting DSP.
\n
"
);
SB_Reset
();
break
;
/* DSP - Write Data or Command */
case
0x22c
:
TRACE
(
"val=%x
\n
"
,
val
);
if
(
command
==
-
1
)
{
/* Clear input buffer and set the current command */
command
=
val
;
InSize
=
0
;
}
if
(
InSize
!=
DSP_Command
[
command
])
/* Fill the input buffer the command parameters if any */
DSP_InBuffer
[
InSize
++
]
=
val
;
else
{
/* Process command */
switch
(
command
)
{
case
0x10
:
/* SB */
FIXME
(
"Direct DAC (8-bit) - Not Implemented
\n
"
);
break
;
case
0x14
:
/* SB */
SamplesCount
=
DSP_InBuffer
[
1
]
+
(
val
<<
8
)
+
1
;
TRACE
(
"DMA DAC (8-bit) for %x samples
\n
"
,
SamplesCount
);
dma_enable
=
1
;
break
;
case
0x20
:
FIXME
(
"Direct ADC (8-bit) - Not Implemented
\n
"
);
break
;
case
0x24
:
/* SB */
FIXME
(
"DMA ADC (8-bit) - Not Implemented
\n
"
);
break
;
case
0x40
:
/* SB */
SampleRate
=
1000000
/
(
256
-
val
);
TRACE
(
"Set Time Constant (%d <-> %d Hz => %d Hz)
\n
"
,
DSP_InBuffer
[
0
],
SampleRate
,
SB_StdSampleRate
(
SampleRate
));
SampleRate
=
SB_StdSampleRate
(
SampleRate
);
wav_fmt
.
nSamplesPerSec
=
SampleRate
;
wav_fmt
.
nAvgBytesPerSec
=
SampleRate
;
IDirectSoundBuffer_SetFormat
(
lpdsbuf
,
&
wav_fmt
);
break
;
/* case 0xBX/0xCX -> See below */
case
0xD0
:
/* SB */
TRACE
(
"Halt DMA operation (8-bit)
\n
"
);
dma_enable
=
0
;
break
;
case
0xD1
:
/* SB */
FIXME
(
"Enable Speaker - Not Implemented
\n
"
);
break
;
case
0xD3
:
/* SB */
FIXME
(
"Disable Speaker - Not Implemented
\n
"
);
break
;
case
0xD4
:
/* SB */
FIXME
(
"Continue DMA operation (8-bit) - Not Implemented
\n
"
);
break
;
case
0xD8
:
/* SB */
FIXME
(
"Speaker Status - Not Implemented
\n
"
);
break
;
case
0xE0
:
/* SB 2.0 */
TRACE
(
"DSP Identification
\n
"
);
DSP_OutBuffer
[
OutSize
++
]
=
~
val
;
break
;
case
0xE1
:
/* SB */
FIXME
(
"DSP Version - Not Implemented
\n
"
);
break
;
case
0xF2
:
/* SB */
TRACE
(
"IRQ Request (8-bit)
\n
"
);
DOSVM_QueueEvent
(
SB_IRQ
,
SB_IRQ_PRI
,
NULL
,
NULL
);
break
;
default:
if
(((
command
&
0xF0
)
==
0xB0
)
||
((
DSP_InBuffer
[
0
]
&
0xF0
)
==
0xC0
))
{
/* SB16 */
FIXME
(
"Generic DAC/ADC DMA (16-bit, 8-bit) - %d % d
\n
"
,
command
,
DSP_InBuffer
[
1
]);
if
(
command
&
0x02
)
FIXME
(
"Generic DAC/ADC fifo mode not supported
\n
"
);
if
(
command
&
0x04
)
FIXME
(
"Generic DAC/ADC autoinit dma mode not supported
\n
"
);
if
(
command
&
0x08
)
FIXME
(
"Generic DAC/ADC adc mode not supported
\n
"
);
switch
(
command
>>
4
)
{
case
0xB
:
FIXME
(
"Generic DAC/ADC 8-bit not supported
\n
"
);
SampleMode
=
0
;
break
;
case
0xC
:
FIXME
(
"Generic DAC/ADC 16-bit not supported
\n
"
);
SampleMode
=
1
;
break
;
default:
ERR
(
"Generic DAC/ADC resolution unknown
\n
"
);
break
;
}
if
(
DSP_InBuffer
[
1
]
&
0x010
)
FIXME
(
"Generic DAC/ADC signed sample mode not supported
\n
"
);
if
(
DSP_InBuffer
[
1
]
&
0x020
)
FIXME
(
"Generic DAC/ADC stereo mode not supported
\n
"
);
SamplesCount
=
DSP_InBuffer
[
2
]
+
(
val
<<
8
)
+
1
;
TRACE
(
"Generic DMA for %x samples
\n
"
,
SamplesCount
);
dma_enable
=
1
;
}
else
FIXME
(
"DSP command %x not supported
\n
"
,
val
);
}
/* Empty the input buffer and end the command */
InSize
=
0
;
command
=
-
1
;
}
}
}
BYTE
SB_ioport_in
(
WORD
port
)
{
BYTE
res
=
0
;
switch
(
port
)
{
/* DSP Read Data */
case
0x22a
:
/* Value in the read buffer */
if
(
OutSize
)
res
=
DSP_OutBuffer
[
--
OutSize
];
else
/* return the last byte */
res
=
DSP_OutBuffer
[
0
];
break
;
/* DSP - Write Buffer Status */
case
0x22c
:
/* DSP always ready for writing */
res
=
0x00
;
break
;
/* DSP - Data Available Status */
/* DSP - IRQ Acknowledge, 8-bit */
case
0x22e
:
/* DSP data availability check */
if
(
OutSize
)
res
=
0x80
;
else
res
=
0x00
;
break
;
}
return
res
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment