Skip to content

Commit bae439f

Browse files
committed
[fw-isoldr] Expand the mini-kos library.
Added a bit modified dmac, regfield, math and some timer stubs.
1 parent 0963cb3 commit bae439f

File tree

7 files changed

+564
-0
lines changed

7 files changed

+564
-0
lines changed
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
/* KallistiOS ##version##
2+
3+
dmac.h
4+
Copyright (C) 2024 Paul Cercueil
5+
6+
*/
7+
8+
/** \file arch/dmac.h
9+
\brief SH4 DMA Controller API
10+
\ingroup system_dmac
11+
12+
This header provies an API to use the DMA controller of the SH4.
13+
14+
\author Paul Cercueil
15+
*/
16+
17+
#ifndef __ARCH_DMAC_H
18+
#define __ARCH_DMAC_H
19+
20+
#include <sys/cdefs.h>
21+
__BEGIN_DECLS
22+
23+
#include <stdint.h>
24+
25+
/** \defgroup dmac DMA Controller API
26+
\brief API to use the SH4's DMA Controller
27+
\ingroup system
28+
29+
This API can be used to program DMA transfers from memory to memory,
30+
from hardware to memory or from memory to hardware.
31+
32+
@{
33+
*/
34+
35+
/** \brief DMA callback type.
36+
\ingroup dmac
37+
38+
Function type for DMA callbacks.
39+
Those registered callbacks will be called when a DMA transfer completes.
40+
They will be called in an interrupt context, so don't try anything funny.
41+
*/
42+
typedef void (*dma_callback_t)(void *data);
43+
44+
/** \brief DMA channel enum.
45+
\ingroup dmac
46+
47+
Represents one of the 4 DMA channels available on the SH4.
48+
*/
49+
typedef enum dma_channel {
50+
DMA_CHANNEL_0, /**< Channel #0: On Dreamcast, reserved for hardware. */
51+
DMA_CHANNEL_1, /**< Channel #1: External, hardware or mem-to-mem requests. */
52+
DMA_CHANNEL_2, /**< Channel #2: on Dreamcast, reserved for PVR use. */
53+
DMA_CHANNEL_3, /**< Channel #3: mem-to-mem requests only. */
54+
} dma_channel_t;
55+
56+
/** \brief DMA request.
57+
\ingroup dmac
58+
59+
List of the possible DMA requests.
60+
61+
"Auto" requests are started as soon as the DMA transfer is programmed to
62+
the DMA controller. On the other hand, SCI/SCIF/TMU2 requests are only
63+
started when the given hardware event occurs.
64+
65+
"External" requests are controlled by external pins of the SH4 CPU. These
66+
can be wired to other parts of the mother board.
67+
*/
68+
typedef enum dma_request {
69+
DMA_REQUEST_EXTERNAL_MEM_TO_MEM = 0,
70+
DMA_REQUEST_EXTERNAL_MEM_TO_DEV = 2,
71+
DMA_REQUEST_EXTERNAL_DEV_TO_MEM = 3,
72+
DMA_REQUEST_AUTO_MEM_TO_MEM = 4,
73+
DMA_REQUEST_AUTO_MEM_TO_DEV = 5,
74+
DMA_REQUEST_AUTO_DEV_TO_MEM = 6,
75+
76+
DMA_REQUEST_SCI_TRANSMIT = 8,
77+
DMA_REQUEST_SCI_RECEIVE = 9,
78+
DMA_REQUEST_SCIF_TRANSMIT = 10,
79+
DMA_REQUEST_SCIF_RECEIVE = 11,
80+
DMA_REQUEST_TMU2_MEM_TO_MEM = 12,
81+
DMA_REQUEST_TMU2_MEM_TO_DEV = 13,
82+
DMA_REQUEST_TMU2_DEV_TO_MEM = 14,
83+
} dma_request_t;
84+
85+
/** \brief DMA unit size.
86+
\ingroup dmac
87+
88+
The unit size controls the granularity at which the DMA will transfer data.
89+
For instance, copying data to a 16-bit bus will require a 16-bit unit size.
90+
91+
For memory-to-memory transfers, it is recommended to use 32-byte transfers
92+
for the maximum speed.
93+
*/
94+
typedef enum dma_unitsize {
95+
DMA_UNITSIZE_64BIT,
96+
DMA_UNITSIZE_8BIT,
97+
DMA_UNITSIZE_16BIT,
98+
DMA_UNITSIZE_32BIT,
99+
DMA_UNITSIZE_32BYTE,
100+
} dma_unitsize_t;
101+
102+
/** \brief DMA address mode.
103+
\ingroup dmac
104+
105+
The "address mode" specifies how the source or destination address of a DMA
106+
transfer is modified as the transfer goes on. It is only valid when the DMA
107+
transfer is configured as pointing to memory for that source or destination.
108+
*/
109+
typedef enum dma_addrmode {
110+
DMA_ADDRMODE_FIXED, /**< The source/destination address is not modified. */
111+
DMA_ADDRMODE_INCREMENT, /**< The source/destination address is incremented. */
112+
DMA_ADDRMODE_DECREMENT, /**< The source/destination address is decremented. */
113+
} dma_addrmode_t;
114+
115+
/** \brief DMA transmit mode.
116+
\ingroup dmac
117+
118+
In "Cycle steal" mode, the DMA controller will release the bus at the end of
119+
each transfer unit (configured by the unit size). This allows the CPU to
120+
access the bus if it needs to.
121+
122+
In "Burst" mode, the DMA controller will hold the bus until the DMA transfer
123+
completes.
124+
*/
125+
typedef enum dma_transmitmode {
126+
DMA_TRANSMITMODE_CYCLE_STEAL,
127+
DMA_TRANSMITMODE_BURST,
128+
} dma_transmitmode_t;
129+
130+
/** \brief DMA transfer configuration.
131+
\ingroup dmac
132+
133+
This structure represents the configuration used for a given DMA channel.
134+
*/
135+
typedef struct dma_config {
136+
dma_channel_t channel; /**< DMA channel used for the transfer. */
137+
dma_request_t request; /**< DMA request type. */
138+
dma_unitsize_t unit_size; /**< Unit size used for the DMA transfer. */
139+
dma_addrmode_t src_mode, dst_mode; /**< Source/destination address mode. */
140+
dma_transmitmode_t transmit_mode; /**< DMA Transfer transmit mode. */
141+
dma_callback_t callback; /**< Optional callback function for
142+
end-of-transfer notification. */
143+
} dma_config_t;
144+
145+
/** \brief DMA address.
146+
\ingroup dmac
147+
148+
This type represents an address that can be used for DMA transfers.
149+
*/
150+
typedef uint32_t dma_addr_t;
151+
152+
/** \brief Convert a hardware address to a DMA address.
153+
\ingroup dmac
154+
155+
This function will convert a hardware address (pointing to a device's FIFO,
156+
or to one of the various mapped memories) to an address suitable for use
157+
with the DMA controller.
158+
159+
\param hw_addr The hardware address.
160+
\return The converted DMA address.
161+
*/
162+
dma_addr_t hw_to_dma_addr(uintptr_t hw_addr);
163+
164+
/** \brief Prepare a source memory buffer for a DMA transfer.
165+
\ingroup dmac
166+
167+
This function will flush the data cache for the memory area covered by the
168+
buffer to ensure memory coherency, and return an address suitable for use
169+
with the DMA controller.
170+
171+
\param ptr A pointer to the source buffer.
172+
\param len The size in bytes of the source buffer.
173+
\return The converted DMA address.
174+
175+
\sa dma_map_dst()
176+
*/
177+
dma_addr_t dma_map_src(const void *ptr, size_t len);
178+
179+
/** \brief Prepare a destination memory buffer for a DMA transfer.
180+
\ingroup dmac
181+
182+
This function will invalidate the data cache for the memory area covered by
183+
the buffer to ensure memory coherency, and return an address suitable for
184+
use with the DMA controller.
185+
186+
\param ptr A pointer to the destination buffer.
187+
\param len The size in bytes of the destination buffer.
188+
\return The converted DMA address.
189+
190+
\sa dma_map_src()
191+
*/
192+
dma_addr_t dma_map_dst(void *ptr, size_t len);
193+
194+
/** \brief Program a DMA transfer.
195+
\ingroup dmac
196+
197+
This function will program a DMA transfer using the specified configuration,
198+
source/destination addresses and transfer length.
199+
200+
It will return as soon as the DMA transfer is programmed, which means that
201+
it will not work for the DMA transfer to complete before returning.
202+
203+
\param cfg A pointer to the configuration structure.
204+
\param dst The destination address, if targetting memory;
205+
can be 0 otherwise.
206+
\param src The source address, if targetting memory;
207+
can be 0 otherwise.
208+
\param len The size in bytes of the DMA transfer.
209+
\param cb_data The parameter that will be passed to the
210+
end-of-transfer callback, if a callback has been
211+
specified in the configuration structure.
212+
\retval 0 On success.
213+
\retval -1 On error.
214+
215+
\sa dma_wait_complete()
216+
*/
217+
int dma_transfer(const dma_config_t *cfg, dma_addr_t dst, dma_addr_t src,
218+
size_t len, void *cb_data);
219+
220+
/** \brief Wait for a DMA transfer to complete
221+
\ingroup dmac
222+
223+
This function will block until any previously programmed DMA transfer for
224+
the given DMA channel has completed.
225+
226+
\param channel The DMA channel to wait for.
227+
*/
228+
void dma_wait_complete(dma_channel_t channel);
229+
230+
/** \brief Get the remaining size of a DMA transfer
231+
\ingroup dmac
232+
233+
This function will return the number of bytes remaining to transfer, if a
234+
transfer was previously programmed.
235+
236+
\param channel The DMA channel to wait for.
237+
\return The number of bytes remaining to transfer, or zero
238+
if the previous transfer completed.
239+
*/
240+
size_t dma_transfer_get_remaining(dma_channel_t channel);
241+
242+
/** @} */
243+
244+
__END_DECLS
245+
246+
#endif /* __ARCH_DMAC_H */

