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