1 |
/* |
/* |
2 |
* Copyright (C) 2005-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_algor.c,v 1.1 2006/02/18 17:55:25 debug Exp $ |
* $Id: dev_algor.c,v 1.6 2007/06/15 18:44:18 debug Exp $ |
29 |
* |
* |
30 |
* Algor misc. stuff. |
* COMMENT: Algor P5064 misc. stuff |
31 |
* |
* |
32 |
* TODO: This is hardcoded for P5064 right now. Generalize it to P40xx etc. |
* TODO: This is hardcoded for P5064 right now. Generalize it to P40xx etc. |
33 |
|
* |
34 |
|
* CPU irq 2 = ISA, 3 = PCI, 4 = Local. |
35 |
*/ |
*/ |
36 |
|
|
37 |
#include <stdio.h> |
#include <stdio.h> |
41 |
#include "cpu.h" |
#include "cpu.h" |
42 |
#include "device.h" |
#include "device.h" |
43 |
#include "devices.h" |
#include "devices.h" |
44 |
|
#include "interrupt.h" |
45 |
#include "machine.h" |
#include "machine.h" |
46 |
#include "memory.h" |
#include "memory.h" |
47 |
#include "misc.h" |
#include "misc.h" |
49 |
#include "algor_p5064reg.h" |
#include "algor_p5064reg.h" |
50 |
|
|
51 |
|
|
52 |
|
struct algor_data { |
53 |
|
uint64_t base_addr; |
54 |
|
struct interrupt mips_irq_2; |
55 |
|
struct interrupt mips_irq_3; |
56 |
|
struct interrupt mips_irq_4; |
57 |
|
}; |
58 |
|
|
59 |
|
|
60 |
DEVICE_ACCESS(algor) |
DEVICE_ACCESS(algor) |
61 |
{ |
{ |
62 |
struct algor_data *d = extra; |
struct algor_data *d = extra; |
70 |
|
|
71 |
switch (relative_addr) { |
switch (relative_addr) { |
72 |
|
|
73 |
|
case P5064_LED1 + 0x0: |
74 |
|
case P5064_LED1 + 0x4: |
75 |
|
case P5064_LED1 + 0x8: |
76 |
|
case P5064_LED1 + 0xc: |
77 |
|
break; |
78 |
|
|
79 |
case P5064_LOCINT: |
case P5064_LOCINT: |
80 |
{ |
/* |
81 |
|
* TODO: See how ISAINT is implemented. |
82 |
|
* |
83 |
|
* Implemented so far: COM1 only. |
84 |
|
*/ |
85 |
|
n = "P5064_LOCINT"; |
86 |
|
if (writeflag == MEM_READ) { |
87 |
|
/* Ugly hack for NetBSD startup. TODO: fix */ |
88 |
static int x = 0; |
static int x = 0; |
89 |
x ++; |
if (((++ x) & 0xffff) == 0) |
|
odata = LOCINT_PCIBR; |
|
|
if ((x & 0xffff) == 0) |
|
90 |
odata |= LOCINT_RTC; |
odata |= LOCINT_RTC; |
91 |
|
|
92 |
|
if (cpu->machine->isa_pic_data.pic1->irr & |
93 |
|
~cpu->machine->isa_pic_data.pic1->ier & 0x10) |
94 |
|
odata |= LOCINT_COM1; |
95 |
|
if (cpu->machine->isa_pic_data.pic1->irr & |
96 |
|
~cpu->machine->isa_pic_data.pic1->ier & 0x08) |
97 |
|
odata |= LOCINT_COM2; |
98 |
|
|
99 |
|
/* Read => ack: */ |
100 |
|
cpu->machine->isa_pic_data.pic1->irr &= ~0x18; |
101 |
|
INTERRUPT_DEASSERT(d->mips_irq_4); |
102 |
|
} else { |
103 |
|
if (idata & LOCINT_COM1) |
104 |
|
cpu->machine->isa_pic_data.pic1->ier &= ~0x10; |
105 |
|
else |
106 |
|
cpu->machine->isa_pic_data.pic1->ier |= 0x10; |
107 |
|
if (idata & LOCINT_COM2) |
108 |
|
cpu->machine->isa_pic_data.pic1->ier &= ~0x08; |
109 |
|
else |
110 |
|
cpu->machine->isa_pic_data.pic1->ier |= 0x08; |
111 |
|
} |
112 |
|
break; |
113 |
|
|
114 |
|
case P5064_PANIC: |
115 |
|
n = "P5064_PANIC"; |
116 |
|
if (writeflag == MEM_READ) |
117 |
|
odata = 0; |
118 |
|
break; |
119 |
|
|
120 |
|
case P5064_PCIINT: |
121 |
|
/* |
122 |
|
* TODO: See how ISAINT is implemented. |
123 |
|
*/ |
124 |
|
n = "P5064_PCIINT"; |
125 |
|
if (writeflag == MEM_READ) { |
126 |
|
odata = 0; |
127 |
|
INTERRUPT_DEASSERT(d->mips_irq_3); |
128 |
} |
} |
129 |
break; |
break; |
130 |
|
|
131 |
|
case P5064_ISAINT: |
132 |
|
/* |
133 |
|
* ISA interrupts: |
134 |
|
* |
135 |
|
* Bit: IRQ Source: |
136 |
|
* 0 ISAINT_ISABR |
137 |
|
* 1 ISAINT_IDE0 |
138 |
|
* 2 ISAINT_IDE1 |
139 |
|
* |
140 |
|
* NOTE/TODO: Ugly redirection to the ISA controller. |
141 |
|
*/ |
142 |
|
n = "P5064_ISAINT"; |
143 |
|
if (writeflag == MEM_WRITE) { |
144 |
|
if (idata & ISAINT_IDE0) |
145 |
|
cpu->machine->isa_pic_data.pic2->ier &= ~0x40; |
146 |
|
else |
147 |
|
cpu->machine->isa_pic_data.pic2->ier |= 0x40; |
148 |
|
if (idata & ISAINT_IDE1) |
149 |
|
cpu->machine->isa_pic_data.pic2->ier &= ~0x80; |
150 |
|
else |
151 |
|
cpu->machine->isa_pic_data.pic2->ier |= 0x80; |
152 |
|
cpu->machine->isa_pic_data.pic1->ier &= ~0x04; |
153 |
|
} else { |
154 |
|
if (cpu->machine->isa_pic_data.pic2->irr & |
155 |
|
~cpu->machine->isa_pic_data.pic2->ier & 0x40) |
156 |
|
odata |= ISAINT_IDE0; |
157 |
|
if (cpu->machine->isa_pic_data.pic2->irr & |
158 |
|
~cpu->machine->isa_pic_data.pic2->ier & 0x80) |
159 |
|
odata |= ISAINT_IDE1; |
160 |
|
|
161 |
|
/* Read => ack: */ |
162 |
|
cpu->machine->isa_pic_data.pic2->irr &= ~0xc0; |
163 |
|
INTERRUPT_DEASSERT(d->mips_irq_2); |
164 |
|
} |
165 |
|
break; |
166 |
|
|
167 |
|
case P5064_KBDINT: |
168 |
|
/* |
169 |
|
* TODO: See how ISAINT is implemented. |
170 |
|
*/ |
171 |
|
n = "P5064_KBDINT"; |
172 |
|
if (writeflag == MEM_READ) |
173 |
|
odata = 0; |
174 |
|
break; |
175 |
|
|
176 |
default:if (writeflag == MEM_READ) { |
default:if (writeflag == MEM_READ) { |
177 |
fatal("[ algor: read from 0x%x ]\n", |
fatal("[ algor: read from 0x%x ]\n", |
178 |
(int)relative_addr); |
(int)relative_addr); |
179 |
} else { |
} else { |
180 |
fatal("[ algor: write to 0x%x: 0x%llx ]\n", |
fatal("[ algor: write to 0x%x: 0x%"PRIx64" ]\n", |
181 |
(int)relative_addr, (long long)idata); |
(int) relative_addr, (uint64_t) idata); |
182 |
} |
} |
183 |
} |
} |
184 |
|
|
185 |
if (n != NULL) { |
if (n != NULL) { |
186 |
if (writeflag == MEM_READ) { |
if (writeflag == MEM_READ) { |
187 |
debug("[ algor: read from %s ]\n", n); |
debug("[ algor: read from %s: 0x%"PRIx64" ]\n", |
188 |
|
n, (uint64_t) odata); |
189 |
} else { |
} else { |
190 |
debug("[ algor: write to %s: 0x%llx ]\n", |
debug("[ algor: write to %s: 0x%"PRIx64" ]\n", |
191 |
n, (long long)idata); |
n, (uint64_t) idata); |
192 |
} |
} |
193 |
} |
} |
194 |
|
|
201 |
|
|
202 |
DEVINIT(algor) |
DEVINIT(algor) |
203 |
{ |
{ |
204 |
struct algor_data *d = malloc(sizeof(struct algor_data)); |
char tmpstr[200]; |
205 |
if (d == NULL) { |
struct algor_data *d; |
206 |
fprintf(stderr, "out of memory\n"); |
|
207 |
exit(1); |
CHECK_ALLOCATION(d = malloc(sizeof(struct algor_data))); |
|
} |
|
208 |
memset(d, 0, sizeof(struct algor_data)); |
memset(d, 0, sizeof(struct algor_data)); |
209 |
|
|
210 |
|
d->base_addr = devinit->addr; |
211 |
if (devinit->addr != 0x1ff00000) { |
if (devinit->addr != 0x1ff00000) { |
212 |
fatal("The Algor base address should be 0x1ff00000.\n"); |
fatal("The Algor base address should be 0x1ff00000.\n"); |
213 |
exit(1); |
exit(1); |
214 |
} |
} |
215 |
|
|
216 |
|
/* Connect to MIPS irq 2, 3, and 4: */ |
217 |
|
snprintf(tmpstr, sizeof(tmpstr), "%s.2", devinit->interrupt_path); |
218 |
|
INTERRUPT_CONNECT(tmpstr, d->mips_irq_2); |
219 |
|
snprintf(tmpstr, sizeof(tmpstr), "%s.3", devinit->interrupt_path); |
220 |
|
INTERRUPT_CONNECT(tmpstr, d->mips_irq_3); |
221 |
|
snprintf(tmpstr, sizeof(tmpstr), "%s.4", devinit->interrupt_path); |
222 |
|
INTERRUPT_CONNECT(tmpstr, d->mips_irq_4); |
223 |
|
|
224 |
memory_device_register(devinit->machine->memory, devinit->name, |
memory_device_register(devinit->machine->memory, devinit->name, |
225 |
devinit->addr, 0x100000, dev_algor_access, d, DM_DEFAULT, NULL); |
devinit->addr, 0x100000, dev_algor_access, d, DM_DEFAULT, NULL); |
226 |
|
|
|
d->base_addr = devinit->addr; |
|
|
|
|
227 |
devinit->return_ptr = d; |
devinit->return_ptr = d; |
228 |
|
|
229 |
return 1; |
return 1; |