1 |
/* |
/* |
2 |
* Copyright (C) 2003-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2003-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_mc146818.c,v 1.91 2006/10/07 03:20:19 debug Exp $ |
* $Id: dev_mc146818.c,v 1.95 2007/02/03 16:55:55 debug Exp $ |
29 |
* |
* |
30 |
* MC146818 real-time clock, used by many different machines types. |
* MC146818 real-time clock, used by many different machines types. |
31 |
* (DS1687 as used in some other machines is also similar to the MC146818.) |
* (DS1687 as used in some other machines is also similar to the MC146818.) |
76 |
int timebase_hz; |
int timebase_hz; |
77 |
int interrupt_hz; |
int interrupt_hz; |
78 |
int old_interrupt_hz; |
int old_interrupt_hz; |
79 |
int irq_nr; |
struct interrupt irq; |
80 |
struct timer *timer; |
struct timer *timer; |
81 |
volatile int pending_timer_interrupts; |
volatile int pending_timer_interrupts; |
82 |
|
|
120 |
|
|
121 |
if ((d->reg[MC_REGB * 4] & MC_REGB_PIE) && pti > 0) { |
if ((d->reg[MC_REGB * 4] & MC_REGB_PIE) && pti > 0) { |
122 |
static int warned = 0; |
static int warned = 0; |
123 |
if (pti > 800 && !warned) { |
if (pti > 1500 && !warned) { |
124 |
warned = 1; |
warned = 1; |
125 |
fatal("[ WARNING: MC146818 interrupts lost, " |
fatal("[ WARNING: MC146818 interrupts lost, " |
126 |
"host too slow? ]\n"); |
"host too slow? ]\n"); |
139 |
} |
} |
140 |
#endif |
#endif |
141 |
|
|
142 |
cpu_interrupt(cpu, d->irq_nr); |
INTERRUPT_ASSERT(d->irq); |
143 |
|
|
144 |
d->reg[MC_REGC * 4] |= MC_REGC_PF; |
d->reg[MC_REGC * 4] |= MC_REGC_PF; |
145 |
} |
} |
472 |
case MC_REGB*4: |
case MC_REGB*4: |
473 |
d->reg[MC_REGB*4] = data[0]; |
d->reg[MC_REGB*4] = data[0]; |
474 |
if (!(data[0] & MC_REGB_PIE)) { |
if (!(data[0] & MC_REGB_PIE)) { |
475 |
cpu_interrupt_ack(cpu, d->irq_nr); |
INTERRUPT_DEASSERT(d->irq); |
476 |
} |
} |
477 |
|
|
478 |
/* debug("[ mc146818: write to MC_REGB, data[0] " |
/* debug("[ mc146818: write to MC_REGB, data[0] " |
566 |
data[0] = d->reg[relative_addr]; |
data[0] = d->reg[relative_addr]; |
567 |
|
|
568 |
if (relative_addr == MC_REGC*4) { |
if (relative_addr == MC_REGC*4) { |
569 |
cpu_interrupt_ack(cpu, d->irq_nr); |
INTERRUPT_DEASSERT(d->irq); |
570 |
|
|
571 |
/* |
/* |
572 |
* Acknowledging an interrupt decreases the |
* Acknowledging an interrupt decreases the |
573 |
* number of pending "real world" timer ticks. |
* number of pending "real world" timer ticks. |
574 |
*/ |
*/ |
575 |
if (d->reg[MC_REGC * 4] & MC_REGC_PF) |
if (d->reg[MC_REGC * 4] & MC_REGC_PF && |
576 |
|
d->pending_timer_interrupts > 0) |
577 |
d->pending_timer_interrupts --; |
d->pending_timer_interrupts --; |
578 |
|
|
579 |
d->reg[MC_REGC * 4] = 0x00; |
d->reg[MC_REGC * 4] = 0x00; |
601 |
* so it contains both rtc related stuff and the station's Ethernet address. |
* so it contains both rtc related stuff and the station's Ethernet address. |
602 |
*/ |
*/ |
603 |
void dev_mc146818_init(struct machine *machine, struct memory *mem, |
void dev_mc146818_init(struct machine *machine, struct memory *mem, |
604 |
uint64_t baseaddr, int irq_nr, int access_style, int addrdiv) |
uint64_t baseaddr, char *irq_path, int access_style, int addrdiv) |
605 |
{ |
{ |
606 |
unsigned char ether_address[6]; |
unsigned char ether_address[6]; |
607 |
int i, dev_len; |
int i, dev_len; |
614 |
} |
} |
615 |
|
|
616 |
memset(d, 0, sizeof(struct mc_data)); |
memset(d, 0, sizeof(struct mc_data)); |
617 |
d->irq_nr = irq_nr; |
|
618 |
d->access_style = access_style; |
d->access_style = access_style; |
619 |
d->addrdiv = addrdiv; |
d->addrdiv = addrdiv; |
620 |
|
|
621 |
|
INTERRUPT_CONNECT(irq_path, d->irq); |
622 |
|
|
623 |
d->use_bcd = 0; |
d->use_bcd = 0; |
624 |
switch (access_style) { |
switch (access_style) { |
625 |
case MC146818_SGI: |
case MC146818_SGI: |