/[gxemul]/trunk/src/devices/dev_i80321.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/devices/dev_i80321.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 33 by dpavlin, Mon Oct 8 16:19:56 2007 UTC revision 34 by dpavlin, Mon Oct 8 16:21:17 2007 UTC
# Line 1  Line 1 
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:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: dev_i80321.c,v 1.15 2006/03/04 12:38:47 debug Exp $   *  $Id: dev_i80321.c,v 1.20 2007/02/05 16:49:21 debug Exp $
29   *   *
30   *  Intel i80321 (ARM) core functionality.   *  Intel i80321 (ARM) core functionality.
31   *   *
32   *  TODO: This is mostly just a dummy device.   *      o)  Interrupt controller
33   *  TODO 2: This is hardcoded for little endian emulation.   *      o)  Timer
34     *      o)  PCI controller
35     *      o)  Memory controller
36     *
37     *  TODO:
38     *      o)  LOTS of things left to implement.
39     *      o)  This is hardcoded for little endian emulation.
40   */   */
41    
42  #include <stdio.h>  #include <stdio.h>
# Line 40  Line 46 
46  #include "bus_pci.h"  #include "bus_pci.h"
47  #include "cpu.h"  #include "cpu.h"
48  #include "device.h"  #include "device.h"
 #include "devices.h"  
