PCem
view src/piix.c @ 140:3bf6c44c8166
Restricted PIIX PCI config registers. Windows 98 no longer forces drives into compatibility mode.
| author | TomW |
|---|---|
| date | Thu Jul 31 18:23:40 2014 +0100 |
| parents | 7dbba9693027 |
| children | d0d530adce12 |
line source
1 /*PRD format :
3 word 0 - base address
4 word 1 - bits 1 - 15 = byte count, bit 31 = end of transfer
5 */
6 #include <string.h>
8 #include "ibm.h"
9 #include "ide.h"
10 #include "io.h"
11 #include "pci.h"
13 #include "piix.h"
15 uint8_t piix_bus_master_read(uint16_t port, void *priv);
16 void piix_bus_master_write(uint16_t port, uint8_t val, void *priv);
18 static uint8_t card_piix[256], card_piix_ide[256];
20 void piix_write(int func, int addr, uint8_t val, void *priv)
21 {
22 // pclog("piix_write: func=%d addr=%02x val=%02x %04x:%08x\n", func, addr, val, CS, pc);
23 if (func > 1)
24 return;
26 if (func == 1) /*IDE*/
27 {
28 switch (addr)
29 {
30 case 0x04:
31 card_piix_ide[0x04] = (card_piix_ide[0x04] & ~1) | (val & 1);
32 break;
33 case 0x07:
34 card_piix_ide[0x07] = (card_piix_ide[0x07] & ~0x38) | (val & 0x38);
35 break;
36 case 0x0d:
37 card_piix_ide[0x0d] = val;
38 break;
40 case 0x20:
41 card_piix_ide[0x20] = (val & ~0x0f) | 1;
42 break;
43 case 0x21:
44 card_piix_ide[0x21] = val;
45 break;
47 case 0x40:
48 card_piix_ide[0x40] = val;
49 break;
50 case 0x41:
51 if ((val ^ card_piix_ide[0x41]) & 0x80)
52 {
53 ide_pri_disable();
54 if (val & 0x80)
55 ide_pri_enable();
56 }
57 card_piix_ide[0x41] = val;
58 break;
59 case 0x42:
60 card_piix_ide[0x42] = val;
61 break;
62 case 0x43:
63 if ((val ^ card_piix_ide[0x43]) & 0x80)
64 {
65 ide_sec_disable();
66 if (val & 0x80)
67 ide_sec_enable();
68 }
69 card_piix_ide[0x43] = val;
70 break;
71 }
72 if ((addr & ~3) == 0x20) /*Bus master base address*/
73 {
74 uint16_t base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8);
75 io_removehandler(0, 0x10000, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL);
76 io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL);
77 }
78 // pclog("PIIX write %02X %02X\n", addr, val);
79 }
80 else
81 {
82 switch (addr)
83 {
84 case 0x00: case 0x01: case 0x02: case 0x03:
85 case 0x08: case 0x09: case 0x0a: case 0x0b:
86 case 0x0e:
87 return;
88 }
89 card_piix[addr] = val;
90 }
91 }
93 uint8_t piix_read(int func, int addr, void *priv)
94 {
95 // pclog("piix_read: func=%d addr=%02x %04x:%08x\n", func, addr, CS, pc);
96 if (func > 1)
97 return 0xff;
99 if (func == 1) /*IDE*/
100 {
101 // pclog("PIIX IDE read %02X %02X\n", addr, card_piix_ide[addr]);
102 return card_piix_ide[addr];
103 }
104 else
105 return card_piix[addr];
106 }
108 struct
109 {
110 uint8_t command;
111 uint8_t status;
112 uint32_t ptr, ptr_cur;
113 int count;
114 uint32_t addr;
115 int eot;
116 } piix_busmaster[2];
118 static void piix_bus_master_next_addr(int channel)
119 {
120 piix_busmaster[channel].addr = (*(unsigned long *)(&ram[piix_busmaster[channel].ptr_cur])) & ~1;
121 piix_busmaster[channel].count = (*(unsigned long *)(&ram[piix_busmaster[channel].ptr_cur + 4])) & 0xfffe;
122 piix_busmaster[channel].eot = (*(unsigned long *)(&ram[piix_busmaster[channel].ptr_cur + 4])) >> 31;
123 piix_busmaster[channel].ptr_cur += 8;
124 // pclog("New DMA settings on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot);
125 }
127 void piix_bus_master_write(uint16_t port, uint8_t val, void *priv)
128 {
129 int channel = (port & 8) ? 1 : 0;
130 // pclog("PIIX Bus Master write %04X %02X %04x:%08x\n", port, val, CS, pc);
131 switch (port & 7)
132 {
133 case 0:
134 if ((val & 1) && !(piix_busmaster[channel].command & 1)) /*Start*/
135 {
136 piix_busmaster[channel].ptr_cur = piix_busmaster[channel].ptr;
137 piix_bus_master_next_addr(channel);
138 piix_busmaster[channel].status |= 1;
139 }
140 if (!(val & 1) && (piix_busmaster[channel].command & 1)) /*Stop*/
141 piix_busmaster[channel].status &= ~1;
143 piix_busmaster[channel].command = val;
144 break;
145 case 2:
146 piix_busmaster[channel].status = (val & 0x60) | ((piix_busmaster[channel].status & ~val) & 6) | (piix_busmaster[channel].status & 1);
147 break;
148 case 4:
149 piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xffffff00) | val;
150 break;
151 case 5:
152 piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xffff00ff) | (val << 8);
153 break;
154 case 6:
155 piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xff00ffff) | (val << 16);
156 break;
157 case 7:
158 piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0x00ffffff) | (val << 24);
159 break;
160 }
161 }
163 uint8_t piix_bus_master_read(uint16_t port, void *priv)
164 {
165 int channel = (port & 8) ? 1 : 0;
166 // pclog("PIIX Bus Master read %04X %04x:%08x\n", port, CS, pc);
167 switch (port & 7)
168 {
169 case 0:
170 return piix_busmaster[channel].command;
171 case 2:
172 return piix_busmaster[channel].status;
173 case 4:
174 return piix_busmaster[channel].ptr;
175 case 5:
176 return piix_busmaster[channel].ptr >> 8;
177 case 6:
178 return piix_busmaster[channel].ptr >> 16;
179 case 7:
180 return piix_busmaster[channel].ptr >> 24;
181 }
182 return 0xff;
183 }
185 int piix_bus_master_sector_read(int channel, uint8_t *data)
186 {
187 int transferred = 0;
189 if (!(piix_busmaster[channel].status & 1))
190 return 1; /*DMA disabled*/
192 while (transferred < 512)
193 {
194 if (piix_busmaster[channel].count < (512 - transferred) && piix_busmaster[channel].eot)
195 fatal("DMA on channel %i - Read count less than 512! Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot);
197 if (piix_busmaster[channel].count < (512 - transferred))
198 {
199 // pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count);
200 memcpy(&ram[piix_busmaster[channel].addr], data + transferred, piix_busmaster[channel].count);
201 transferred += piix_busmaster[channel].count;
202 piix_busmaster[channel].addr += piix_busmaster[channel].count;
203 piix_busmaster[channel].count = 0;
204 }
205 else
206 {
207 // pclog("Transferring larger - %i bytes\n", 512 - transferred);
208 memcpy(&ram[piix_busmaster[channel].addr], data + transferred, 512 - transferred);
209 piix_busmaster[channel].addr += (512 - transferred);
210 piix_busmaster[channel].count -= (512 - transferred);
211 transferred += (512 - transferred);
212 }
214 // pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot);
216 if (!piix_busmaster[channel].count)
217 {
218 // pclog("DMA on channel %i - block over\n", channel);
219 if (piix_busmaster[channel].eot) /*End of transfer?*/
220 {
221 // pclog("DMA on channel %i - transfer over\n", channel);
222 piix_busmaster[channel].status &= ~1;
223 }
224 else
225 piix_bus_master_next_addr(channel);
226 }
227 }
228 return 0;
229 }
230 int piix_bus_master_sector_write(int channel, uint8_t *data)
231 {
232 int transferred = 0;
234 if (!(piix_busmaster[channel].status & 1))
235 return 1; /*DMA disabled*/
237 while (transferred < 512)
238 {
239 if (piix_busmaster[channel].count < (512 - transferred) && piix_busmaster[channel].eot)
240 fatal("DMA on channel %i - Write count less than 512! Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot);
242 if (piix_busmaster[channel].count < (512 - transferred))
243 {
244 // pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count);
245 memcpy(data + transferred, &ram[piix_busmaster[channel].addr], piix_busmaster[channel].count);
246 transferred += piix_busmaster[channel].count;
247 piix_busmaster[channel].addr += piix_busmaster[channel].count;
248 piix_busmaster[channel].count = 0;
249 }
250 else
251 {
252 // pclog("Transferring larger - %i bytes\n", 512 - transferred);
253 memcpy(data + transferred, &ram[piix_busmaster[channel].addr], 512 - transferred);
254 piix_busmaster[channel].addr += (512 - transferred);
255 piix_busmaster[channel].count -= (512 - transferred);
256 transferred += (512 - transferred);
257 }
259 // pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot);
261 if (!piix_busmaster[channel].count)
262 {
263 // pclog("DMA on channel %i - block over\n", channel);
264 if (piix_busmaster[channel].eot) /*End of transfer?*/
265 {
266 // pclog("DMA on channel %i - transfer over\n", channel);
267 piix_busmaster[channel].status &= ~1;
268 }
269 else
270 piix_bus_master_next_addr(channel);
271 }
272 }
273 return 0;
274 }
276 void piix_bus_master_set_irq(int channel)
277 {
278 piix_busmaster[channel].status |= 4;
279 }
281 void piix_init(int card)
282 {
283 pci_add_specific(card, piix_read, piix_write, NULL);
285 memset(card_piix, 0, 256);
286 card_piix[0x00] = 0x86; card_piix[0x01] = 0x80; /*Intel*/
287 card_piix[0x02] = 0x2e; card_piix[0x03] = 0x12; /*82371FB (PIIX)*/
288 card_piix[0x04] = 0x07; card_piix[0x05] = 0x00;
289 card_piix[0x06] = 0x00; card_piix[0x07] = 0x02;
290 card_piix[0x08] = 0x00; /*A0 stepping*/
291 card_piix[0x09] = 0x00; card_piix[0x0a] = 0x01; card_piix[0x0b] = 0x06;
292 card_piix[0x0e] = 0x80; /*Multi-function device*/
293 card_piix[0x4c] = 0x4d;
294 card_piix[0x4e] = 0x03;
295 card_piix[0x60] = card_piix[0x61] = card_piix[0x62] = card_piix[0x63] = 0x80;
296 card_piix[0x69] = 0x02;
297 card_piix[0x70] = card_piix[0x71] = 0x80;
298 card_piix[0x76] = card_piix[0x77] = 0x0c;
299 card_piix[0x78] = 0x02; card_piix[0x79] = 0x00;
300 card_piix[0xa0] = 0x08;
301 card_piix[0xa2] = card_piix[0xa3] = 0x00;
302 card_piix[0xa4] = card_piix[0xa5] = card_piix[0xa6] = card_piix[0xa7] = 0x00;
303 card_piix[0xa8] = 0x0f;
304 card_piix[0xaa] = card_piix[0xab] = 0x00;
305 card_piix[0xac] = 0x00;
306 card_piix[0xae] = 0x00;
308 card_piix_ide[0x00] = 0x86; card_piix_ide[0x01] = 0x80; /*Intel*/
309 card_piix_ide[0x02] = 0x30; card_piix_ide[0x03] = 0x12; /*82371FB (PIIX)*/
310 card_piix_ide[0x04] = 0x00; card_piix_ide[0x05] = 0x00;
311 card_piix_ide[0x06] = 0x80; card_piix_ide[0x07] = 0x02;
312 card_piix_ide[0x08] = 0x00;
313 card_piix_ide[0x09] = 0x80; card_piix_ide[0x0a] = 0x01; card_piix_ide[0x0b] = 0x01;
314 card_piix_ide[0x0d] = 0x00;
315 card_piix_ide[0x0e] = 0x00;
316 card_piix_ide[0x20] = 0x01; card_piix_ide[0x21] = card_piix_ide[0x22] = card_piix_ide[0x23] = 0x00; /*Bus master interface base address*/
317 card_piix_ide[0x40] = card_piix_ide[0x41] = 0x00;
318 card_piix_ide[0x42] = card_piix_ide[0x43] = 0x00;
320 ide_set_bus_master(piix_bus_master_sector_read, piix_bus_master_sector_write, piix_bus_master_set_irq);
321 }
