Ia64: stop passing in global variable as argument to cmos_init()
[qemu-kvm/amd-iommu.git] / hw / extboot.c
blob056fb59feb7e269888374f892f410abe36bb226e
1 /*
2 * Extended boot option ROM support.
4 * Copyright IBM, Corp. 2007
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
14 #include "hw.h"
15 #include "pc.h"
16 #include "isa.h"
17 #include "block.h"
19 /* Extended Boot ROM suport */
21 union extboot_cmd
23 uint16_t type;
24 struct {
25 uint16_t type;
26 uint16_t cylinders;
27 uint16_t heads;
28 uint16_t sectors;
29 uint64_t nb_sectors;
30 } query_geometry;
31 struct {
32 uint16_t type;
33 uint16_t nb_sectors;
34 uint16_t segment;
35 uint16_t offset;
36 uint64_t sector;
37 } xfer;
40 static void get_translated_chs(BlockDriverState *bs, int *c, int *h, int *s)
42 bdrv_get_geometry_hint(bs, c, h, s);
44 if (*c <= 1024) {
45 *c >>= 0;
46 *h <<= 0;
47 } else if (*c <= 2048) {
48 *c >>= 1;
49 *h <<= 1;
50 } else if (*c <= 4096) {
51 *c >>= 2;
52 *h <<= 2;
53 } else if (*c <= 8192) {
54 *c >>= 3;
55 *h <<= 3;
56 } else {
57 *c >>= 4;
58 *h <<= 4;
61 /* what is the correct algorithm for this?? */
62 if (*h == 256) {
63 *h = 255;
64 *c = *c + 1;
68 static uint32_t extboot_read(void *opaque, uint32_t addr)
70 int *pcmd = opaque;
71 return *pcmd;
74 static void extboot_write_cmd(void *opaque, uint32_t addr, uint32_t value)
76 union extboot_cmd *cmd = (void *)(phys_ram_base + ((value & 0xFFFF) << 4));
77 BlockDriverState *bs = opaque;
78 int cylinders, heads, sectors, err;
79 int64_t nb_sectors;
81 get_translated_chs(bs, &cylinders, &heads, &sectors);
83 if (cmd->type == 0x01 || cmd->type == 0x02) {
84 target_ulong pa = cmd->xfer.segment * 16 + cmd->xfer.segment;
86 /* possible buffer overflow */
87 if ((pa + cmd->xfer.nb_sectors * 512) > phys_ram_size)
88 return;
91 switch (cmd->type) {
92 case 0x00:
93 bdrv_get_geometry(bs, &nb_sectors);
94 cmd->query_geometry.cylinders = cylinders;
95 cmd->query_geometry.heads = heads;
96 cmd->query_geometry.sectors = sectors;
97 cmd->query_geometry.nb_sectors = nb_sectors;
98 cpu_physical_memory_set_dirty((value & 0xFFFF) << 4);
99 break;
100 case 0x01:
101 err = bdrv_read(bs, cmd->xfer.sector, phys_ram_base +
102 cmd->xfer.segment * 16 + cmd->xfer.offset,
103 cmd->xfer.nb_sectors);
104 if (err)
105 printf("Read failed\n");
106 break;
107 case 0x02:
108 err = bdrv_write(bs, cmd->xfer.sector, phys_ram_base +
109 cmd->xfer.segment * 16 + cmd->xfer.offset,
110 cmd->xfer.nb_sectors);
111 if (err)
112 printf("Write failed\n");
114 cpu_physical_memory_set_dirty(cmd->xfer.segment * 16 + cmd->xfer.offset);
115 break;
119 void extboot_init(BlockDriverState *bs, int cmd)
121 int *pcmd;
123 pcmd = qemu_mallocz(sizeof(int));
124 if (!pcmd) {
125 fprintf(stderr, "Error allocating memory\n");
126 exit(1);
129 *pcmd = cmd;
130 register_ioport_read(0x404, 1, 1, extboot_read, pcmd);
131 register_ioport_write(0x405, 1, 2, extboot_write_cmd, bs);