1 /*
2 * Copyright (C) 2005-2019 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * COMMENT: PC CMOS/RTC device (ISA ports 0x70 and 0x71)
29 *
30 * The main point of this device is to be a "PC style wrapper" for accessing
31 * the MC146818 (the RTC). In most other respects, this device is bogus, and
32 * just acts as a 256-byte RAM device.
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "cpu.h"
40 #include "device.h"
41 #include "devices.h"
42 #include "emul.h"
43 #include "machine.h"
44 #include "memory.h"
45 #include "misc.h"
46
47
48 #define DEV_PCCMOS_LENGTH 2
49 #define PCCMOS_MC146818_FAKE_ADDR 0x1d00000000ULL
50
51 struct pccmos_data {
52 unsigned char select;
53 unsigned char ram[256];
54 };
55
56
DEVICE_ACCESS(pccmos)57 DEVICE_ACCESS(pccmos)
58 {
59 struct pccmos_data *d = (struct pccmos_data *) extra;
60 uint64_t idata = 0, odata = 0;
61 unsigned char b = 0;
62 int r = 1;
63
64 if (writeflag == MEM_WRITE)
65 b = idata = memory_readmax64(cpu, data, len);
66
67 /*
68 * Accesses to CMOS register 0 .. 0xd are rerouted to the
69 * RTC; all other access are treated as CMOS RAM read/writes.
70 */
71
72 if ((relative_addr & 1) == 0) {
73 if (writeflag == MEM_WRITE) {
74 d->select = idata;
75 if (idata <= 0x0d) {
76 r = cpu->memory_rw(cpu, cpu->mem,
77 PCCMOS_MC146818_FAKE_ADDR, &b, 1,
78 MEM_WRITE, PHYSICAL);
79 }
80 } else
81 odata = d->select;
82 } else {
83 if (d->select <= 0x0d) {
84 if (writeflag == MEM_WRITE) {
85 r = cpu->memory_rw(cpu, cpu->mem,
86 PCCMOS_MC146818_FAKE_ADDR + 1, &b, 1,
87 MEM_WRITE, PHYSICAL);
88 } else {
89 r = cpu->memory_rw(cpu, cpu->mem,
90 PCCMOS_MC146818_FAKE_ADDR + 1, &b, 1,
91 MEM_READ, PHYSICAL);
92 odata = b;
93 }
94 } else {
95 if (writeflag == MEM_WRITE)
96 d->ram[d->select] = idata;
97 else
98 odata = d->ram[d->select];
99 }
100 }
101
102 if (r == 0)
103 fatal("[ pccmos: memory_rw() error! ]\n");
104
105 if (writeflag == MEM_READ)
106 memory_writemax64(cpu, data, len, odata);
107
108 return 1;
109 }
110
111
DEVINIT(pccmos)112 DEVINIT(pccmos)
113 {
114 int type = MC146818_PC_CMOS, len = DEV_PCCMOS_LENGTH;
115 struct pccmos_data *d;
116
117 CHECK_ALLOCATION(d = (struct pccmos_data *) malloc(sizeof(struct pccmos_data)));
118 memset(d, 0, sizeof(struct pccmos_data));
119
120 switch (devinit->machine->machine_type) {
121 case MACHINE_CATS:
122 case MACHINE_NETWINDER:
123 type = MC146818_CATS;
124 d->ram[0x48] = 20; /* century */
125 len = DEV_PCCMOS_LENGTH * 2;
126 break;
127 case MACHINE_ALGOR:
128 type = MC146818_ALGOR;
129 break;
130 case MACHINE_ARC:
131 fatal("\nARC pccmos: TODO\n\n");
132 type = MC146818_ALGOR;
133 break;
134 case MACHINE_EVBMIPS:
135 /* Malta etc. */
136 type = MC146818_ALGOR;
137 break;
138 case MACHINE_COBALT:
139 case MACHINE_PREP:
140 case MACHINE_MVMEPPC:
141 case MACHINE_ALPHA:
142 case MACHINE_IYONIX: // TODO: not sure about exact type.
143 break;
144 default:fatal("devinit_pccmos(): unimplemented machine type"
145 " %i\n", devinit->machine->machine_type);
146 exit(1);
147 }
148
149 memory_device_register(devinit->machine->memory, devinit->name,
150 devinit->addr, len, dev_pccmos_access, (void *)d,
151 DM_DEFAULT, NULL);
152
153 dev_mc146818_init(devinit->machine, devinit->machine->memory,
154 PCCMOS_MC146818_FAKE_ADDR, devinit->interrupt_path, type, 1);
155
156 return 1;
157 }
158
159