25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_footbridge.c,v 1.22 2005/10/07 15:10:02 debug Exp $ |
* $Id: dev_footbridge.c,v 1.26 2005/10/26 14:37:04 debug Exp $ |
29 |
* |
* |
30 |
* Footbridge. Used in Netwinder and Cats. |
* Footbridge. Used in Netwinder and Cats. |
31 |
* |
* |
32 |
* TODO: Most things. For example: |
* TODO: Most things. For example: |
33 |
* |
* |
34 |
|
* o) Fix the timer TODO (see below). |
35 |
|
* |
36 |
* o) Add actual support for the fcom serial port. |
* o) Add actual support for the fcom serial port. |
37 |
|
* |
38 |
* o) FIQs. |
* o) FIQs. |
39 |
* o) Lots of other things. |
* |
40 |
|
* o) .. |
41 |
*/ |
*/ |
42 |
|
|
43 |
#include <stdio.h> |
#include <stdio.h> |
58 |
|
|
59 |
#define DEV_FOOTBRIDGE_TICK_SHIFT 14 |
#define DEV_FOOTBRIDGE_TICK_SHIFT 14 |
60 |
#define DEV_FOOTBRIDGE_LENGTH 0x400 |
#define DEV_FOOTBRIDGE_LENGTH 0x400 |
61 |
|
#define TIMER_POLL_THRESHOLD 15 |
62 |
|
|
63 |
|
|
64 |
/* |
/* |
73 |
int i; |
int i; |
74 |
struct footbridge_data *d = (struct footbridge_data *) extra; |
struct footbridge_data *d = (struct footbridge_data *) extra; |
75 |
|
|
76 |
|
if (!d->timer_being_read) |
77 |
|
d->timer_poll_mode = 0; |
78 |
|
|
79 |
for (i=0; i<N_FOOTBRIDGE_TIMERS; i++) { |
for (i=0; i<N_FOOTBRIDGE_TIMERS; i++) { |
80 |
int amount = 1 << DEV_FOOTBRIDGE_TICK_SHIFT; |
int amount = 1 << DEV_FOOTBRIDGE_TICK_SHIFT; |
81 |
if (d->timer_control[i] & TIMER_FCLK_16) |
if (d->timer_control[i] & TIMER_FCLK_16) |
118 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
119 |
int x; |
int x; |
120 |
|
|
121 |
idata = memory_readmax64(cpu, data, len); |
if (writeflag == MEM_WRITE) { |
122 |
|
idata = memory_readmax64(cpu, data, len); |
|
if (writeflag == MEM_WRITE) |
|
123 |
fatal("[ footbridge_isa: WARNING/TODO: write! ]\n"); |
fatal("[ footbridge_isa: WARNING/TODO: write! ]\n"); |
124 |
|
} |
125 |
|
|
126 |
/* |
/* |
127 |
* NetBSD seems to want a value of 0x20 + x, where x is the highest |
* NetBSD seems to want a value of 0x20 + x, where x is the highest |
170 |
int bus, device, function, regnr, res; |
int bus, device, function, regnr, res; |
171 |
uint64_t pci_word; |
uint64_t pci_word; |
172 |
|
|
173 |
idata = memory_readmax64(cpu, data, len); |
if (writeflag == MEM_WRITE) |
174 |
|
idata = memory_readmax64(cpu, data, len); |
175 |
|
|
176 |
bus = (relative_addr >> 16) & 0xff; |
bus = (relative_addr >> 16) & 0xff; |
177 |
device = (relative_addr >> 11) & 0x1f; |
device = (relative_addr >> 11) & 0x1f; |
227 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
228 |
int timer_nr = 0; |
int timer_nr = 0; |
229 |
|
|
230 |
idata = memory_readmax64(cpu, data, len); |
if (writeflag == MEM_WRITE) |
231 |
|
idata = memory_readmax64(cpu, data, len); |
232 |
|
|
233 |
if (relative_addr >= TIMER_1_LOAD && relative_addr <= TIMER_4_CLEAR) { |
if (relative_addr >= TIMER_1_LOAD && relative_addr <= TIMER_4_CLEAR) { |
234 |
timer_nr = (relative_addr >> 5) & (N_FOOTBRIDGE_TIMERS - 1); |
timer_nr = (relative_addr >> 5) & (N_FOOTBRIDGE_TIMERS - 1); |
286 |
d->irq_enable |= idata; |
d->irq_enable |= idata; |
287 |
cpu_interrupt(cpu, 64); |
cpu_interrupt(cpu, 64); |
288 |
} else { |
} else { |
289 |
|
odata = d->irq_enable; |
290 |
fatal("[ WARNING: footbridge read from " |
fatal("[ WARNING: footbridge read from " |
291 |
"ENABLE SET? ]\n"); |
"ENABLE SET? ]\n"); |
292 |
exit(1); |
exit(1); |
|
odata = d->irq_enable; |
|
293 |
} |
} |
294 |
break; |
break; |
295 |
|
|
298 |
d->irq_enable &= ~idata; |
d->irq_enable &= ~idata; |
299 |
cpu_interrupt(cpu, 64); |
cpu_interrupt(cpu, 64); |
300 |
} else { |
} else { |
301 |
|
odata = d->irq_enable; |
302 |
fatal("[ WARNING: footbridge read from " |
fatal("[ WARNING: footbridge read from " |
303 |
"ENABLE CLEAR? ]\n"); |
"ENABLE CLEAR? ]\n"); |
304 |
exit(1); |
exit(1); |
|
odata = d->irq_enable; |
|
305 |
} |
} |
306 |
break; |
break; |
307 |
|
|
348 |
|
|
349 |
case TIMER_1_VALUE: |
case TIMER_1_VALUE: |
350 |
if (writeflag == MEM_READ) { |
if (writeflag == MEM_READ) { |
351 |
dev_footbridge_tick(cpu, d); |
/* |
352 |
|
* TODO: This is INCORRECT! but speeds up NetBSD |
353 |
|
* and OpenBSD boot sequences. A better solution |
354 |
|
* would be to only call dev_footbridge_tick() if |
355 |
|
* the timer is polled "very often" (such as during |
356 |
|
* bootup), but not during normal operation. |
357 |
|
*/ |
358 |
|
d->timer_being_read = 1; |
359 |
|
d->timer_poll_mode ++; |
360 |
|
if (d->timer_poll_mode > TIMER_POLL_THRESHOLD) |
361 |
|
dev_footbridge_tick(cpu, d); |
362 |
odata = d->timer_value[timer_nr]; |
odata = d->timer_value[timer_nr]; |
363 |
|
d->timer_being_read = 0; |
364 |
} else |
} else |
365 |
d->timer_value[timer_nr] = idata & TIMER_MAX_VAL; |
d->timer_value[timer_nr] = idata & TIMER_MAX_VAL; |
366 |
break; |
break; |
446 |
bus_pci_add(devinit->machine, d->pcibus, |
bus_pci_add(devinit->machine, d->pcibus, |
447 |
devinit->machine->memory, 0xc0, 7, 0, |
devinit->machine->memory, 0xc0, 7, 0, |
448 |
pci_ali_m1543_init, pci_ali_m1543_rr); |
pci_ali_m1543_init, pci_ali_m1543_rr); |
449 |
|
/* bus_pci_add(devinit->machine, d->pcibus, |
450 |
|
devinit->machine->memory, 0xc0, 10, 0, |
451 |
|
pci_dec21143_init, pci_dec21143_rr); */ |
452 |
bus_pci_add(devinit->machine, d->pcibus, |
bus_pci_add(devinit->machine, d->pcibus, |
453 |
devinit->machine->memory, 0xc0, 16, 0, |
devinit->machine->memory, 0xc0, 16, 0, |
454 |
pci_ali_m5229_init, pci_ali_m5229_rr); |
pci_ali_m5229_init, pci_ali_m5229_rr); |