firmware/isoldr/loader/kos/arch/timer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ void timer_spin_sleep(int ms);
139139
/* Spin-loop kernel sleep func: uses the first timer in the
140140
SH-4 to very accurately delay even when interrupts are disabled */
141141
void timer_spin_sleep_bios(int ms);
142+
#define thd_sleep timer_spin_sleep_bios
143+
144+
/* Not accurate, but it's a hack to get a delay function */
145+
void timer_spin_delay_ns(uint32 ns);
142146

143147
/** \brief Enable high-priority timer interrupts.
144148
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* KallistiOS ##version##
2+
3+
dc/math.h
4+
Copyright (C) 2023 Paul Cercueil
5+
Copyright (C) 2025 Ruslan Rostovtsev
6+
*/
7+
8+
/**
9+
\file dc/math.h
10+
\brief Prototypes for optimized math functions written in ASM
11+
\ingroup math_general
12+
13+
\author Paul Cercueil
14+
*/
15+
16+
#ifndef __DC_MATH_H
17+
#define __DC_MATH_H
18+
19+
#include <sys/cdefs.h>
20+
__BEGIN_DECLS
21+
22+
/** \defgroup math_general General
23+
\brief Optimized general-purpose math utilities
24+
\ingroup math
25+
@{
26+
*/
27+
28+
/**
29+
\brief Returns the bit-reverse of a 32-bit value (where MSB
30+
becomes LSB and vice-versa).
31+
32+
\return the bit-reverse value of the argument.
33+
*/
34+
unsigned int bit_reverse(unsigned int value);
35+
36+
/**
37+
\brief Returns the bit-reverse of an 8-bit value (where MSB
38+
becomes LSB and vice-versa).
39+
40+
\return the bit-reverse value of the argument.
41+
*/
42+
unsigned char bit_reverse8(unsigned char value);
43+
44+
/** @} */
45+
46+
__END_DECLS
47+
48+
#endif /* __DC_MATH_H */
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* KallistiOS ##version##
2+
3+
kos/compiler.h
4+
Copyright (C) 2024 Paul Cercueil
5+
6+
Macros to extract / insert bit fields
7+
*/
8+
9+
/** \file kos/regfield.h
10+
\brief Macros to help dealing with register fields.
11+
\ingroup kernel
12+
13+
\author Paul Cercueil
14+
*/
15+
16+
#ifndef __KOS_REGFIELD_H
17+
#define __KOS_REGFIELD_H
18+
19+
#include <sys/cdefs.h>
20+
__BEGIN_DECLS
21+
22+
/** \brief Create a mask with a bit set
23+
24+
\param bit The bit to set (from 0 to 31)
25+
\return A 32-bit mask with the corresponding bit set
26+
*/
27+
#define BIT(bit) (1u << (bit))
28+
29+
/** \brief Create a mask with a range of bits set
30+
31+
\param h The high bit of the range to set, included
32+
\param l The low bit of the range to set, included
33+
\return A 32-bit mask with the corresponding bits set
34+
*/
35+
#define GENMASK(h, l) ((0xffffffff << (l)) & (0xffffffff >> (31 - (h))))
36+
37+
/** \brief Extract a field value from a variable
38+
39+
\param var The 32-bit variable containing the field
40+
\param field A 32-bit mask that corresponds to the field
41+
\return The value of the field (shifted)
42+
*/
43+
#define FIELD_GET(var, field) \
44+
(((var) & (field)) >> __builtin_ctz(field))
45+
46+
/** \brief Prepare a field with a given value
47+
48+
\param field A 32-bit mask that corresponds to the field
49+
\param value The value to be put in the field
50+
*/
51+
#define FIELD_PREP(field, value) \
52+
(((value) << __builtin_ctz(field)) & (field))
53+
54+
__END_DECLS
55+
#endif /* __KOS_REGFIELD_H */

0 commit comments

Comments
 (0)