1 #define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT))
2
3 #define _LARGEFILE_SOURCE
4 #define _LARGEFILE64_SOURCE
5 #define _GNU_SOURCE
6 #include <errno.h>
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <string.h>
10
11 #include <sys/types.h>
12
13 #include "ibm.h"
14 #include "hdd.h"
15 #include "io.h"
16 #include "pic.h"
17 #include "timer.h"
18 #include "hdd_file.h"
19 #include "scsi.h"
20 #include "scsi_cd.h"
21 #include "scsi_zip.h"
22 #include "ide.h"
23
24 /* ATA Commands */
25 #define WIN_SRST 0x08 /* ATAPI Device Reset */
26 #define WIN_RECAL 0x10
27 #define WIN_RESTORE WIN_RECAL
28 #define WIN_READ 0x20 /* 28-Bit Read */
29 #define WIN_READ_NORETRY 0x21 /* 28-Bit Read - no retry*/
30 #define WIN_WRITE 0x30 /* 28-Bit Write */
31 #define WIN_WRITE_NORETRY 0x31 /* 28-Bit Write */
32 #define WIN_VERIFY 0x40 /* 28-Bit Verify */
33 #define WIN_VERIFY_ONCE 0x41 /* Deprecated command - same as 0x40 */
34 #define WIN_FORMAT 0x50
35 #define WIN_SEEK 0x70
36 #define WIN_DRIVE_DIAGNOSTICS 0x90 /* Execute Drive Diagnostics */
37 #define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */
38 #define WIN_PACKETCMD 0xA0 /* Send a packet command. */
39 #define WIN_PIDENTIFY 0xA1 /* Identify ATAPI device */
40 #define WIN_READ_MULTIPLE 0xC4
41 #define WIN_WRITE_MULTIPLE 0xC5
42 #define WIN_SET_MULTIPLE_MODE 0xC6
43 #define WIN_READ_DMA 0xC8
44 #define WIN_WRITE_DMA 0xCA
45 #define WIN_SETIDLE1 0xE3
46 #define WIN_CHECK_POWER_MODE 0xE5
47 #define WIN_IDENTIFY 0xEC /* Ask drive to identify itself */
48 #define WIN_SET_FEATURES 0xEF
49
50 /** Evaluate to non-zero if the currently selected drive is an ATAPI device */
51 #define IDE_DRIVE_IS_CDROM(ide) (ide->type == IDE_CDROM)
52
53
54 enum
55 {
56 IDE_NONE = 0,
57 IDE_HDD,
58 IDE_CDROM
59 };
60
61 struct IDE;
62
63 typedef struct IDE
64 {
65 int type;
66 int board;
67 uint8_t atastat;
68 uint8_t error;
69 int secount,sector,cylinder,head,drive,cylprecomp;
70 uint8_t command;
71 uint8_t fdisk;
72 int pos;
73 int reset;
74 uint16_t buffer[65536];
75 int irqstat;
76 int service;
77 int lba;
78 uint32_t lba_addr;
79 int skip512;
80 int blocksize, blockcount;
81 uint8_t sector_buffer[256*512];
82 int do_initial_read;
83 int sector_pos;
84 hdd_file_t hdd_file;
85 atapi_device_t atapi;
86 } IDE;
87
88 int cdrom_channel = 2;
89 int zip_channel = -1;
90
91 IDE ide_drives[7];
92
93 IDE *ext_ide;
94
95 char ide_fn[7][512];
96
97 int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size);
98 int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size);
99 void (*ide_bus_master_set_irq)(int channel);
100
101 int idecallback[2] = {0, 0};
102
103 int cur_ide[2];
104
getstat(IDE * ide)105 uint8_t getstat(IDE *ide) { return ide->atastat; }
106
ide_irq_raise(IDE * ide)107 void ide_irq_raise(IDE *ide)
108 {
109 // pclog("IDE_IRQ_RAISE\n");
110 if (!(ide->fdisk&2)) {
111 // if (ide->board && !ide->irqstat) pclog("IDE_IRQ_RAISE\n");
112 picint((ide->board)?(1<<15):(1<<14));
113 if (ide_bus_master_set_irq)
114 ide_bus_master_set_irq(ide->board);
115 }
116 ide->irqstat=1;
117 ide->service=1;
118 }
119
ide_irq_lower(IDE * ide)120 static inline void ide_irq_lower(IDE *ide)
121 {
122 // pclog("IDE_IRQ_LOWER\n");
123 // if (ide.board == 0) {
124 picintc((ide->board)?(1<<15):(1<<14));
125 // }
126 ide->irqstat=0;
127 }
128
ide_irq_update(IDE * ide)129 void ide_irq_update(IDE *ide)
130 {
131 if (ide->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(ide->fdisk & 2))
132 picint((ide->board)?(1<<15):(1<<14));
133 else if ((pic2.pend|pic2.ins)&0x40)
134 picintc((ide->board)?(1<<15):(1<<14));
135 }
136 /**
137 * Copy a string into a buffer, padding with spaces, and placing characters as
138 * if they were packed into 16-bit values, stored little-endian.
139 *
140 * @param str Destination buffer
141 * @param src Source string
142 * @param len Length of destination buffer to fill in. Strings shorter than
143 * this length will be padded with spaces.
144 */
ide_padstr(char * str,const char * src,int len)145 void ide_padstr(char *str, const char *src, int len)
146 {
147 int i, v;
148
149 for (i = 0; i < len; i++) {
150 if (*src != '\0') {
151 v = *src++;
152 } else {
153 v = ' ';
154 }
155 str[i ^ 1] = v;
156 }
157 }
158
159 /**
160 * Fill in ide->buffer with the output of the "IDENTIFY DEVICE" command
161 */
ide_identify(IDE * ide)162 static void ide_identify(IDE *ide)
163 {
164 memset(ide->buffer, 0, 512);
165
166 //ide->buffer[1] = 101; /* Cylinders */
167
168 if ((hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) >= 16514064)
169 ide->buffer[1] = 16383;
170 else
171 ide->buffer[1] = hdc[cur_ide[ide->board]].tracks; /* Cylinders */
172 ide->buffer[3] = hdc[cur_ide[ide->board]].hpc; /* Heads */
173 ide->buffer[6] = hdc[cur_ide[ide->board]].spt; /* Sectors */
174
175 ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
176 ide_padstr((char *) (ide->buffer + 23), "v1.0", 8); /* Firmware */
177 ide_padstr((char *) (ide->buffer + 27), "PCemHD", 40); /* Model */
178
179 ide->buffer[20] = 3; /*Buffer type*/
180 ide->buffer[21] = 512; /*Buffer size*/
181 ide->buffer[47] = 16; /*Max sectors on multiple transfer command*/
182 ide->buffer[48] = 1; /*Dword transfers supported*/
183 ide->buffer[49] = (1 << 9) | (1 << 8); /* LBA and DMA supported */
184 ide->buffer[50] = 0x4000; /* Capabilities */
185 ide->buffer[51] = 2 << 8; /*PIO timing mode*/
186 ide->buffer[52] = 2 << 8; /*DMA timing mode*/
187 ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0;
188 ide->buffer[60] = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) & 0xFFFF; /* Total addressable sectors (LBA) */
189 ide->buffer[61] = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) >> 16;
190 ide->buffer[63] = 7; /*Multiword DMA*/
191 ide->buffer[80] = 0xe; /*ATA-1 to ATA-3 supported*/
192 }
193
194 /*
195 * Return the sector offset for the current register values
196 */
ide_get_sector(IDE * ide)197 static off64_t ide_get_sector(IDE *ide)
198 {
199 if (ide->lba)
200 {
201 return (off64_t)ide->lba_addr + ide->skip512;
202 }
203 else
204 {
205 int heads = ide->hdd_file.hpc;
206 int sectors = ide->hdd_file.spt;
207
208 return ((((off64_t) ide->cylinder * heads) + ide->head) *
209 sectors) + (ide->sector - 1) + ide->skip512;
210 }
211 }
212
213 /**
214 * Move to the next sector using CHS addressing
215 */
ide_next_sector(IDE * ide)216 static void ide_next_sector(IDE *ide)
217 {
218 if (ide->lba)
219 {
220 ide->lba_addr++;
221 }
222 else
223 {
224 ide->sector++;
225
226 if (ide->sector == (ide->hdd_file.spt + 1)) {
227 ide->sector = 1;
228 ide->head++;
229
230 if (ide->head == ide->hdd_file.hpc) {
231 ide->head = 0;
232 ide->cylinder++;
233 }
234 }
235 }
236 }
237
loadhd(IDE * ide,int d,const char * fn)238 static void loadhd(IDE *ide, int d, const char *fn)
239 {
240 hdd_load(&ide->hdd_file, d, fn);
241
242 if (ide->hdd_file.f)
243 ide->type = IDE_HDD;
244 else
245 ide->type = IDE_NONE;
246 }
247
ide_set_signature(IDE * ide)248 void ide_set_signature(IDE *ide)
249 {
250 ide->secount=1;
251 ide->sector=1;
252 ide->head=0;
253 ide->cylinder=(IDE_DRIVE_IS_CDROM(ide) ? 0xEB14 : ((ide->type == IDE_HDD) ? 0 : 0xFFFF));
254 // if (ide->type == IDE_HDD) ide->drive = 0;
255 }
256
resetide(void)257 void resetide(void)
258 {
259 int d;
260
261 /* Close hard disk image files (if previously open) */
262 for (d = 0; d < 4; d++) {
263 ide_drives[d].type = IDE_NONE;
264 hdd_close(&ide_drives[d].hdd_file);
265
266 ide_drives[d].atastat = READY_STAT | DSC_STAT;
267 ide_drives[d].service = 0;
268 ide_drives[d].board = (d & 2) ? 1 : 0;
269 }
270
271 idecallback[0]=idecallback[1]=0;
272 if (hdd_controller_current_is_ide())
273 {
274 for (d = 0; d < 4; d++)
275 {
276 ide_drives[d].drive = d;
277
278 if (cdrom_channel == d)
279 {
280 ide_drives[d].type = IDE_CDROM;
281 scsi_bus_atapi_init(&ide_drives[d].atapi.bus, &scsi_cd, d, &ide_drives[d].atapi);
282 }
283 else if (zip_channel == d)
284 {
285 ide_drives[d].type = IDE_CDROM;
286 scsi_bus_atapi_init(&ide_drives[d].atapi.bus, &scsi_zip, d, &ide_drives[d].atapi);
287 }
288 else
289 {
290 loadhd(&ide_drives[d], d, ide_fn[d]);
291 }
292
293 ide_set_signature(&ide_drives[d]);
294
295 ide_drives[d].atapi.ide = &ide_drives[d];
296 ide_drives[d].atapi.board = (d & 2) ? 1 : 0;
297 ide_drives[d].atapi.atastat = &ide_drives[d].atastat;
298 ide_drives[d].atapi.error = &ide_drives[d].error;
299 ide_drives[d].atapi.cylinder = &ide_drives[d].cylinder;
300 }
301 }
302
303
304 cur_ide[0] = 0;
305 cur_ide[1] = 2;
306 }
307
308
309 int idetimes=0;
writeidew(int ide_board,uint16_t val)310 void writeidew(int ide_board, uint16_t val)
311 {
312 IDE *ide = &ide_drives[cur_ide[ide_board]];
313
314 if (ide->command == WIN_PACKETCMD)
315 {
316 atapi_data_write(&ide->atapi, val);
317 }
318 else
319 {
320 ide->buffer[ide->pos >> 1] = val;
321 ide->pos += 2;
322
323 if (ide->pos>=512)
324 {
325 ide->pos=0;
326 ide->atastat = BUSY_STAT;
327 timer_process();
328 if (ide->command == WIN_WRITE_MULTIPLE)
329 callbackide(ide_board);
330 else
331 idecallback[ide_board] = 6 * IDE_TIME;
332 timer_update_outstanding();
333 }
334 }
335 }
336
writeidel(int ide_board,uint32_t val)337 void writeidel(int ide_board, uint32_t val)
338 {
339 // pclog("WriteIDEl %08X\n", val);
340 writeidew(ide_board, val);
341 writeidew(ide_board, val >> 16);
342 }
343
writeide(int ide_board,uint16_t addr,uint8_t val)344 void writeide(int ide_board, uint16_t addr, uint8_t val)
345 {
346 IDE *ide = &ide_drives[cur_ide[ide_board]];
347 IDE *ide_other = &ide_drives[cur_ide[ide_board] ^ 1];
348
349 /* if (ide_board && (cr0&1) && !(eflags&VM_FLAG))
350 {
351 // pclog("Failed write IDE %04X:%08X\n",CS,pc);
352 return;
353 }*/
354 // if ((cr0&1) && !(eflags&VM_FLAG))
355 // if (ide_board)
356 // pclog("WriteIDE %04X %02X from %04X(%08X):%08X %i\n", addr, val, CS, cs, cpu_state.pc, ins);
357 // return;
358 addr|=0x80;
359 // if (ide_board) pclog("Write IDEb %04X %02X %04X(%08X):%04X %i %02X %02X\n",addr,val,CS,cs,pc,ins,ide->atastat,ide_drives[0].atastat);
360 /*if (idedebug) */
361 // pclog("Write IDE %08X %02X %04X:%08X\n",addr,val,CS,pc);
362 // int c;
363 // rpclog("Write IDE %08X %02X %08X %08X\n",addr,val,PC,armregs[12]);
364
365 if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) return;
366
367 switch (addr)
368 {
369 case 0x1F0: /* Data */
370 writeidew(ide_board, val | (val << 8));
371 return;
372
373 case 0x1F1: /* Features */
374 ide->cylprecomp = val;
375 ide_other->cylprecomp = val;
376 return;
377
378 case 0x1F2: /* Sector count */
379 ide->secount = val;
380 ide_other->secount = val;
381 return;
382
383 case 0x1F3: /* Sector */
384 ide->sector = val;
385 ide->lba_addr = (ide->lba_addr & 0xFFFFF00) | val;
386 ide_other->sector = val;
387 ide_other->lba_addr = (ide_other->lba_addr & 0xFFFFF00) | val;
388 return;
389
390 case 0x1F4: /* Cylinder low */
391 ide->cylinder = (ide->cylinder & 0xFF00) | val;
392 ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8);
393 ide_other->cylinder = (ide_other->cylinder&0xFF00) | val;
394 ide_other->lba_addr = (ide_other->lba_addr&0xFFF00FF) | (val << 8);
395 // pclog("Write cylinder low %02X\n",val);
396 return;
397
398 case 0x1F5: /* Cylinder high */
399 ide->cylinder = (ide->cylinder & 0xFF) | (val << 8);
400 ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16);
401 ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8);
402 ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16);
403 return;
404
405 case 0x1F6: /* Drive/Head */
406 /* if (val==0xB0)
407 {
408 dumpregs();
409 exit(-1);
410 }*/
411
412 if (cur_ide[ide_board] != ((val>>4)&1)+(ide_board<<1))
413 {
414 cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1);
415
416 if (ide->reset || ide_other->reset)
417 {
418 ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT;
419 ide->error = ide_other->error = 1;
420 ide->secount = ide_other->secount = 1;
421 ide->sector = ide_other->sector = 1;
422 ide->head = ide_other->head = 0;
423 ide->cylinder = ide_other->cylinder = 0;
424 ide->reset = ide_other->reset = 0;
425 // ide->blocksize = ide_other->blocksize = 0;
426 if (IDE_DRIVE_IS_CDROM(ide))
427 ide->cylinder=0xEB14;
428 if (IDE_DRIVE_IS_CDROM(ide_other))
429 ide_other->cylinder=0xEB14;
430
431 idecallback[ide_board] = 0;
432 timer_update_outstanding();
433 return;
434 }
435
436 ide = &ide_drives[cur_ide[ide_board]];
437 }
438
439 ide->head = val & 0xF;
440 ide->lba = val & 0x40;
441 ide_other->head = val & 0xF;
442 ide_other->lba = val & 0x40;
443
444 ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24);
445 ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF)|((val & 0xF) << 24);
446
447 ide_irq_update(ide);
448 return;
449
450 case 0x1F7: /* Command register */
451 if (ide->type == IDE_NONE) return;
452 // pclog("IDE command %02X drive %i\n",val,ide.drive);
453 ide_irq_lower(ide);
454 ide->command=val;
455
456 // pclog("New IDE command - %02X %i %i\n",ide->command,cur_ide[ide_board],ide_board);
457 ide->error=0;
458 switch (val)
459 {
460 case WIN_SRST: /* ATAPI Device Reset */
461 if (IDE_DRIVE_IS_CDROM(ide)) ide->atastat = BUSY_STAT;
462 else ide->atastat = READY_STAT;
463 timer_process();
464 idecallback[ide_board]=100*IDE_TIME;
465 timer_update_outstanding();
466 return;
467
468 case WIN_RESTORE:
469 case WIN_SEEK:
470 // pclog("WIN_RESTORE start\n");
471 ide->atastat = READY_STAT;
472 timer_process();
473 idecallback[ide_board]=100*IDE_TIME;
474 timer_update_outstanding();
475 return;
476
477 case WIN_READ_MULTIPLE:
478 if (!ide->blocksize && (ide->type != IDE_CDROM))
479 fatal("READ_MULTIPLE - blocksize = 0\n");
480 #if 0
481 if (ide->lba) pclog("Read Multiple %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
482 else pclog("Read Multiple %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins);
483 #endif
484 ide->blockcount = 0;
485
486 case WIN_READ:
487 case WIN_READ_NORETRY:
488 case WIN_READ_DMA:
489 /* if (ide.secount>1)
490 {
491 fatal("Read %i sectors from sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head);
492 }*/
493 #if 0
494 if (ide->lba) pclog("Read %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
495 else pclog("Read %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins);
496 #endif
497 ide->atastat = BUSY_STAT;
498 timer_process();
499 idecallback[ide_board]=200*IDE_TIME;
500 timer_update_outstanding();
501 ide->do_initial_read = 1;
502 return;
503
504 case WIN_WRITE_MULTIPLE:
505 if (!ide->blocksize && (ide->type != IDE_CDROM))
506 fatal("Write_MULTIPLE - blocksize = 0\n");
507 #if 0
508 if (ide->lba) pclog("Write Multiple %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
509 else pclog("Write Multiple %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head);
510 #endif
511 ide->blockcount = 0;
512
513 case WIN_WRITE:
514 case WIN_WRITE_NORETRY:
515 /* if (ide.secount>1)
516 {
517 fatal("Write %i sectors to sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head);
518 }*/
519 #if 0
520 if (ide->lba) pclog("Write %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
521 else pclog("Write %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head);
522 #endif
523 ide->atastat = DRQ_STAT | DSC_STAT | READY_STAT;
524 ide->pos=0;
525 return;
526
527 case WIN_WRITE_DMA:
528 #if 0
529 if (ide->lba) pclog("Write %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
530 else pclog("Write %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head);
531 #endif
532 ide->atastat = BUSY_STAT;
533 timer_process();
534 idecallback[ide_board]=200*IDE_TIME;
535 timer_update_outstanding();
536 return;
537
538 case WIN_VERIFY:
539 case WIN_VERIFY_ONCE:
540 #if 0
541 if (ide->lba) pclog("Read verify %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
542 else pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head);
543 #endif
544 ide->atastat = BUSY_STAT;
545 timer_process();
546 idecallback[ide_board]=200*IDE_TIME;
547 timer_update_outstanding();
548 return;
549
550 case WIN_FORMAT:
551 // pclog("Format track %i head %i\n",ide.cylinder,ide.head);
552 ide->atastat = DRQ_STAT;
553 // idecallback[ide_board]=200;
554 ide->pos=0;
555 return;
556
557 case WIN_SPECIFY: /* Initialize Drive Parameters */
558 ide->atastat = BUSY_STAT;
559 timer_process();
560 idecallback[ide_board]=30*IDE_TIME;
561 timer_update_outstanding();
562 // pclog("SPECIFY\n");
563 // output=1;
564 return;
565
566 case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */
567 ide->atastat = BUSY_STAT;
568 timer_process();
569 idecallback[ide_board]=200*IDE_TIME;
570 timer_update_outstanding();
571 return;
572
573 case WIN_PIDENTIFY: /* Identify Packet Device */
574 case WIN_SET_MULTIPLE_MODE: /*Set Multiple Mode*/
575 // output=1;
576 case WIN_SETIDLE1: /* Idle */
577 case WIN_CHECK_POWER_MODE:
578 ide->atastat = BUSY_STAT;
579 timer_process();
580 callbackide(ide_board);
581 // idecallback[ide_board]=200*IDE_TIME;
582 timer_update_outstanding();
583 return;
584
585 case WIN_IDENTIFY: /* Identify Device */
586 case WIN_SET_FEATURES:
587 // output=3;
588 // timetolive=500;
589 ide->atastat = BUSY_STAT;
590 timer_process();
591 idecallback[ide_board]=200*IDE_TIME;
592 timer_update_outstanding();
593 return;
594
595 case WIN_PACKETCMD: /* ATAPI Packet */
596 if (ide->type == IDE_CDROM)
597 atapi_command_start(&ide->atapi, ide->cylprecomp);
598
599 ide->atastat = BUSY_STAT;
600 timer_process();
601 idecallback[ide_board] = IDE_TIME;
602 timer_update_outstanding();
603
604 ide->atapi.bus_state = 0;
605 return;
606
607 case 0xF0:
608 default:
609 ide->atastat = READY_STAT | ERR_STAT | DSC_STAT;
610 ide->error = ABRT_ERR;
611 ide_irq_raise(ide);
612 /* fatal("Bad IDE command %02X\n", val);*/
613 return;
614 }
615
616 return;
617
618 case 0x3F6: /* Device control */
619 if ((ide->fdisk&4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE))
620 {
621 timer_process();
622 idecallback[ide_board]=500*IDE_TIME;
623 timer_update_outstanding();
624 ide->reset = ide_other->reset = 1;
625 ide->atastat = ide_other->atastat = BUSY_STAT;
626 // pclog("IDE Reset %i\n", ide_board);
627 }
628 if (val & 4)
629 {
630 /*Drive held in reset*/
631 timer_process();
632 idecallback[ide_board] = 0;
633 timer_update_outstanding();
634 ide->atastat = ide_other->atastat = BUSY_STAT;
635 }
636 ide->fdisk = ide_other->fdisk = val;
637 ide_irq_update(ide);
638 return;
639 }
640 // fatal("Bad IDE write %04X %02X\n", addr, val);
641 }
642
readide(int ide_board,uint16_t addr)643 uint8_t readide(int ide_board, uint16_t addr)
644 {
645 IDE *ide = &ide_drives[cur_ide[ide_board]];
646 uint8_t temp = 0xff;
647 uint16_t tempw;
648
649 addr|=0x80;
650
651 /* if (ide_board && (cr0&1) && !(eflags&VM_FLAG))
652 {
653 // pclog("Failed read IDE %04X:%08X\n",CS,pc);
654 return 0xFF;
655 }*/
656 // if ((cr0&1) && !(eflags&VM_FLAG))
657 // pclog("ReadIDE %04X from %04X(%08X):%08X\n", addr, CS, cs, pc);
658 // return 0xFF;
659
660 if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) return 0;
661 // /*if (addr!=0x1F7 && addr!=0x3F6) */pclog("Read IDEb %04X %02X %02X %i %04X:%04X %i %04X\n",addr,ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,pc,ide_board, BX);
662 //rpclog("Read IDE %08X %08X %02X\n",addr,PC,iomd.irqb.mask);
663 switch (addr)
664 {
665 case 0x1F0: /* Data */
666 tempw = readidew(ide_board);
667 // pclog("Read IDEW %04X\n", tempw);
668 temp = tempw & 0xff;
669 break;
670
671 case 0x1F1: /* Error */
672 // pclog("Read error %02X\n",ide.error);
673 temp = ide->error;
674 break;
675
676 case 0x1F2: /* Sector count */
677 // pclog("Read sector count %02X\n",ide->secount);
678 if (ide->type == IDE_CDROM && ide->command == WIN_PACKETCMD)
679 temp = atapi_read_iir(&ide->atapi);
680 else
681 temp = (uint8_t)ide->secount;
682 break;
683
684 case 0x1F3: /* Sector */
685 temp = (uint8_t)ide->sector;
686 break;
687
688 case 0x1F4: /* Cylinder low */
689 // pclog("Read cyl low %02X\n",ide.cylinder&0xFF);
690 temp = (uint8_t)(ide->cylinder&0xFF);
691 break;
692
693 case 0x1F5: /* Cylinder high */
694 // pclog("Read cyl low %02X\n",ide.cylinder>>8);
695 temp = (uint8_t)(ide->cylinder>>8);
696 break;
697
698 case 0x1F6: /* Drive/Head */
699 temp = (uint8_t)(ide->head | ((cur_ide[ide_board] & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0);
700 break;
701
702 case 0x1F7: /* Status */
703 if (ide->type == IDE_NONE)
704 {
705 // pclog("Return status 00\n");
706 temp = 0;
707 break;
708 }
709 ide_irq_lower(ide);
710 if (ide->type == IDE_CDROM)
711 {
712 // pclog("Read CDROM status %02X\n",(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0));
713 temp = (ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
714 if (ide->command == WIN_PACKETCMD)
715 {
716 if (atapi_read_drq(&ide->atapi))
717 temp |= DRQ_STAT;
718 else
719 temp &= ~DRQ_STAT;
720 }
721 }
722 else
723 {
724 // && ide->service) return ide.atastat[ide.board]|SERVICE_STAT;
725 // pclog("Return status %02X %04X:%04X %02X %02X\n",ide->atastat, CS ,pc, AH, BH);
726 temp = ide->atastat;
727 }
728 break;
729
730 case 0x3F6: /* Alternate Status */
731 // pclog("3F6 read %02X\n",ide.atastat[ide.board]);
732 // if (output) output=0;
733 if (ide->type == IDE_NONE)
734 {
735 // pclog("Return status 00\n");
736 temp = 0;
737 break;
738 }
739 if (ide->type == IDE_CDROM)
740 {
741 // pclog("Read CDROM status %02X\n",(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0));
742 temp = (ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
743 if (ide->command == WIN_PACKETCMD)
744 {
745 if (atapi_read_drq(&ide->atapi))
746 temp |= DRQ_STAT;
747 else
748 temp &= ~DRQ_STAT;
749 }
750 }
751 else
752 {
753 // && ide->service) return ide.atastat[ide.board]|SERVICE_STAT;
754 // pclog("Return status %02X\n",ide->atastat);
755 temp = ide->atastat;
756 }
757 break;
758 }
759 // if (ide_board) pclog("Read IDEb %04X %02X %02X %02X %i %04X:%04X %i\n", addr, temp, ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,cpu_state.pc,ide_board);
760 return temp;
761 // fatal("Bad IDE read %04X\n", addr);
762 }
763
readidew(int ide_board)764 uint16_t readidew(int ide_board)
765 {
766 IDE *ide = &ide_drives[cur_ide[ide_board]];
767 uint16_t temp;
768
769 /* if (ide_board && (cr0&1) && !(eflags&VM_FLAG))
770 {
771 // pclog("Failed read IDEw %04X:%08X\n",CS,pc);
772 return 0xFFFF;
773 }*/
774 // return 0xFFFF;
775 // pclog("Read IDEw %04X %04X:%04X %02X %i %i\n",ide->buffer[ide->pos >> 1],CS,pc,opcode,ins, ide->pos);
776
777 if (ide->command == WIN_PACKETCMD)
778 {
779 temp = atapi_data_read(&ide->atapi);
780 }
781 else
782 {
783 temp = ide->buffer[ide->pos >> 1];
784 ide->pos += 2;
785 if (ide->pos >= 512 && ide->command)
786 {
787 // pclog("Over! packlen %i %i\n",ide->packlen,ide->pos);
788 ide->pos = 0;
789 ide->atastat = READY_STAT | DSC_STAT;
790 if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE)
791 {
792 ide->secount = (ide->secount - 1) & 0xff;
793 if (ide->secount)
794 {
795 ide_next_sector(ide);
796 ide->atastat = BUSY_STAT;
797 timer_process();
798 if (ide->command == WIN_READ_MULTIPLE)
799 callbackide(ide_board);
800 else
801 idecallback[ide_board] = 6 * IDE_TIME;
802 timer_update_outstanding();
803 // pclog("set idecallback\n");
804 // callbackide(ide_board);
805 }
806 // else
807 // pclog("readidew done %02X\n", ide->atastat);
808 }
809 }
810 }
811 // pclog("Read IDEw %04X\n",temp);
812 return temp;
813 }
814
readidel(int ide_board)815 uint32_t readidel(int ide_board)
816 {
817 uint16_t temp;
818 // pclog("Read IDEl %i\n", ide_board);
819 temp = readidew(ide_board);
820 return temp | (readidew(ide_board) << 16);
821 }
822
823 int times30=0;
callbackide(int ide_board)824 void callbackide(int ide_board)
825 {
826 IDE *ide = &ide_drives[cur_ide[ide_board]];
827 IDE *ide_other = &ide_drives[cur_ide[ide_board] ^ 1];
828 atapi_device_t *atapi_dev = &ide->atapi;
829
830 ext_ide = ide;
831 // return;
832 if (ide->command==0x30) times30++;
833 // if (times30==2240) output=1;
834 //if (times30==2471 && ide->command==0xA0) output=1;
835 ///*if (ide_board) */pclog("CALLBACK %02X %i %i %i\n",ide->command,times30,ide->reset,cur_ide[ide_board]);
836 // if (times30==1294)
837 // output=1;
838 if (ide->reset)
839 {
840 ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT;
841 ide->error = ide_other->error = 1;
842 ide->secount = ide_other->secount = 1;
843 ide->sector = ide_other->sector = 1;
844 ide->head = ide_other->head = 0;
845 ide->cylinder = ide_other->cylinder = 0;
846 ide->reset = ide_other->reset = 0;
847 if (IDE_DRIVE_IS_CDROM(ide))
848 {
849 ide->cylinder=0xEB14;
850 atapi->stop();
851 }
852 if (ide->type == IDE_NONE)
853 {
854 ide->cylinder=0xFFFF;
855 atapi->stop();
856 }
857 if (IDE_DRIVE_IS_CDROM(ide_other))
858 {
859 ide_other->cylinder=0xEB14;
860 atapi->stop();
861 }
862 if (ide_other->type == IDE_NONE)
863 {
864 ide_other->cylinder=0xFFFF;
865 atapi->stop();
866 }
867 // pclog("Reset callback\n");
868 return;
869 }
870 switch (ide->command)
871 {
872 //Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h.
873 case WIN_SRST: /*ATAPI Device Reset */
874 ide->atastat = READY_STAT | DSC_STAT;
875 ide->error=1; /*Device passed*/
876 ide->secount = ide->sector = 1;
877 ide_set_signature(ide);
878 if (IDE_DRIVE_IS_CDROM(ide))
879 ide->atastat = 0;
880 ide_irq_raise(ide);
881 if (IDE_DRIVE_IS_CDROM(ide))
882 ide->service = 0;
883 return;
884
885 case WIN_RESTORE:
886 case WIN_SEEK:
887 if (IDE_DRIVE_IS_CDROM(ide)) {
888 pclog("WIN_RESTORE callback on CD-ROM\n");
889 goto abort_cmd;
890 }
891 // pclog("WIN_RESTORE callback\n");
892 ide->atastat = READY_STAT | DSC_STAT;
893 ide_irq_raise(ide);
894 return;
895
896 case WIN_READ:
897 case WIN_READ_NORETRY:
898 if (IDE_DRIVE_IS_CDROM(ide)) {
899 ide_set_signature(ide);
900 goto abort_cmd;
901 }
902 if (ide->do_initial_read)
903 {
904 ide->do_initial_read = 0;
905 ide->sector_pos = 0;
906 hdd_read_sectors(&ide->hdd_file, ide_get_sector(ide), ide->secount ? ide->secount : 256, ide->sector_buffer);
907 }
908 memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512);
909 ide->sector_pos++;
910 // pclog("Read %i %i %i %08X\n",ide.cylinder,ide.head,ide.sector,addr);
911 /* if (ide.cylinder || ide.head)
912 {
913 fatal("Read from other cylinder/head");
914 }*/
915 ide->pos=0;
916 ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
917 // pclog("Read sector callback %i %i %i offset %08X %i left %i %02X\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount,ide.spt,ide.atastat[ide.board]);
918 // if (addr) output=3;
919 ide_irq_raise(ide);
920
921 readflash_set(READFLASH_HDC, ide->drive);
922 return;
923
924 case WIN_READ_DMA:
925 if (IDE_DRIVE_IS_CDROM(ide)) {
926 goto abort_cmd;
927 }
928 if (ide->do_initial_read)
929 {
930 ide->do_initial_read = 0;
931 ide->sector_pos = 0;
932 hdd_read_sectors(&ide->hdd_file, ide_get_sector(ide), ide->secount ? ide->secount : 256, ide->sector_buffer);
933 }
934 ide->pos=0;
935
936 if (ide_bus_master_read_data)
937 {
938 if (ide_bus_master_read_data(ide_board, &ide->sector_buffer[ide->sector_pos*512], 512))
939 idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/
940 else
941 {
942 /*DMA successful*/
943 ide->sector_pos++;
944 ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
945
946 ide->secount = (ide->secount - 1) & 0xff;
947 if (ide->secount)
948 {
949 ide_next_sector(ide);
950 ide->atastat = BUSY_STAT;
951 idecallback[ide_board]=6*IDE_TIME;
952 }
953 else
954 {
955 ide_irq_raise(ide);
956 }
957 }
958 }
959
960 readflash_set(READFLASH_HDC, ide->drive);
961 return;
962
963 case WIN_READ_MULTIPLE:
964 if (IDE_DRIVE_IS_CDROM(ide)) {
965 goto abort_cmd;
966 }
967 if (ide->do_initial_read)
968 {
969 ide->do_initial_read = 0;
970 ide->sector_pos = 0;
971 hdd_read_sectors(&ide->hdd_file, ide_get_sector(ide), ide->secount ? ide->secount : 256, ide->sector_buffer);
972 }
973 memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512);
974 ide->sector_pos++;
975 ide->pos=0;
976 ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
977 if (!ide->blockcount)// || ide->secount == 1)
978 {
979 // pclog("Read multiple int\n");
980 ide_irq_raise(ide);
981 }
982 ide->blockcount++;
983 if (ide->blockcount >= ide->blocksize)
984 ide->blockcount = 0;
985
986 readflash_set(READFLASH_HDC, ide->drive);
987 return;
988
989 case WIN_WRITE:
990 case WIN_WRITE_NORETRY:
991 if (IDE_DRIVE_IS_CDROM(ide)) {
992 goto abort_cmd;
993 }
994 hdd_write_sectors(&ide->hdd_file, ide_get_sector(ide), 1, ide->buffer);
995 ide_irq_raise(ide);
996 ide->secount = (ide->secount - 1) & 0xff;
997 if (ide->secount)
998 {
999 ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
1000 ide->pos=0;
1001 ide_next_sector(ide);
1002 }
1003 else
1004 ide->atastat = READY_STAT | DSC_STAT;
1005
1006 readflash_set(READFLASH_HDC, ide->drive);
1007 return;
1008
1009 case WIN_WRITE_DMA:
1010 if (IDE_DRIVE_IS_CDROM(ide)) {
1011 goto abort_cmd;
1012 }
1013
1014 if (ide_bus_master_write_data)
1015 {
1016 if (ide_bus_master_write_data(ide_board, (uint8_t *)ide->buffer, 512))
1017 idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/
1018 else
1019 {
1020 /*DMA successful*/
1021 hdd_write_sectors(&ide->hdd_file, ide_get_sector(ide), 1, ide->buffer);
1022
1023 ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
1024
1025 ide->secount = (ide->secount - 1) & 0xff;
1026 if (ide->secount)
1027 {
1028 ide_next_sector(ide);
1029 ide->atastat = BUSY_STAT;
1030 idecallback[ide_board]=6*IDE_TIME;
1031 }
1032 else
1033 {
1034 ide_irq_raise(ide);
1035 }
1036 }
1037 }
1038
1039 readflash_set(READFLASH_HDC, ide->drive);
1040 return;
1041
1042 case WIN_WRITE_MULTIPLE:
1043 if (IDE_DRIVE_IS_CDROM(ide)) {
1044 goto abort_cmd;
1045 }
1046 hdd_write_sectors(&ide->hdd_file, ide_get_sector(ide), 1, ide->buffer);
1047 ide->blockcount++;
1048 if (ide->blockcount >= ide->blocksize || ide->secount == 1)
1049 {
1050 ide->blockcount = 0;
1051 ide_irq_raise(ide);
1052 }
1053 ide->secount = (ide->secount - 1) & 0xff;
1054 if (ide->secount)
1055 {
1056 ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
1057 ide->pos=0;
1058 ide_next_sector(ide);
1059 }
1060 else
1061 ide->atastat = READY_STAT | DSC_STAT;
1062
1063 readflash_set(READFLASH_HDC, ide->drive);
1064 return;
1065
1066 case WIN_VERIFY:
1067 case WIN_VERIFY_ONCE:
1068 if (IDE_DRIVE_IS_CDROM(ide)) {
1069 goto abort_cmd;
1070 }
1071 ide->pos=0;
1072 ide->atastat = READY_STAT | DSC_STAT;
1073 // pclog("Read verify callback %i %i %i offset %08X %i left\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount);
1074 ide_irq_raise(ide);
1075
1076 readflash_set(READFLASH_HDC, ide->drive);
1077 return;
1078
1079 case WIN_FORMAT:
1080 if (IDE_DRIVE_IS_CDROM(ide)) {
1081 goto abort_cmd;
1082 }
1083 hdd_format_sectors(&ide->hdd_file, ide_get_sector(ide), ide->secount);
1084 ide->atastat = READY_STAT | DSC_STAT;
1085 ide_irq_raise(ide);
1086
1087 readflash_set(READFLASH_HDC, ide->drive);
1088 return;
1089
1090 case WIN_DRIVE_DIAGNOSTICS:
1091 ide_set_signature(ide);
1092 ide->error=1; /*No error detected*/
1093 if (IDE_DRIVE_IS_CDROM(ide))
1094 {
1095 ide->atastat = 0;
1096 }
1097 else
1098 {
1099 ide->atastat = READY_STAT | DSC_STAT;
1100 ide_irq_raise(ide);
1101 }
1102 return;
1103
1104 case WIN_SPECIFY: /* Initialize Drive Parameters */
1105 if (IDE_DRIVE_IS_CDROM(ide)) {
1106 pclog("IS CDROM - ABORT\n");
1107 goto abort_cmd;
1108 }
1109 ide->hdd_file.spt = ide->secount;
1110 ide->hdd_file.hpc = ide->head+1;
1111 ide->atastat = READY_STAT | DSC_STAT;
1112 // pclog("SPECIFY - %i sectors per track, %i heads per cylinder %i %i\n",ide->spt,ide->hpc,cur_ide[ide_board],ide_board);
1113 ide_irq_raise(ide);
1114 return;
1115
1116 case WIN_PIDENTIFY: /* Identify Packet Device */
1117 if (IDE_DRIVE_IS_CDROM(ide)) {
1118 // pclog("ATAPI identify\n");
1119 atapi_dev->bus.devices[0]->atapi_identify(ide->buffer, atapi_dev->bus.device_data[0]);
1120
1121 ide->pos=0;
1122 ide->error=0;
1123 ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
1124 ide_irq_raise(ide);
1125 return;
1126 }
1127 // pclog("Not ATAPI\n");
1128 goto abort_cmd;
1129
1130 case WIN_SET_MULTIPLE_MODE:
1131 if (IDE_DRIVE_IS_CDROM(ide)) {
1132 pclog("IS CDROM - ABORT\n");
1133 goto abort_cmd;
1134 }
1135 ide->blocksize = ide->secount;
1136 ide->atastat = READY_STAT | DSC_STAT;
1137 pclog("Set multiple mode - %i\n", ide->blocksize);
1138 ide_irq_raise(ide);
1139 return;
1140
1141 case WIN_SETIDLE1: /* Idle */
1142 goto abort_cmd;
1143
1144 case WIN_IDENTIFY: /* Identify Device */
1145 if (ide->type == IDE_NONE)
1146 {
1147 goto abort_cmd;
1148 }
1149 if (IDE_DRIVE_IS_CDROM(ide))
1150 {
1151 ide_set_signature(ide);
1152 goto abort_cmd;
1153 }
1154 else
1155 {
1156 ide_identify(ide);
1157 ide->pos=0;
1158 ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
1159 // pclog("ID callback\n");
1160 ide_irq_raise(ide);
1161 }
1162 return;
1163
1164 case WIN_SET_FEATURES:
1165 if (ide->type == IDE_NONE)
1166 goto abort_cmd;
1167 if (!IDE_DRIVE_IS_CDROM(ide))
1168 goto abort_cmd;
1169
1170 if (!atapi_dev->bus.devices[0]->atapi_set_feature(ide->cylprecomp, ide->secount, atapi_dev->bus.device_data[0]))
1171 goto abort_cmd;
1172 ide->atastat = READY_STAT | DSC_STAT;
1173 ide_irq_raise(ide);
1174 return;
1175
1176 case WIN_CHECK_POWER_MODE:
1177 if (ide->type == IDE_NONE)
1178 {
1179 goto abort_cmd;
1180 }
1181 ide->secount = 0xff;
1182 ide->atastat = READY_STAT | DSC_STAT;
1183 ide_irq_raise(ide);
1184 return;
1185
1186 case WIN_PACKETCMD: /* ATAPI Packet */
1187 if (!IDE_DRIVE_IS_CDROM(ide)) goto abort_cmd;
1188
1189 atapi_process_packet(atapi_dev);
1190
1191 return;
1192 }
1193
1194 abort_cmd:
1195 ide->command = 0;
1196 ide->atastat = READY_STAT | ERR_STAT | DSC_STAT;
1197 ide->error = ABRT_ERR;
1198 ide->pos = 0;
1199 ide_irq_raise(ide);
1200 }
1201
ide_callback_pri()1202 void ide_callback_pri()
1203 {
1204 idecallback[0] = 0;
1205 callbackide(0);
1206 }
1207
ide_callback_sec()1208 void ide_callback_sec()
1209 {
1210 idecallback[1] = 0;
1211 callbackide(1);
1212 }
1213
1214
1215
ide_write_pri(uint16_t addr,uint8_t val,void * priv)1216 void ide_write_pri(uint16_t addr, uint8_t val, void *priv)
1217 {
1218 writeide(0, addr, val);
1219 }
ide_write_pri_w(uint16_t addr,uint16_t val,void * priv)1220 void ide_write_pri_w(uint16_t addr, uint16_t val, void *priv)
1221 {
1222 writeidew(0, val);
1223 }
ide_write_pri_l(uint16_t addr,uint32_t val,void * priv)1224 void ide_write_pri_l(uint16_t addr, uint32_t val, void *priv)
1225 {
1226 writeidel(0, val);
1227 }
ide_read_pri(uint16_t addr,void * priv)1228 uint8_t ide_read_pri(uint16_t addr, void *priv)
1229 {
1230 return readide(0, addr);
1231 }
ide_read_pri_w(uint16_t addr,void * priv)1232 uint16_t ide_read_pri_w(uint16_t addr, void *priv)
1233 {
1234 return readidew(0);
1235 }
ide_read_pri_l(uint16_t addr,void * priv)1236 uint32_t ide_read_pri_l(uint16_t addr, void *priv)
1237 {
1238 return readidel(0);
1239 }
1240
ide_write_sec(uint16_t addr,uint8_t val,void * priv)1241 void ide_write_sec(uint16_t addr, uint8_t val, void *priv)
1242 {
1243 writeide(1, addr, val);
1244 }
ide_write_sec_w(uint16_t addr,uint16_t val,void * priv)1245 void ide_write_sec_w(uint16_t addr, uint16_t val, void *priv)
1246 {
1247 writeidew(1, val);
1248 }
ide_write_sec_l(uint16_t addr,uint32_t val,void * priv)1249 void ide_write_sec_l(uint16_t addr, uint32_t val, void *priv)
1250 {
1251 writeidel(1, val);
1252 }
ide_read_sec(uint16_t addr,void * priv)1253 uint8_t ide_read_sec(uint16_t addr, void *priv)
1254 {
1255 return readide(1, addr);
1256 }
ide_read_sec_w(uint16_t addr,void * priv)1257 uint16_t ide_read_sec_w(uint16_t addr, void *priv)
1258 {
1259 return readidew(1);
1260 }
ide_read_sec_l(uint16_t addr,void * priv)1261 uint32_t ide_read_sec_l(uint16_t addr, void *priv)
1262 {
1263 return readidel(1);
1264 }
1265
ide_pri_enable()1266 void ide_pri_enable()
1267 {
1268 io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
1269 io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
1270 }
1271
ide_pri_disable()1272 void ide_pri_disable()
1273 {
1274 io_removehandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL);
1275 io_removehandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL);
1276 }
1277
ide_sec_enable()1278 void ide_sec_enable()
1279 {
1280 io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
1281 io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
1282 }
1283
ide_sec_disable()1284 void ide_sec_disable()
1285 {
1286 io_removehandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL);
1287 io_removehandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL);
1288 }
1289
ide_init()1290 static void *ide_init()
1291 {
1292 ide_pri_enable();
1293 ide_sec_enable();
1294
1295 timer_add(ide_callback_pri, &idecallback[0], &idecallback[0], NULL);
1296 timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL);
1297
1298 return (void *)-1;
1299 }
1300
ide_close(void * p)1301 static void ide_close(void *p)
1302 {
1303 }
1304
ide_set_bus_master(int (* read_data)(int channel,uint8_t * data,int size),int (* write_data)(int channel,uint8_t * data,int size),void (* set_irq)(int channel))1305 void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size), int (*write_data)(int channel, uint8_t *data, int size), void (*set_irq)(int channel))
1306 {
1307 ide_bus_master_read_data = read_data;
1308 ide_bus_master_write_data = write_data;
1309 ide_bus_master_set_irq = set_irq;
1310 }
1311
1312 device_t ide_device =
1313 {
1314 "Standard IDE",
1315 DEVICE_AT,
1316 ide_init,
1317 ide_close,
1318 NULL,
1319 NULL,
1320 NULL,
1321 NULL,
1322 NULL
1323 };
1324