25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_gt.c,v 1.43 2006/08/13 08:34:06 debug Exp $ |
* $Id: dev_gt.c,v 1.44 2006/09/23 03:52:10 debug Exp $ |
29 |
* |
* |
30 |
* Galileo Technology GT-64xxx PCI controller. |
* Galileo Technology GT-64xxx PCI controller. |
31 |
* |
* |
44 |
#include "machine.h" |
#include "machine.h" |
45 |
#include "memory.h" |
#include "memory.h" |
46 |
#include "misc.h" |
#include "misc.h" |
47 |
|
#include "timer.h" |
48 |
|
|
49 |
#include "gtreg.h" |
#include "gtreg.h" |
50 |
|
|
59 |
|
|
60 |
|
|
61 |
struct gt_data { |
struct gt_data { |
|
int timer0_irqnr; |
|
62 |
int pci_irqbase; |
int pci_irqbase; |
63 |
int type; |
int type; |
64 |
|
|
65 |
|
struct timer *timer; |
66 |
|
int timer0_irqnr; |
67 |
|
int interrupt_hz; |
68 |
|
int pending_timer0_interrupts; |
69 |
|
|
70 |
/* Address decode registers: */ |
/* Address decode registers: */ |
71 |
uint32_t decode[GT_N_DECODE_REGS]; |
uint32_t decode[GT_N_DECODE_REGS]; |
72 |
|
|
74 |
}; |
}; |
75 |
|
|
76 |
|
|
77 |
DEVICE_TICK(gt) |
/* |
78 |
|
* timer_tick(): |
79 |
|
* |
80 |
|
* Called d->interrupt_hz times per (real-world) second. |
81 |
|
*/ |
82 |
|
static void timer_tick(struct timer *timer, void *extra) |
83 |
{ |
{ |
84 |
struct gt_data *gt_data = extra; |
struct gt_data *d = (struct gt_data *) extra; |
85 |
|
d->pending_timer0_interrupts ++; |
86 |
|
} |
87 |
|
|
|
/* TODO: Implement real timer interrupts. */ |
|
88 |
|
|
89 |
cpu_interrupt(cpu, gt_data->timer0_irqnr); |
DEVICE_TICK(gt) |
90 |
|
{ |
91 |
|
struct gt_data *d = (struct gt_data *) extra; |
92 |
|
|
93 |
|
if (d->pending_timer0_interrupts > 0) |
94 |
|
cpu_interrupt(cpu, d->timer0_irqnr); |
95 |
} |
} |
96 |
|
|
97 |
|
|
146 |
odata = GTIC_T0EXP; |
odata = GTIC_T0EXP; |
147 |
cpu_interrupt_ack(cpu, d->timer0_irqnr); |
cpu_interrupt_ack(cpu, d->timer0_irqnr); |
148 |
|
|
149 |
|
if (d->pending_timer0_interrupts > 0) |
150 |
|
d->pending_timer0_interrupts --; |
151 |
|
|
152 |
debug("[ gt: read from GT_INTR_CAUSE (0x%08x) ]\n", |
debug("[ gt: read from GT_INTR_CAUSE (0x%08x) ]\n", |
153 |
(int)odata); |
(int)odata); |
154 |
} |
} |
159 |
cpu_interrupt_ack(cpu, d->pci_irqbase + odata); |
cpu_interrupt_ack(cpu, d->pci_irqbase + odata); |
160 |
break; |
break; |
161 |
|
|
162 |
|
case GT_TIMER_CTRL: |
163 |
|
if (writeflag == MEM_WRITE) { |
164 |
|
if (idata & ENTC0) { |
165 |
|
/* TODO: Don't hardcode this. */ |
166 |
|
d->interrupt_hz = 100; |
167 |
|
if (d->timer == NULL) |
168 |
|
d->timer = timer_add(d->interrupt_hz, |
169 |
|
timer_tick, d); |
170 |
|
else |
171 |
|
timer_update_frequency(d->timer, |
172 |
|
d->interrupt_hz); |
173 |
|
} |
174 |
|
} |
175 |
|
break; |
176 |
|
|
177 |
case GT_PCI0_CFG_ADDR: |
case GT_PCI0_CFG_ADDR: |
178 |
if (cpu->byte_order != EMUL_LITTLE_ENDIAN) { |
if (cpu->byte_order != EMUL_LITTLE_ENDIAN) { |
179 |
fatal("[ gt: TODO: big endian PCI access ]\n"); |
fatal("[ gt: TODO: big endian PCI access ]\n"); |