49  #include "machine.h"  #include "machine.h"
50  #include "memory.h"  #include "memory.h"
51  #include "misc.h"  #include "misc.h"
52    #include "timer.h"
53    
54    
55  #include "i80321reg.h"  #include "i80321reg.h"
56    
57  #define TICK_SHIFT              20  #define TICK_SHIFT              15
58  #define DEV_I80321_LENGTH       VERDE_PMMR_SIZE  #define DEV_I80321_LENGTH       VERDE_PMMR_SIZE
59    
60    struct i80321_data {
61            /*  Interrupt Controller  */
62            struct interrupt irq;
63            uint32_t        *status;        /*  Note: these point to i80321_isrc  */
64            uint32_t        *enable;        /*  and i80321_inten in the CPU!  */
65    
66            /*  Timer:  */
67            struct timer    *timer;
68            double          hz;
69            int             pending_tmr0_interrupts;
70    
71            /*  PCI Controller:  */
72            uint32_t        pci_addr;
73            struct pci_data *pci_bus;
74    
75            /*  Memory Controller:  */
76            uint32_t        mcu_reg[0x100 / sizeof(uint32_t)];
77    };
78    
79    
80  void dev_i80321_tick(struct cpu *cpu, void *extra)  static void i80321_assert(struct i80321_data *d, uint32_t linemask)
81    {
82            *d->status |= linemask;
83            if (*d->status & *d->enable)
84                    INTERRUPT_ASSERT(d->irq);
85    }
86    static void i80321_deassert(struct i80321_data *d, uint32_t linemask)
87  {  {
88          /*  struct i80321_data *d = extra;  */          *d->status &= ~linemask;
89          int do_timer_interrupt = 0;          if (!(*d->status & *d->enable))
90                    INTERRUPT_DEASSERT(d->irq);
91    }
92    
93    
94    /*  
95     *  i80321_interrupt_assert():
96     *  i80321_interrupt_deassert():
97     *
98     *  Called whenever an i80321 interrupt is asserted/deasserted.
99     */
100    void i80321_interrupt_assert(struct interrupt *interrupt)
101    { i80321_assert(interrupt->extra, interrupt->line); }
102    void i80321_interrupt_deassert(struct interrupt *interrupt)
103    {
104            struct i80321_data *d = interrupt->extra;
105    
106            /*  Ack. timer interrupts:  */
107            if (interrupt->line == 1 << 9 &&
108                d->pending_tmr0_interrupts > 0)
109                    d->pending_tmr0_interrupts --;
110    
111            i80321_deassert(d, interrupt->line);
112    }
113    
         if (cpu->cd.arm.tmr0 & TMRx_ENABLE) {  
                 do_timer_interrupt = 1;  
         }  
114    
115          if (do_timer_interrupt) {  /*  TMR0 ticks, called d->hz times per second.  */
116                  cpu_interrupt(cpu, 9);  static void tmr0_tick(struct timer *t, void *extra)
117    {
118            struct i80321_data *d = extra;
119            d->pending_tmr0_interrupts ++;
120    }
121    
122    
123    DEVICE_TICK(i80321)
124    {
125            struct i80321_data *d = extra;
126    
127            if (cpu->cd.arm.tmr0 & TMRx_ENABLE && d->pending_tmr0_interrupts > 0) {
128                    i80321_assert(d, 1 << 9);
129                  cpu->cd.arm.tisr |= TISR_TMR0;                  cpu->cd.arm.tisr |= TISR_TMR0;
130          } else {          } else {
131                  cpu_interrupt_ack(cpu, 9);                  i80321_deassert(d, 1 << 9);
132                  cpu->cd.arm.tisr &= ~TISR_TMR0;                  cpu->cd.arm.tisr &= ~TISR_TMR0;
133          }          }
134  }  }
# Line 223  DEVINIT(i80321) Line 286  DEVINIT(i80321)
286          struct i80321_data *d = malloc(sizeof(struct i80321_data));          struct i80321_data *d = malloc(sizeof(struct i80321_data));
287          uint32_t memsize = devinit->machine->physical_ram_in_mb * 1048576;          uint32_t memsize = devinit->machine->physical_ram_in_mb * 1048576;
288          uint32_t base;          uint32_t base;
289            char tmpstr[300];
290            int i;
291            struct cpu *cpu = devinit->machine->cpus[devinit->
292                machine->bootstrap_cpu];
293    
294          if (d == NULL) {          if (d == NULL) {
295                  fprintf(stderr, "out of memory\n");                  fprintf(stderr, "out of memory\n");
# Line 230  DEVINIT(i80321) Line 297  DEVINIT(i80321)
297          }          }
298          memset(d, 0, sizeof(struct i80321_data));          memset(d, 0, sizeof(struct i80321_data));
299    
300            /*  Connect to the CPU interrupt pin:  */
301            INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
302    
303            /*  Register 32 i80321 interrupts:  */
304            for (i=0; i<32; i++) {
305                    struct interrupt template;
306                    char tmpstr[300];
307                    snprintf(tmpstr, sizeof(tmpstr), "%s.i80321.%i",
308                        devinit->interrupt_path, i);
309                    memset(&template, 0, sizeof(template));
310                    template.line = 1 << i;
311                    template.name = tmpstr;
312                    template.extra = d;
313                    template.interrupt_assert = i80321_interrupt_assert;
314                    template.interrupt_deassert = i80321_interrupt_deassert;
315                    interrupt_handler_register(&template);
316    
317                    /*
318                     *  Connect the CPU's TMR0 and TMR1 interrupts to these
319                     *  i80321 timer interrupts (nr 9 and 10):
320                     */
321                    if (i == 9)
322                            INTERRUPT_CONNECT(tmpstr, cpu->cd.arm.tmr0_irq);
323                    if (i == 10)
324                            INTERRUPT_CONNECT(tmpstr, cpu->cd.arm.tmr1_irq);
325            }
326    
327            d->status = &cpu->cd.arm.i80321_isrc;
328            d->enable = &cpu->cd.arm.i80321_inten;
329    
330          d->mcu_reg[MCU_SDBR / sizeof(uint32_t)] = base = 0xa0000000;          d->mcu_reg[MCU_SDBR / sizeof(uint32_t)] = base = 0xa0000000;
331          d->mcu_reg[MCU_SBR0 / sizeof(uint32_t)] = (base + memsize) >> 25;          d->mcu_reg[MCU_SBR0 / sizeof(uint32_t)] = (base + memsize) >> 25;
332          d->mcu_reg[MCU_SBR1 / sizeof(uint32_t)] = (base + memsize) >> 25;          d->mcu_reg[MCU_SBR1 / sizeof(uint32_t)] = (base + memsize) >> 25;
333    
334            snprintf(tmpstr, sizeof(tmpstr), "%s.i80321", devinit->interrupt_path);
335    
336          d->pci_bus = bus_pci_init(devinit->machine,          d->pci_bus = bus_pci_init(devinit->machine,
337              0 /*  TODO: pciirq  */,              tmpstr      /*  pciirq  */,
338              0x90000000 /*  TODO: pci_io_offset  */,              0x90000000  /*  TODO: pci_io_offset  */,
339              0x90010000 /*  TODO: pci_mem_offset  */,              0x90010000  /*  TODO: pci_mem_offset  */,
340              0xffff0000 /*  TODO: pci_portbase  */,              0xffff0000  /*  TODO: pci_portbase  */,
341              0x00000000 /*  TODO: pci_membase  */,              0x00000000  /*  TODO: pci_membase  */,
342              29 /*  TODO: pci_irqbase  */,              tmpstr      /*  pci_irqbase  */,
343              0x90000000 /*  TODO: isa_portbase  */,              0x90000000  /*  TODO: isa_portbase  */,
344              0x90010000 /*  TODO: isa_membase  */,              0x90010000  /*  TODO: isa_membase  */,
345              0 /*  TODO: isa_irqbase  */);              "TODO: isa_irqbase" /*  TODO: isa_irqbase  */);
346    
347          memory_device_register(devinit->machine->memory, devinit->name,          memory_device_register(devinit->machine->memory, devinit->name,
348              devinit->addr, DEV_I80321_LENGTH,              devinit->addr, DEV_I80321_LENGTH,
349              dev_i80321_access, d, DM_DEFAULT, NULL);              dev_i80321_access, d, DM_DEFAULT, NULL);
350    
351            /*  TODO: Don't hardcode to 100 Hz!  */
352            d->hz = 100;
353            d->timer = timer_add(d->hz, tmr0_tick, d);
354    
355          machine_add_tickfunction(devinit->machine, dev_i80321_tick,          machine_add_tickfunction(devinit->machine, dev_i80321_tick,
356              d, TICK_SHIFT, 0.0);              d, TICK_SHIFT, 0.0);
357    
358          devinit->return_ptr = d;          devinit->return_ptr = d->pci_bus;
359    
360          return 1;          return 1;
361  }  }

Legend:
Removed from v.33  
changed lines
  Added in v.34

  ViewVC Help
Powered by ViewVC 1.1.26