2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY, without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
22 #define DMA_0_ADDR 0x00
23 #define DMA_0_COUNT 0x01
24 #define DMA_1_ADDR 0x02
25 #define DMA_1_COUNT 0x03
26 #define DMA_2_ADDR 0x04
27 #define DMA_2_COUNT 0x05
28 #define DMA_3_ADDR 0x06
29 #define DMA_3_COUNT 0x07
31 #define DMA_4_ADDR 0xc0
32 #define DMA_4_COUNT 0xc2
33 #define DMA_5_ADDR 0xc4
34 #define DMA_5_COUNT 0xc6
35 #define DMA_6_ADDR 0xc8
36 #define DMA_6_COUNT 0xca
37 #define DMA_7_ADDR 0xcc
38 #define DMA_7_COUNT 0xce
41 ((c < 4) ? DMA_0_ADDR + ((c) << 1) : (DMA_4_ADDR + ((c) << 2)))
42 #define DMA_COUNT(c) \
43 ((c < 4) ? DMA_0_COUNT + ((c) << 1) : (DMA_4_COUNT + ((c) << 2)))
45 #define DMA8_MASK 0x0a
46 #define DMA8_MODE 0x0b
47 #define DMA8_CLR_FLIPFLOP 0x0c
48 #define DMA8_RESET 0x0d
49 #define DMA8_MASK_RST 0x0e
50 #define DMA8_RMASK 0x0f
51 #define DMA16_MASK 0xd4
52 #define DMA16_MODE 0xd6
53 #define DMA16_CLR_FLIPFLOP 0xd8
54 #define DMA16_RESET 0xda
55 #define DMA16_MASK_RST 0xdc
56 #define DMA16_RMASK 0xde
58 #define DMA_MASK(c) ((c) < 4 ? DMA8_MASK : DMA16_MASK)
59 #define DMA_MODE(c) ((c) < 4 ? DMA8_MODE : DMA16_MODE)
60 #define DMA_CLR_FLIPFLOP(c) ((c) < 4 ? DMA8_CLR_FLIPFLOP : DMA16_CLR_FLIPFLOP)
61 #define DMA_RESET(c) ((c) < 4 ? DMA8_RESET : DMA16_RESET)
62 #define DMA_MASK_RST(c) ((c) < 4 ? DMA8_MASK_RST : DMA16_MASK_RST)
63 #define DMA_RMASK(c) ((c) < 4 ? DMA8_RMASK : DMA16_RMASK)
65 #define DMA_0_PAGE 0x87
66 #define DMA_1_PAGE 0x83
67 #define DMA_2_PAGE 0x81
68 #define DMA_3_PAGE 0x82
69 #define DMA_4_PAGE 0x8f
70 #define DMA_5_PAGE 0x8b
71 #define DMA_6_PAGE 0x89
72 #define DMA_7_PAGE 0x8a
74 #define MODE_CHAN(x) ((x) & 3)
75 #define MODE_WRITE 0x04
76 #define MODE_READ 0x08
77 #define MODE_AUTO 0x10
78 #define MODE_DECR 0x20
79 #define MODE_SINGLE 0x40
80 #define MODE_BLOCK 0x80
81 #define MODE_CASCADE 0xc0
83 #define MASK_CHAN(x) ((x) & 3)
84 #define MASK_DISABLE 0x04
86 #define RMASK_CHAN(x) (1 << ((x) & 3))
88 #define IS_16BIT(c) ((c) >= 4)
90 static void dma_io(int chan, uint32_t phyaddr, int size, unsigned int flags, unsigned int dir);
91 static inline void mask(int chan);
92 static inline void unmask(int chan);
94 static int page_port[] = {
95 DMA_0_PAGE, DMA_1_PAGE, DMA_2_PAGE, DMA_3_PAGE,
96 DMA_4_PAGE, DMA_5_PAGE, DMA_6_PAGE, DMA_7_PAGE
99 void dma_out(int chan, uint32_t phyaddr, int size, unsigned int flags)
101 dma_io(chan, phyaddr, size, flags, MODE_READ);
104 void dma_in(int chan, uint32_t phyaddr, int size, unsigned int flags)
106 dma_io(chan, phyaddr, size, flags, MODE_WRITE);
109 static void dma_io(int chan, uint32_t phyaddr, int size, unsigned int flags, unsigned int dir)
112 int addr_port, count_port;
114 addr_port = DMA_ADDR(chan);
115 count_port = DMA_COUNT(chan);
118 outb(0, DMA_CLR_FLIPFLOP(chan));
120 /* first 2 bits of flags correspond to the mode bits 6,7 */
121 mode = ((flags & 3) << 6) | dir | MODE_CHAN(chan);
122 if(flags & DMA_DECR) mode |= MODE_DECR;
123 if(flags & DMA_AUTO) mode |= MODE_AUTO;
124 outb(mode, DMA_MODE(chan));
131 outb(phyaddr & 0xff, addr_port);
132 outb((phyaddr >> 8) & 0xff, addr_port);
133 outb((phyaddr >> 16) & 0xff, page_port[chan]);
136 outb(size & 0xff, count_port);
137 outb((size >> 8) & 0xff, count_port);
142 static inline void mask(int chan)
144 outb(MASK_CHAN(chan) | MASK_DISABLE, DMA_MASK(chan));
147 static inline void unmask(int chan)
149 outb(MASK_CHAN(chan), DMA_MASK(chan));