Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openhackware / src / bloc.c
1 /*
2  * <bloc.c>
3  *
4  * Open Hack'Ware BIOS bloc devices management
5  * 
6  * Copyright (c) 2004-2005 Jocelyn Mayer
7  * 
8  *   This program is free software; you can redistribute it and/or
9  *   modify it under the terms of the GNU General Public License V2
10  *   as published by the Free Software Foundation
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include "bios.h"
25
26 #undef DPRINTF
27 #define DPRINTF(fmt, args...) do { } while (0)
28
29 struct bloc_device_t {
30     int device;
31     /* Hardware */
32     uint32_t io_base;
33     int drv;
34     /* Geometry */
35     int heads;
36     int trks;
37     int sects;
38     int seclen;
39     /* Position */
40     int bloc;
41     int vbloc;
42     int vpos;
43     /* Access */
44     int (*init)(bloc_device_t *bd, int device);
45     int (*read_sector)(bloc_device_t *bd, void *buffer, int secnum);
46     int (*ioctl)(bloc_device_t *bd, int func, void *args);
47     /* buffer */
48     char *buffer;
49     /* Private data */
50     int tmp;
51     void *private;
52 #ifdef USE_OPENFIRMWARE
53     void *OF_private;
54 #endif
55     /* Partitions */
56     part_t *parts, *bparts;
57     part_t *boot_part;
58     int bpartnum;
59     /* Chain */
60     bloc_device_t *next;
61 };
62
63 static bloc_device_t *bd_list;
64  
65 static int fdc_initialize (bloc_device_t *bd, int device);
66 static int fdc_read_sector (bloc_device_t *bd, void *buffer, int secnum);
67
68 static int ide_initialize (bloc_device_t *bd, int device);
69 static int ide_read_sector (bloc_device_t *bd, void *buffer, int secnum);
70 static int ide_reset (bloc_device_t *bd);
71
72 static int mem_initialize (bloc_device_t *bd, int device);
73 static int mem_read_sector (bloc_device_t *bd, void *buffer, int secnum);
74 static int mem_ioctl (bloc_device_t *bd, int func, void *args);
75
76 bloc_device_t *bd_open (int device)
77 {
78     bloc_device_t *bd;
79     int num;
80
81     bd = bd_get(device);
82     if (bd != NULL)
83         return bd;
84     bd = malloc(sizeof(bloc_device_t));
85     if (bd == NULL)
86         return NULL;
87     bd->ioctl = NULL;
88     switch (device) {
89     case 'a':
90         num = 0;
91         bd->init = &fdc_initialize;
92         bd->read_sector = &fdc_read_sector;
93         break;
94     case 'b':
95         num = 1;
96         bd->init = &fdc_initialize;
97         bd->read_sector = &fdc_read_sector;
98         break;
99     case 'c':
100         num = 0;
101         bd->init = &ide_initialize;
102         bd->read_sector = &ide_read_sector;
103         break;
104     case 'd':
105         num = 1;
106         bd->init = &ide_initialize;
107         bd->read_sector = &ide_read_sector;
108         break;
109     case 'e':
110         num = 2;
111         bd->init = &ide_initialize;
112         bd->read_sector = &ide_read_sector;
113         break;
114     case 'f':
115         num = 3;
116         bd->init = &ide_initialize;
117         bd->read_sector = &ide_read_sector;
118         break;
119     case 'm':
120         num = 0;
121         bd->init = &mem_initialize;
122         bd->read_sector = &mem_read_sector;
123         bd->ioctl = &mem_ioctl;
124         break;
125     default:
126         return NULL;
127     }
128     bd->bloc = -1;
129     if ((*bd->init)(bd, num) < 0) {
130         free(bd);
131         return NULL;
132     }
133     bd->buffer = malloc(bd->seclen);
134     if (bd->buffer == NULL) {
135         free(bd);
136         return NULL;
137     }
138     bd->device = device;
139
140     return bd;
141 }
142
143 int bd_seek (bloc_device_t *bd, uint32_t bloc, uint32_t pos)
144 {
145     uint32_t maxbloc;
146
147     maxbloc = bd_maxbloc(bd);
148     if (bloc > maxbloc) {
149         DPRINTF("%p bloc: %d maxbloc: %d C: %d H: %d S: %d\n",
150                 bd, bloc, maxbloc, bd->trks, bd->heads, bd->sects);
151         return -1;
152     }
153     bd->vbloc = bloc;
154     bd->vpos = pos;
155     DPRINTF("%s: %p %08x %08x %08x %08x %08x\n", __func__, bd, bloc, pos,
156             bd->bloc, bd->vbloc, bd->vpos);
157
158     return 0;
159 }
160
161 int bd_read (bloc_device_t *bd, void *buffer, int len)
162 {
163     int clen, total;
164
165     for (total = 0; len > 0; total += clen) {
166         if (bd->vbloc != bd->bloc) {
167             /* Do physical seek */
168 #if 0
169             DPRINTF("Read sector %d\n", bd->vbloc);
170 #endif
171             if ((*bd->read_sector)(bd, bd->buffer, bd->vbloc) < 0) {
172                 printf("Error reading bloc %d\n", bd->vbloc);
173                 return -1;
174             }
175             bd->bloc = bd->vbloc;
176         }
177         clen = bd->seclen - bd->vpos;
178         if (clen > len)
179             clen = len;
180         memcpy(buffer, bd->buffer + bd->vpos, clen);
181 #if 0
182         DPRINTF("%s: %p copy %d bytes (%08x %08x %08x) %08x %08x %08x %08x\n",
183                 __func__, bd, clen, bd->bloc, bd->vbloc, bd->vpos,
184                 ((uint32_t *)buffer)[0], ((uint32_t *)buffer)[1],
185                 ((uint32_t *)buffer)[2], ((uint32_t *)buffer)[3]);
186 #endif
187         bd->vpos += clen;
188         if (bd->vpos == bd->seclen) {
189             bd->vbloc++;
190             bd->vpos = 0;
191         }
192         buffer += clen;
193         len -= clen;
194     }
195
196     return total;
197 }
198
199 int bd_write (unused bloc_device_t *bd,
200               unused const void *buffer, unused int len)
201 {
202     return -1;
203 }
204
205 int bd_ioctl (bloc_device_t *bd, int func, void *args)
206 {
207     if (bd->ioctl == NULL)
208         return -1;
209
210     return (*bd->ioctl)(bd, func, args);
211 }
212
213 void bd_close (unused bloc_device_t *bd)
214 {
215 }
216
217 void bd_reset_all(void)
218 {
219     bloc_device_t *bd;
220     for (bd = bd_list; bd != NULL; bd = bd->next) {
221         if (bd->init == &ide_initialize) {
222             /* reset IDE drive because Darwin wants all IDE devices to be reset */
223             ide_reset(bd);
224         }
225     }
226 }
227
228 uint32_t bd_seclen (bloc_device_t *bd)
229 {
230     return bd->seclen;
231 }
232
233 uint32_t bd_maxbloc (bloc_device_t *bd)
234 {
235     return bd_CHS2sect(bd, bd->trks, 0, 1);
236 }
237
238 /* XXX: to be suppressed */
239 void bd_set_boot_part (bloc_device_t *bd, part_t *partition, int partnum)
240 {
241     dprintf("%s: part %p (%p) %d\n", __func__, partition, bd->boot_part, partnum);
242     if (bd->boot_part == NULL) {
243         bd->boot_part = partition;
244         bd->bpartnum = partnum;
245     }
246 }
247
248 part_t **_bd_parts (bloc_device_t *bd)
249 {
250     return &bd->parts;
251 }
252
253 part_t **_bd_bparts (bloc_device_t *bd)
254 {
255     return &bd->bparts;
256 }
257
258 void bd_set_boot_device (bloc_device_t *bd)
259 {
260 #if defined (USE_OPENFIRMWARE)
261     OF_blockdev_set_boot_device(bd->OF_private, bd->bpartnum, "\\\\ofwboot");
262 #endif
263 }
264
265 part_t *bd_probe (int boot_device)
266 {
267     char devices[] = { /*'a', 'b',*/ 'c', 'd', 'e', 'f', 'm', '\0', };
268     bloc_device_t *bd, **cur;
269     part_t *boot_part, *tmp;
270     int i, force_raw;
271
272     boot_part = NULL;
273     /* Probe bloc devices */
274     for (i = 0; devices[i] != '\0'; i++) {
275         if (devices[i] == 'm' && boot_device != 'm')
276             break;
277         bd = bd_open(devices[i]);
278         if (bd != NULL) {
279             DPRINTF("New bloc device %c: %p\n", devices[i], bd);
280             for (cur = &bd_list; *cur != NULL; cur = &(*cur)->next)
281                 continue;
282             *cur = bd;
283         } else {
284             DPRINTF("No bloc device %c\n", devices[i]);
285         }
286     }
287     /* Probe partitions for each bloc device found */
288     for (bd = bd_list; bd != NULL; bd = bd->next) {
289         dprintf("Probe partitions for device %c\n", bd->device);
290         if (bd->device == 'm')
291             force_raw = 1;
292         else
293             force_raw = 0;
294         tmp = part_probe(bd, force_raw);
295         if (boot_device == bd->device) {
296             boot_part = tmp;
297             bd_set_boot_device(bd);
298         }
299     }
300
301     return boot_part;
302 }
303
304 bloc_device_t *bd_get (int device)
305 {
306     bloc_device_t *cur;
307
308     for (cur = bd_list; cur != NULL; cur = cur->next) {
309         if (cur->device == device) {
310             DPRINTF("%s: found device %c: %p\n", __func__, device, cur);
311             return cur;
312         }
313     }
314
315     return NULL;
316 }
317
318 void bd_put (unused bloc_device_t *bd)
319 {
320 }
321
322 void bd_sect2CHS (bloc_device_t *bd, uint32_t secnum,
323                   int *cyl, int *head, int *sect)
324 {
325     uint32_t tmp;
326
327     tmp = secnum / bd->sects;
328     *sect = secnum - (tmp * bd->sects) + 1;
329     *cyl = tmp / bd->heads;
330     *head = tmp - (*cyl * bd->heads);
331 }
332
333 uint32_t bd_CHS2sect (bloc_device_t *bd,
334                       int cyl, int head, int sect)
335 {
336     return (((cyl * bd->heads) + head) * bd->sects) + sect - 1;
337 }
338
339 /* Floppy driver */
340 #define FDC_OUT_BASE    (0x03F0)
341 #define FDC_DOR_PORT    (FDC_OUT_BASE + 0x0002)
342 #define FDC_TAPE_PORT   (FDC_OUT_BASE + 0x0003)
343 #define FDC_MAIN_STATUS (FDC_OUT_BASE + 0x0004)
344 #define FDC_WRITE_PORT  (FDC_OUT_BASE + 0x0005)
345 #define FDC_READ_PORT   (FDC_OUT_BASE + 0x0005)
346
347 static int fdc_read_data (uint8_t *addr, int len)
348 {
349     uint8_t status;
350     int i;
351
352     for (i = 0; i < len; i++) {
353         status = inb(FDC_MAIN_STATUS);
354         if ((status & 0xD0) != 0xD0) {
355 #if 0
356             ERROR("fdc_read_data: read data status != READ_DATA: %0x\n",
357                   status);
358 #endif
359             return -1;
360         }
361         addr[i] = inb(FDC_READ_PORT);
362     }
363
364     return 0;
365 }
366
367 static inline int fdc_write_cmd (uint8_t cmd)
368 {
369     uint8_t status;
370
371     status = inb(FDC_MAIN_STATUS);
372     if ((status & 0xC0) != 0x80) {
373 #if 0
374         ERROR("fdc_write_cmd: read data status != WRITE_CMD: %0x\n",
375               status);
376 #endif
377         return -1;
378     }
379     outb(FDC_WRITE_PORT, cmd);
380
381     return 0;
382 }
383
384 static int fdc_reset (void)
385 {
386     uint8_t dor;
387     
388     dor = inb(FDC_DOR_PORT);
389     /* Stop motors & enter reset */
390     dor &= ~0x34;
391     outb(FDC_DOR_PORT, dor);
392     usleep(1000);
393     /* leave reset state */
394     dor |= 0x04;
395     outb(FDC_DOR_PORT, dor);
396     usleep(1000);
397
398     return 0;
399 }
400
401 static int fdc_recalibrate (int drv)
402 {
403     uint8_t data[2];
404
405     if (drv == 0)
406         data[0] = 0;
407     else
408         data[0] = 1;
409     if (fdc_write_cmd(0x07) < 0) {
410         ERROR("fdc_recalibrate != WRITE_CMD\n");
411         return -1;
412     }
413     if (fdc_write_cmd(data[0]) < 0) {
414         ERROR("fdc_recalibrate data\n");
415         return -1;
416     }
417     /* Wait for drive to go out of busy state */
418     while ((inb(FDC_MAIN_STATUS) & 0x0F) != 0x00)
419         continue;
420     /* Check command status */
421     if (fdc_write_cmd(0x08) < 0) {
422         ERROR("fdc_recalibrate != SENSE_INTERRUPT_STATUS\n");
423         return -1;
424     }
425     data[0] = inb(FDC_READ_PORT);
426     data[1] = inb(FDC_READ_PORT);
427     if (data[0] & 0xD0) {
428         /* recalibrate / seek failed */
429         return -1;
430     }
431     /* Status should be WRITE_CMD right now */
432     if ((inb(FDC_MAIN_STATUS) & 0xD0) != 0x80) {
433         ERROR("fdc_recalibrate status\n");
434         return -1;
435     }
436
437     return 0;
438 }
439
440 static int fdc_start_read (int drv, uint8_t hd, uint8_t trk, uint8_t sect,
441                            int mt)
442 {
443     uint8_t fdc_cmd[9], status;
444     int i;
445     
446     fdc_cmd[0] = 0x66;
447     if (mt)
448         fdc_cmd[0] |= 0x80;
449     fdc_cmd[1] = 0x00;
450     if (hd)
451         fdc_cmd[1] |= 0x04;
452     if (drv)
453         fdc_cmd[1] |= 0x01;
454     fdc_cmd[2] = trk;
455     fdc_cmd[3] = hd;
456     fdc_cmd[4] = sect;
457     fdc_cmd[5] = 0x02;
458     fdc_cmd[6] = 0x12;
459     fdc_cmd[7] = 0x00;
460     fdc_cmd[8] = 0x00;
461     for (i = 0; i < (int)sizeof(fdc_cmd); i++) {
462         status = inb(FDC_MAIN_STATUS);
463         if ((status & 0xC0) != 0x80) {
464             ERROR("fdc_start_read: write command status != WRITE_CMD: %0x\n",
465                   status);
466             return -1;
467         }
468         outb(FDC_WRITE_PORT, fdc_cmd[i]);
469     }
470     status = inb(FDC_MAIN_STATUS);
471     if ((status & 0xD0) != 0xD0) {
472         ERROR("fdc_read_sector: status != READ_DATA: %0x\n", status);
473         return -1;
474     }
475
476     return 0;
477 }
478
479 /* FDC driver entry points */
480 static int fdc_initialize (bloc_device_t *bd, int device)
481 {
482     uint8_t fifo[10];
483 #if 0
484     uint32_t tape;
485 #endif
486     int status;
487
488     if (device > 1)
489         return -1;
490     DPRINTF("Init FDC drive %d\n", device);
491     /* Manage 1.44 MB disks only, for now */
492     bd->drv = device;
493     bd->heads = 2;
494     bd->trks = 80;
495     bd->sects = 18;
496     bd->seclen = 512;
497     bd->tmp = -1;
498     fdc_reset();
499     /* Dump registers */
500     if (fdc_write_cmd(0x0E) < 0) {
501 #if 0
502         ERROR("fdc_reset: DUMP_REGISTER != WRITE_CMD\n");
503 #endif
504         return -1;
505     }
506     if (fdc_read_data(fifo, 10) < 0) {
507         ERROR("fdc_reset: DUMP_REGISTER data\n");
508         return -1;
509     }
510     /* SPECIFY: be sure we're not in DMA mode */
511     if (fdc_write_cmd(0x03) < 0) {
512         ERROR("fdc_reset: SPECIFY != WRITE_CMD\n");
513         return -1;
514     }
515     if (fdc_write_cmd(fifo[4]) < 0 || fdc_write_cmd(fifo[5] | 0x01)) {
516         ERROR("fdc_reset: SPECIFY data\n");
517         return -1;
518     }
519     /* Status should be WRITE_CMD right now */
520     status = inb(FDC_MAIN_STATUS);
521     if ((status & 0xD0) != 0x80) {
522         ERROR("fdc_initialise: read data status != WRITE_CMD: %0x\n",
523                status);
524         return -1;
525     }
526     /* RECALIBRATE */
527     if (fdc_recalibrate(device) < 0) {
528         printf("fd%c: no floppy inserted\n", 'a' + device);
529         return -1;
530     }
531     printf("fd%c initialized\n", 'a' + device);
532
533     return 0;
534 }
535
536 static int fdc_read_sector (bloc_device_t *bd, void *buffer, int secnum)
537 {
538     int head, cyl, sect;
539     int need_restart;
540
541 #if DEBUG_BIOS > 1
542     printf("Read fdc sector: %d at: %0x\n", secnum, (uint32_t)buffer);
543     bd_sect2CHS(bd, secnum, &cyl, &head, &sect);
544     printf("cur: %d hd: %d trk: %d sect: %d\n", bd->bloc, head, cyl, sect);
545 #endif
546     if (secnum != bd->tmp) {
547         if (fdc_reset() < 0 || fdc_recalibrate(bd->drv) < 0)
548             return -1;
549         need_restart = 1;
550     } else {
551         need_restart = 0;
552     }
553     bd_sect2CHS(bd, secnum, &cyl, &head, &sect);
554     if (need_restart == 1 || (head == 0 && sect == 1)) {
555         if (need_restart == 0) {
556             /* Read the status */
557             uint8_t tmp[7];
558
559             while (fdc_read_data(tmp, 1) == 0)
560                 continue;
561         }
562 #if !defined (DEBUG_BIOS)
563         printf(".");
564 #endif
565         if (fdc_start_read(bd->drv, head, cyl, sect, 1) < 0)
566             return -1;
567         bd->bloc = secnum;
568         bd->tmp = secnum;
569     }
570     if (fdc_read_data(buffer, bd->seclen) < 0)
571         return -1;
572     bd->tmp++;
573
574     return bd->seclen;
575 }
576
577 /* SCSI subset */
578 /* SPC: primary commands, common to all devices */
579 static int spc_inquiry_req (void *buffer, int maxlen)
580 {
581     uint8_t *p;
582     
583     p = buffer;
584     p[0] = 0x12;
585     /* No page code */
586     p[1] = 0x00;
587     p[2] = 0x00;
588     p[3] = maxlen >> 8;
589     p[4] = maxlen;
590     p[5] = 0x00;
591
592     return 6;
593 }
594
595 static int spc_inquiry_treat (void *buffer, int len)
596 {
597     const uint8_t *p;
598
599     if (len < 36)
600         return -1;
601     p = buffer;
602     if ((p[0] >> 5) != 0) {
603         ERROR("Logical unit not ready\n");
604         return -1;
605     }
606
607     return p[0] & 0x1F;
608 }
609
610 static int spc_test_unit_ready_req (void *buffer)
611 {
612     uint8_t *p;
613     
614     p = buffer;
615     p[0] = 0x00;
616     p[1] = 0x00;
617     p[2] = 0x00;
618     p[3] = 0x00;
619     p[4] = 0x00;
620     p[5] = 0x00;
621
622     return 6;
623 }
624
625 /* MMC: multimedia commands */
626 static int mmc_read_capacity_req (void *buffer)
627 {
628     uint8_t *p;
629     
630     p = buffer;
631     p[0] = 0x25;
632     p[1] = 0x00;
633     p[2] = 0x00;
634     p[3] = 0x00;
635     p[4] = 0x00;
636     p[5] = 0x00;
637     p[6] = 0x00;
638     p[7] = 0x00;
639     p[8] = 0x00;
640     p[9] = 0x00;
641
642     return 10;
643 }
644
645 static int mmc_read_capacity_treat (uint32_t *size, uint32_t *ssize,
646                                     const void *buffer, int len)
647 {
648     const uint8_t *p;
649     
650     if (len != 8)
651         return -1;
652     p = buffer;
653     /* Only handle CDROM address mode for now */
654     *size = ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) + 1;
655     *ssize = ((p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]);
656
657     return 0;
658 }
659
660 static int mmc_read12_req (void *buffer, uint32_t LBA, uint32_t size)
661 {
662     uint8_t *p;
663     
664     p = buffer;
665     p[0] = 0xA8;
666     p[1] = 0x00;
667     p[2] = LBA >> 24;
668     p[3] = LBA >> 16;
669     p[4] = LBA >> 8;
670     p[5] = LBA;
671     p[6] = size >> 24;
672     p[7] = size >> 16;
673     p[8] = size >> 8;
674     p[9] = size;
675     p[10] = 0x00;
676     p[11] = 0x00;
677
678     return 12;
679 }
680
681 /* IDE disk driver */
682 static uint32_t ide_base[2] = { 0x1F0, 0x170, };
683 static uint32_t ide_base2[2] = { 0x3F6, 0x376, };
684
685 typedef struct ide_ops_t {
686     uint8_t (*port_read)(bloc_device_t *bd, int port);
687     void (*port_write)(bloc_device_t *bd, int port, uint8_t value);
688     uint32_t (*data_readl)(bloc_device_t *bd);
689     void (*data_writel)(bloc_device_t *bd, uint32_t val);
690     void (*control_write)(bloc_device_t *bd, uint32_t val);
691     uint32_t base[4];
692 #ifdef USE_OPENFIRMWARE
693     void *OF_private[2];
694 #endif
695 } ide_ops_t;
696
697 /* IDE ISA access */
698 static uint8_t ide_isa_port_read (bloc_device_t *bd, int port)
699 {
700     return inb(bd->io_base + port);
701 }
702
703 static void ide_isa_port_write (bloc_device_t *bd, int port, uint8_t value)
704 {
705     outb(bd->io_base + port, value);
706 }
707
708 static uint32_t ide_isa_data_readl (bloc_device_t *bd)
709 {
710     return inl(bd->io_base);
711 }
712
713 static void ide_isa_data_writel (bloc_device_t *bd, uint32_t val)
714 {
715     return outl(bd->io_base, val);
716 }
717
718 static void ide_isa_control_write (bloc_device_t *bd, uint32_t val)
719 {
720     outb(bd->tmp, val);
721 }
722
723 static ide_ops_t ide_isa_ops = {
724     &ide_isa_port_read,
725     &ide_isa_port_write,
726     &ide_isa_data_readl,
727     &ide_isa_data_writel,
728     &ide_isa_control_write,
729     { 0, },
730 #ifdef USE_OPENFIRMWARE
731     { NULL, },
732 #endif
733 };
734
735 static ide_ops_t *ide_pci_ops;
736
737 /* IDE PCI access for pc */
738 static uint8_t ide_pci_port_read (bloc_device_t *bd, int port)
739 {
740     uint8_t value;
741     value = inb(bd->io_base + port);
742     return value;
743 }
744
745 static void ide_pci_port_write (bloc_device_t *bd, int port, uint8_t value)
746 {
747     outb(bd->io_base + port, value);
748 }
749
750 static uint32_t ide_pci_data_readl (bloc_device_t *bd)
751 {
752     return inl(bd->io_base);
753 }
754
755 static void ide_pci_data_writel (bloc_device_t *bd, uint32_t val)
756 {
757     outl(bd->io_base, val);
758 }
759
760 static void ide_pci_control_write (bloc_device_t *bd, uint32_t val)
761 {
762     outb(bd->tmp + 2, val);
763 }
764
765 static ide_ops_t ide_pci_pc_ops = {
766     &ide_pci_port_read,
767     &ide_pci_port_write,
768     &ide_pci_data_readl,
769     &ide_pci_data_writel,
770     &ide_pci_control_write,
771     { 0, },
772 #ifdef USE_OPENFIRMWARE
773     { NULL, },
774 #endif
775 };
776
777 void ide_pci_pc_register (uint32_t io_base0, uint32_t io_base1,
778                           uint32_t io_base2, uint32_t io_base3,
779                           void *OF_private0, void *OF_private1)
780 {
781     if (ide_pci_ops == NULL) {
782         ide_pci_ops = malloc(sizeof(ide_ops_t));
783         if (ide_pci_ops == NULL)
784             return;
785         memcpy(ide_pci_ops, &ide_pci_pc_ops, sizeof(ide_ops_t));
786     }
787     if ((io_base0 != 0 || io_base1 != 0) &&
788         ide_pci_ops->base[0] == 0 && ide_pci_ops->base[2] == 0) {
789         ide_pci_ops->base[0] = io_base0;
790         ide_pci_ops->base[2] = io_base1;
791 #ifdef USE_OPENFIRMWARE
792         ide_pci_ops->OF_private[0] = OF_private0;
793 #endif
794     }
795     if ((io_base2 != 0 || io_base3 != 0) &&
796         ide_pci_ops->base[1] == 0 && ide_pci_ops->base[3] == 0) {
797         ide_pci_ops->base[1] = io_base2;
798         ide_pci_ops->base[3] = io_base3;
799 #ifdef USE_OPENFIRMWARE
800         ide_pci_ops->OF_private[1] = OF_private1;
801 #endif
802     }
803 }
804
805 /* IDE PCI access for pmac */
806 static uint8_t ide_pmac_port_read (bloc_device_t *bd, int port)
807 {
808     uint32_t addr;
809
810     if (port != 8)
811         addr = bd->io_base + (port << 4);
812     else
813         addr = bd->io_base + 0x160;
814     eieio();
815     
816     return *((uint8_t *)addr);
817 }
818
819 static void ide_pmac_port_write (bloc_device_t *bd, int port, uint8_t value)
820 {
821     uint32_t addr;
822
823     if (port != 8)
824         addr = bd->io_base + (port << 4);
825     else
826         addr = bd->io_base + 0x160;
827     *((uint8_t *)addr) = value;
828     eieio();
829 }
830
831 static uint32_t ide_pmac_data_readl (bloc_device_t *bd)
832 {
833     eieio();
834     return ldswap32((uint32_t *)bd->io_base);
835     //    return *((uint32_t *)bd->io_base);
836 }
837
838 static void ide_pmac_data_writel (bloc_device_t *bd, uint32_t val)
839 {
840     //    *((uint32_t *)bd->io_base) = val;
841     stswap32((uint32_t *)bd->io_base, val);
842     eieio();
843 }
844
845 static void ide_pmac_control_write (bloc_device_t *bd, uint32_t val)
846 {
847     ide_pmac_port_write(bd, 8, val);
848 }
849
850 static ide_ops_t ide_pmac_ops = {
851     &ide_pmac_port_read,
852     &ide_pmac_port_write,
853     &ide_pmac_data_readl,
854     &ide_pmac_data_writel,
855     &ide_pmac_control_write,
856     { 0, },
857 #ifdef USE_OPENFIRMWARE
858     { NULL, },
859 #endif
860 };
861
862 void ide_pci_pmac_register (uint32_t io_base0, uint32_t io_base1,
863                             unused void *OF_private)
864 {
865     if (ide_pci_ops == NULL) {
866         ide_pci_ops = malloc(sizeof(ide_ops_t));
867         if (ide_pci_ops == NULL)
868             return;
869         memcpy(ide_pci_ops, &ide_pmac_ops, sizeof(ide_ops_t));
870     }
871     if (io_base0 != 0 && ide_pci_ops->base[0] == 0) {
872         ide_pci_ops->base[0] = io_base0;
873 #ifdef USE_OPENFIRMWARE
874         ide_pci_ops->OF_private[0] = OF_private;
875 #endif
876     }
877     if (io_base1 != 0 && ide_pci_ops->base[1] == 0) {
878         ide_pci_ops->base[1] = io_base1;
879 #ifdef USE_OPENFIRMWARE
880         ide_pci_ops->OF_private[1] = OF_private;
881 #endif
882     }
883 }
884
885 static inline uint8_t ide_port_read (bloc_device_t *bd, int port)
886 {
887     ide_ops_t *ops = bd->private;
888     
889     return ops->port_read(bd, port);
890 }
891
892 static inline void ide_port_write (bloc_device_t *bd, int port, uint8_t value)
893 {
894     ide_ops_t *ops = bd->private;
895     
896     ops->port_write(bd, port, value);
897 }
898
899 static inline uint32_t ide_data_readl (bloc_device_t *bd)
900 {
901     ide_ops_t *ops = bd->private;
902     
903     return ops->data_readl(bd);
904 }
905
906 static inline void ide_data_writel (bloc_device_t *bd, uint32_t val)
907 {
908     ide_ops_t *ops = bd->private;
909     
910     return ops->data_writel(bd, val);
911 }
912
913 static inline void ide_control_write (bloc_device_t *bd, uint32_t val)
914 {
915     ide_ops_t *ops = bd->private;
916     
917     return ops->control_write(bd, val);
918 }
919
920 static int ide_reset (bloc_device_t *bd)
921 {
922     int status, is_cdrom, lcyl;
923
924     ide_control_write(bd, 0x04);
925     status = ide_port_read(bd, 0x07);
926     if (status != 0x90) {
927         return -1;
928     }
929     ide_control_write(bd, 0x00);
930     if (bd->drv == 0)
931         ide_port_write(bd, 0x06, 0xa0);
932     else
933         ide_port_write(bd, 0x06, 0xb0);
934
935     lcyl = ide_port_read(bd, 0x04);
936     switch (lcyl) {
937     case 0x00:
938         /* IDE drive */
939         is_cdrom = 0;
940         break;
941     case 0x14:
942         /* ATAPI device */
943         is_cdrom = 1;
944         break;
945     default:
946         return -1;
947     }
948
949     return is_cdrom;
950 }
951
952 static void atapi_pad_req (void *buffer, int len);
953 static void atapi_make_req (bloc_device_t *bd, uint32_t *buffer,
954                             int maxlen);
955 static int atapi_read_sector (bloc_device_t *bd, void *buffer, int secnum);
956
957 static int ide_initialize (bloc_device_t *bd, int device)
958 {
959 #ifdef USE_OPENFIRMWARE
960     void *OF_parent;
961 #endif
962     const unsigned char *devname, *devtype, *alias;
963     uint32_t atapi_buffer[9];
964     uint32_t size;
965     int status, base, is_cdrom, len, i;
966
967     if (device > 1)
968         base = 1;
969     else
970         base = 0;
971     if (ide_pci_ops != NULL) {
972         bd->private = ide_pci_ops;
973         bd->io_base = ide_pci_ops->base[base];
974         bd->tmp = ide_pci_ops->base[2 + base];
975         if (bd->io_base == 0x00000000 || bd->io_base == 0xFFFFFFFF) {
976             ERROR("No IDE drive %c\n", device);
977             return -1;
978         }
979     } else {
980         bd->private = &ide_isa_ops;
981         bd->io_base = ide_base[base];
982         bd->tmp = ide_base2[base];
983     }
984     bd->drv = device & 1;
985     DPRINTF("Init IDE drive %d-%d (%d)\n", base, bd->drv, device);
986     is_cdrom = ide_reset(bd);
987     printf("ide%d: drive %d: ",
988            (device >> 1), bd->drv);
989     switch(is_cdrom) {
990     case 0:
991         printf("Hard Disk\n");
992         devname = "disk";
993         devtype = "hd";
994         alias = "hd";
995         break;
996     case 1:
997         printf("CD-ROM\n");
998         devname = "cdrom";
999         devtype = "cdrom";
1000         alias = "cd";
1001         break;
1002     default:
1003         printf("none\n");
1004         devname = NULL;
1005         devtype = NULL;
1006         alias = NULL;
1007         break;
1008     }
1009     if (is_cdrom < 0)
1010         return -1;
1011 #ifdef USE_OPENFIRMWARE
1012     /* Register disk into OF tree */
1013     OF_parent = ide_pci_ops->OF_private[base];
1014     if (OF_parent != NULL) {
1015         bd->OF_private = OF_blockdev_register(OF_parent, bd, devtype,
1016                                               devname, bd->drv, alias);
1017     }
1018 #endif
1019     /* Select drive */
1020     if (bd->drv == 0)
1021         ide_port_write(bd, 0x06, 0x40);
1022     else
1023         ide_port_write(bd, 0x06, 0x50);
1024     /* WIN_DEVICE_RESET */
1025     ide_port_write(bd, 0x07, 0x08);
1026     status = ide_port_read(bd, 0x07);
1027     if (is_cdrom) {
1028         if (status != 0x00) {
1029             ERROR("WIN_DEVICE_RESET : status %0x != 0x00 (is_cdrom: %d)\n",
1030                   status, is_cdrom);
1031             return -1;
1032         }
1033         /* TEST_UNIT_READY */
1034         DPRINTF("TEST_UNIT_READY\n");
1035         len = spc_test_unit_ready_req(&atapi_buffer);
1036         atapi_pad_req(&atapi_buffer, len);
1037         ide_port_write(bd, 0x07, 0xA0);
1038         status = ide_port_read(bd, 0x07);
1039         if (status != 0x08) {
1040             ERROR("ATAPI TEST_UNIT_READY : status %0x != 0x08\n", status);
1041             /*return -1;*/ /* fails to boot from cdrom? */
1042         }
1043         for (i = 0; i < 3; i++) {
1044             ide_data_writel(bd, ldswap32(&atapi_buffer[i]));
1045         }
1046         status = ide_port_read(bd, 0x07);
1047         if (status != 0x40) {
1048             ERROR("ATAPI TEST_UNIT_READY : status %0x != 0x40\n", status);
1049             return -1;
1050         }
1051         /* INQUIRY */
1052         DPRINTF("INQUIRY\n");
1053         len = spc_inquiry_req(&atapi_buffer, 36);
1054         atapi_pad_req(&atapi_buffer, len);
1055         atapi_make_req(bd, atapi_buffer, 36);
1056         status = ide_port_read(bd, 0x07);
1057         if (status != 0x48) {
1058             ERROR("ATAPI INQUIRY : status %0x != 0x48\n", status);
1059             return -1;
1060         }
1061         for (i = 0; i < 9; i++)
1062             stswap32(&atapi_buffer[i], ide_data_readl(bd));
1063         if (spc_inquiry_treat(&atapi_buffer, 36) != 0x05) {
1064             ERROR("Only ATAPI CDROMs are handled for now\n");
1065             return -1;
1066         }
1067         /* READ_CAPACITY */
1068         DPRINTF("READ_CAPACITY\n");
1069         len = mmc_read_capacity_req(&atapi_buffer);
1070         atapi_pad_req(&atapi_buffer, len);
1071         atapi_make_req(bd, atapi_buffer, 8);
1072         status = ide_port_read(bd, 0x07);
1073         if (status != 0x48) {
1074             ERROR("ATAPI READ_CAPACITY : status %0x != 0x48\n", status);
1075             return -1;
1076         }
1077         for (i = 0; i < 2; i++)
1078             stswap32(&atapi_buffer[i], ide_data_readl(bd));
1079         if (mmc_read_capacity_treat(&size, &bd->seclen,
1080                                     &atapi_buffer, 8) != 0) {
1081             ERROR("Error retrieving ATAPI CDROM capacity\n");
1082             return -1;
1083         }
1084         bd->read_sector = &atapi_read_sector;
1085         DPRINTF("ATAPI: size=%d ssize=%d\n", size, bd->seclen);
1086     } else {
1087         if (status != 0x41) {
1088             ERROR("WIN_DEVICE_RESET : status %0x != 0x41 (is_cdrom: %d)\n",
1089                   status, is_cdrom);
1090             return -1;
1091         }
1092         /* WIN_READ_NATIVE_MAX */
1093         ide_port_write(bd, 0x07, 0xF8);
1094         status = ide_port_read(bd, 0x07);
1095         if (status != 0x40) {
1096             ERROR("WIN_READ_NATIVE_MAX : status %0x != 0x40\n", status);
1097             return -1;
1098         }
1099         /* Retrieve parameters */
1100         size = (ide_port_read(bd, 0x06) & ~0xF0) << 24;
1101         size |= ide_port_read(bd, 0x05) << 16;
1102         size |= ide_port_read(bd, 0x04) << 8;
1103         size |= ide_port_read(bd, 0x03);
1104         bd->seclen = 512;
1105     } 
1106     bd->heads = 16;
1107     bd->sects = 64;
1108     bd->trks = (size + (16 * 64 - 1)) >> 10;
1109    
1110     return 0;
1111 }
1112
1113 static void atapi_pad_req (void *buffer, int len)
1114 {
1115     uint8_t *p;
1116
1117     p = buffer;
1118     memset(p + len, 0, 12 - len);
1119 }
1120
1121 static void atapi_make_req (bloc_device_t *bd, uint32_t *buffer,
1122                             int maxlen)
1123 {
1124     int i;
1125     /* select drive */
1126     if (bd->drv == 0)
1127         ide_port_write(bd, 0x06, 0x40);
1128     else
1129         ide_port_write(bd, 0x06, 0x50);
1130     ide_port_write(bd, 0x04, maxlen & 0xff);
1131     ide_port_write(bd, 0x05, (maxlen >> 8) & 0xff);
1132     ide_port_write(bd, 0x07, 0xA0);
1133     for (i = 0; i < 3; i++)
1134         ide_data_writel(bd, ldswap32(&buffer[i]));
1135 }
1136
1137 static int atapi_read_sector (bloc_device_t *bd, void *buffer, int secnum)
1138 {
1139     uint32_t atapi_buffer[4];
1140     uint8_t *p;
1141     uint32_t status, value;
1142     int i, len;
1143
1144     len = mmc_read12_req(atapi_buffer, secnum, 1);
1145     atapi_pad_req(&atapi_buffer, len);
1146     atapi_make_req(bd, atapi_buffer, bd->seclen);
1147     status = ide_port_read(bd, 0x07);
1148     if (status != 0x48) {
1149         ERROR("ATAPI READ12 : status %0x != 0x48\n", status);
1150         return -1;
1151     }
1152     p = buffer;
1153     for (i = 0; i < bd->seclen; i += 4) {
1154         value = ide_data_readl(bd);
1155         *p++ = value;
1156         *p++ = value >> 8;
1157         *p++ = value >> 16;
1158         *p++ = value >> 24;
1159     }
1160     status = ide_port_read(bd, 0x07);
1161     if (status != 0x40) {
1162         ERROR("ATAPI READ12 done : status %0x != 0x48\n", status);
1163         return -1;
1164     }
1165
1166     return 0;
1167 }
1168
1169 static int ide_read_sector (bloc_device_t *bd, void *buffer, int secnum)
1170 {
1171     uint32_t value;
1172     uint8_t *p;
1173     int status;
1174     int i;
1175     
1176     bd->drv &= 1;
1177     //    printf("ide_read_sector: drv %d secnum %d buf %p\n", bd->drv, secnum, buffer);
1178     /* select drive & set highest bytes */
1179     if (bd->drv == 0)
1180         ide_port_write(bd, 0x06, 0x40 | (secnum >> 24));
1181     else
1182         ide_port_write(bd, 0x06, 0x50 | (secnum >> 24));
1183     /* Set hcyl */
1184     ide_port_write(bd, 0x05, secnum >> 16);
1185     /* Set lcyl */
1186     ide_port_write(bd, 0x04, secnum >> 8);
1187     /* Set sect */
1188     ide_port_write(bd, 0x03, secnum);
1189     /* Read 1 sector */
1190     ide_port_write(bd, 0x02, 1);
1191     /* WIN_READ */
1192     ide_port_write(bd, 0x07, 0x20);
1193     status = ide_port_read(bd, 0x07);
1194     //    DPRINTF("ide_read_sector: try %d\n", secnum);
1195     if (status != 0x58) {
1196         ERROR("ide_read_sector: %d status %0x != 0x58\n", secnum, status);
1197         return -1;
1198     }
1199     /* Get data */
1200     p = buffer;
1201     for (i = 0; i < bd->seclen; i += 4) {
1202         value = ide_data_readl(bd);
1203         *p++ = value;
1204         *p++ = value >> 8;
1205         *p++ = value >> 16;
1206         *p++ = value >> 24;
1207     }
1208     status = ide_port_read(bd, 0x07);
1209     if (status != 0x50) {
1210         ERROR("ide_read_sector 6: status %0x != 0x50\n", status);
1211         return -1;
1212     }
1213
1214     return bd->seclen;
1215 }
1216
1217 /* Memory image access driver */
1218 static int mem_initialize (bloc_device_t *bd, int device)
1219 {
1220     bd->seclen = 512;
1221     bd->private = NULL;
1222     bd->heads = 1;
1223     bd->sects = 1;
1224     bd->trks = 1;
1225
1226     return device == 'm';
1227 }
1228
1229 static int mem_read_sector (bloc_device_t *bd, void *buffer, int secnum)
1230 {
1231     if (buffer != (char *)bd->private + (bd->seclen * secnum)) {
1232         memmove(buffer,
1233                 (char *)bd->private + (bd->seclen * secnum), bd->seclen);
1234     }
1235
1236     return bd->seclen;
1237 }
1238
1239 static int mem_ioctl (bloc_device_t *bd, int func, void *args)
1240 {
1241     uint32_t *u32;
1242     int ret;
1243
1244     switch (func) {
1245     case MEM_SET_ADDR:
1246         bd->private = args;
1247         ret = 0;
1248         break;
1249     case MEM_SET_SIZE:
1250         u32 = args;
1251         bd->trks = (*u32 + bd->seclen - 1) / bd->seclen + 1;
1252     default:
1253         ret = -1;
1254         break;
1255     }
1256
1257     return ret;
1258 }