/[gxemul]/trunk/src/devices/dev_vr41xx.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_vr41xx.c

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

revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC revision 34 by dpavlin, Mon Oct 8 16:21:17 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2004-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2004-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_vr41xx.c,v 1.41 2006/10/02 09:26:53 debug Exp $   *  $Id: dev_vr41xx.c,v 1.43 2007/01/21 21:02:57 debug Exp $
29   *     *  
30   *  VR41xx (actually, VR4122 and VR4131) misc functions.   *  VR41xx (VR4122 and VR4131) misc functions.
31   *   *
32   *  This is just a big hack. TODO: Fix.   *  This is just a big hack.
33     *
34     *  TODO: Implement more functionality some day.
35   */   */
36    
37  #include <stdio.h>  #include <stdio.h>
# Line 40  Line 42 
42  #include "cpu.h"  #include "cpu.h"
43  #include "device.h"  #include "device.h"
44  #include "devices.h"  #include "devices.h"
45    #include "interrupt.h"
46  #include "machine.h"  #include "machine.h"
47  #include "memory.h"  #include "memory.h"
48  #include "misc.h"  #include "misc.h"
# Line 51  Line 54 
54  #include "vr_rtcreg.h"  #include "vr_rtcreg.h"
55    
56    
57    /*  #define debug fatal  */
58    
59  #define DEV_VR41XX_TICKSHIFT            14  #define DEV_VR41XX_TICKSHIFT            14
60    
61  /*  #define debug fatal  */  #define DEV_VR41XX_LENGTH               0x800   /*  TODO?  */
62    struct vr41xx_data {
63            struct interrupt cpu_irq;               /*  Connected to MIPS irq 2  */
64            int             cpumodel;               /*  Model nr, e.g. 4121  */
65    
66            /*  KIU:  */
67            int             kiu_console_handle;
68            uint32_t        kiu_offset;
69            struct interrupt kiu_irq;
70            int             kiu_int_assert;
71            int             old_kiu_int_assert;
72    
73            int             d0, d1, d2, d3, d4, d5;
74            int             dont_clear_next;
75            int             escape_state;
76    
77            /*  Timer:  */
78            int             pending_timer_interrupts;
79            struct interrupt timer_irq;
80            struct timer    *timer;
81    
82            /*  See icureg.h in NetBSD for more info.  */
83            uint16_t        sysint1;
84            uint16_t        msysint1;
85            uint16_t        giuint;
86            uint16_t        giumask;
87            uint16_t        sysint2;
88            uint16_t        msysint2;
89            struct interrupt giu_irq;
90    };
91    
92    
93  static void recalc_kiu_int_assert(struct cpu *cpu, struct vr41xx_data *d)  /*
94     *  vr41xx_vrip_interrupt_assert():
95     *  vr41xx_vrip_interrupt_deassert():
96     */
97    void vr41xx_vrip_interrupt_assert(struct interrupt *interrupt)
98  {  {
99          if (d->kiu_int_assert != 0)          struct vr41xx_data *d = interrupt->extra;
100                  cpu_interrupt(cpu, 8 + d->kiu_irq_nr);          int line = interrupt->line;
101            if (line < 16)
102                    d->sysint1 |= (1 << line);
103          else          else
104                  cpu_interrupt_ack(cpu, 8 + d->kiu_irq_nr);                  d->sysint2 |= (1 << (line-16));
105            if ((d->sysint1 & d->msysint1) | (d->sysint2 & d->msysint2))
106                    INTERRUPT_ASSERT(d->cpu_irq);
107    }
108    void vr41xx_vrip_interrupt_deassert(struct interrupt *interrupt)
109    {
110            struct vr41xx_data *d = interrupt->extra;
111            int line = interrupt->line;
112            if (line < 16)
113                    d->sysint1 &= ~(1 << line);
114            else
115                    d->sysint2 &= ~(1 << (line-16));
116            if (!(d->sysint1 & d->msysint1) && !(d->sysint2 & d->msysint2))
117                    INTERRUPT_DEASSERT(d->cpu_irq);
118    }
119    
120    
121    /*
122     *  vr41xx_giu_interrupt_assert():
123     *  vr41xx_giu_interrupt_deassert():
124     */
125    void vr41xx_giu_interrupt_assert(struct interrupt *interrupt)
126    {
127            struct vr41xx_data *d = interrupt->extra;
128            int line = interrupt->line;
129            d->giuint |= (1 << line);
130            if (d->giuint & d->giumask)
131                    INTERRUPT_ASSERT(d->giu_irq);
132    }
133    void vr41xx_giu_interrupt_deassert(struct interrupt *interrupt)
134    {
135            struct vr41xx_data *d = interrupt->extra;
136            int line = interrupt->line;
137            d->giuint &= ~(1 << line);
138            if (!(d->giuint & d->giumask))
139                    INTERRUPT_DEASSERT(d->giu_irq);
140    }
141    
142    
143    static void recalc_kiu_int_assert(struct cpu *cpu, struct vr41xx_data *d)
144    {
145            if (d->kiu_int_assert != d->old_kiu_int_assert) {
146                    d->old_kiu_int_assert = d->kiu_int_assert;
147                    if (d->kiu_int_assert != 0)
148                            INTERRUPT_ASSERT(d->kiu_irq);
149                    else
150                            INTERRUPT_DEASSERT(d->kiu_irq);
151            }
152  }  }
153    
154    
# Line 316  DEVICE_TICK(vr41xx) Line 403  DEVICE_TICK(vr41xx)
403  {  {
404          struct vr41xx_data *d = extra;          struct vr41xx_data *d = extra;
405    
406          if (d->pending_timer_interrupts > 0) {          if (d->pending_timer_interrupts > 0)
407                  if (d->cpumodel == 4121 || d->cpumodel == 4181)                  INTERRUPT_ASSERT(d->timer_irq);
                         cpu_interrupt(cpu, 3);  
                 else  
                         cpu_interrupt(cpu, 8 + VRIP_INTR_ETIMER);  
         }  
408    
409          if (cpu->machine->use_x11)          if (cpu->machine->use_x11)
410                  vr41xx_keytick(cpu, d);                  vr41xx_keytick(cpu, d);
# Line 545  DEVICE_ACCESS(vr41xx) Line 628  DEVICE_ACCESS(vr41xx)
628          */          */
629    
630          case 0x13e:     /*  on 4181?  */          case 0x13e:     /*  on 4181?  */
                 /*  RTC interrupt register...  */  
                 /*  Ack. timer interrupts?  */  
                 cpu_interrupt_ack(cpu, 8 + VRIP_INTR_ETIMER);  
                 if (d->pending_timer_interrupts > 0)  
                         d->pending_timer_interrupts --;  
                 break;  
   
631          case 0x1de:     /*  on 4121?  */          case 0x1de:     /*  on 4121?  */
632                  /*  RTC interrupt register...  */                  /*  RTC interrupt register...  */
633                  /*  Ack. timer interrupts?  */                  /*  Ack. timer interrupts?  */
634                  cpu_interrupt_ack(cpu, 3);                  INTERRUPT_DEASSERT(d->timer_irq);
635                  if (d->pending_timer_interrupts > 0)                  if (d->pending_timer_interrupts > 0)
636                          d->pending_timer_interrupts --;                          d->pending_timer_interrupts --;
637                  break;                  break;
# Line 571  DEVICE_ACCESS(vr41xx) Line 647  DEVICE_ACCESS(vr41xx)
647          }          }
648    
649  ret:  ret:
650          /*  Recalculate interrupt assertions:  */          /*
651          cpu_interrupt_ack(cpu, 8 + 31);         /*  TODO: hopefully nothing           *  Recalculate interrupt assertions:
652                                                  useful at irq 15 in           */
653                                                  sysint2  */          if (d->giuint & d->giumask)
654                    INTERRUPT_ASSERT(d->giu_irq);
655            else
656                    INTERRUPT_DEASSERT(d->giu_irq);
657            if ((d->sysint1 & d->msysint1) | (d->sysint2 & d->msysint2))
658                    INTERRUPT_ASSERT(d->cpu_irq);
659            else
660                    INTERRUPT_DEASSERT(d->cpu_irq);
661    
662          if (writeflag == MEM_READ)          if (writeflag == MEM_READ)
663                  memory_writemax64(cpu, data, len, odata);                  memory_writemax64(cpu, data, len, odata);
# Line 585  ret: Line 668  ret:
668    
669  /*  /*
670   *  dev_vr41xx_init():   *  dev_vr41xx_init():
671     *
672     *  machine->path is something like "emul[0].machine[0]".
673   */   */
674  struct vr41xx_data *dev_vr41xx_init(struct machine *machine,  struct vr41xx_data *dev_vr41xx_init(struct machine *machine,
675          struct memory *mem, int cpumodel)          struct memory *mem, int cpumodel)
676  {  {
677          uint64_t baseaddr = 0;          uint64_t baseaddr = 0;
678          char tmps[100];          char tmps[300];
679            int i;
680          struct vr41xx_data *d = malloc(sizeof(struct vr41xx_data));          struct vr41xx_data *d = malloc(sizeof(struct vr41xx_data));
681    
682          if (d == NULL) {          if (d == NULL) {
# Line 599  struct vr41xx_data *dev_vr41xx_init(stru Line 685  struct vr41xx_data *dev_vr41xx_init(stru
685          }          }
686          memset(d, 0, sizeof(struct vr41xx_data));          memset(d, 0, sizeof(struct vr41xx_data));
687    
688            /*  Connect to MIPS irq 2:  */
689            snprintf(tmps, sizeof(tmps), "%s.cpu[%i].2",
690                machine->path, machine->bootstrap_cpu);
691            INTERRUPT_CONNECT(tmps, d->cpu_irq);
692    
693            /*
694             *  Register VRIP interrupt lines 0..25:
695             */
696            for (i=0; i<=25; i++) {
697                    struct interrupt template;
698                    snprintf(tmps, sizeof(tmps), "%s.cpu[%i].vrip.%i",
699                        machine->path, machine->bootstrap_cpu, i);
700                    memset(&template, 0, sizeof(template));
701                    template.line = i;
702                    template.name = tmps;
703                    template.extra = d;
704                    template.interrupt_assert = vr41xx_vrip_interrupt_assert;
705                    template.interrupt_deassert = vr41xx_vrip_interrupt_deassert;
706                    interrupt_handler_register(&template);
707            }
708    
709            /*
710             *  Register GIU interrupt lines 0..31:
711             */
712            for (i=0; i<32; i++) {
713                    struct interrupt template;
714                    snprintf(tmps, sizeof(tmps), "%s.cpu[%i].vrip.%i.giu.%i",
715                        machine->path, machine->bootstrap_cpu, VRIP_INTR_GIU, i);
716                    memset(&template, 0, sizeof(template));
717                    template.line = i;
718                    template.name = tmps;
719                    template.extra = d;
720                    template.interrupt_assert = vr41xx_giu_interrupt_assert;
721                    template.interrupt_deassert = vr41xx_giu_interrupt_deassert;
722                    interrupt_handler_register(&template);
723            }
724    
725          d->cpumodel = cpumodel;          d->cpumodel = cpumodel;
726    
727          /*  TODO: VRC4173 has the KIU at offset 0x100?  */          /*  TODO: VRC4173 has the KIU at offset 0x100?  */
728          d->kiu_offset = 0x180;          d->kiu_offset = 0x180;
729          d->kiu_console_handle = console_start_slave_inputonly(          d->kiu_console_handle = console_start_slave_inputonly(
730              machine, "kiu", 1);              machine, "kiu", 1);
731          d->kiu_irq_nr = VRIP_INTR_KIU;  
732            /*  Connect to the KIU and GIU interrupts:  */
733            snprintf(tmps, sizeof(tmps), "%s.cpu[%i].vrip.%i",
734                machine->path, machine->bootstrap_cpu, VRIP_INTR_GIU);
735            INTERRUPT_CONNECT(tmps, d->giu_irq);
736            snprintf(tmps, sizeof(tmps), "%s.cpu[%i].vrip.%i",
737                machine->path, machine->bootstrap_cpu, VRIP_INTR_KIU);
738            INTERRUPT_CONNECT(tmps, d->kiu_irq);
739    
740            if (machine->use_x11)
741                    machine->main_console_handle = d->kiu_console_handle;  
742    
743          switch (cpumodel) {          switch (cpumodel) {
744          case 4101:          case 4101:
# Line 628  struct vr41xx_data *dev_vr41xx_init(stru Line 761  struct vr41xx_data *dev_vr41xx_init(stru
761                  exit(1);                  exit(1);
762          }          }
763    
764            if (d->cpumodel == 4121 || d->cpumodel == 4181)
765                    snprintf(tmps, sizeof(tmps), "%s.cpu[%i].3",
766                        machine->path, machine->bootstrap_cpu);
767            else
768                    snprintf(tmps, sizeof(tmps), "%s.cpu[%i].vrip.%i",
769                        machine->path, machine->bootstrap_cpu, VRIP_INTR_ETIMER);
770            INTERRUPT_CONNECT(tmps, d->timer_irq);
771    
772          memory_device_register(mem, "vr41xx", baseaddr, DEV_VR41XX_LENGTH,          memory_device_register(mem, "vr41xx", baseaddr, DEV_VR41XX_LENGTH,
773              dev_vr41xx_access, (void *)d, DM_DEFAULT, NULL);              dev_vr41xx_access, (void *)d, DM_DEFAULT, NULL);
774    
# Line 636  struct vr41xx_data *dev_vr41xx_init(stru Line 777  struct vr41xx_data *dev_vr41xx_init(stru
777           *  which chips.           *  which chips.
778           */           */
779          if (cpumodel == 4131) {          if (cpumodel == 4131) {
780                  snprintf(tmps, sizeof(tmps), "ns16550 irq=%i addr=0x%"PRIx64" "                  snprintf(tmps, sizeof(tmps), "ns16550 irq=%s.cpu[%i].vrip.%i "
781                      "name2=siu", 8+VRIP_INTR_SIU, (uint64_t) (baseaddr+0x800));                      "addr=0x%"PRIx64" name2=siu", machine->path,
782                        machine->bootstrap_cpu, VRIP_INTR_SIU,
783                        (uint64_t) (baseaddr+0x800));
784                  device_add(machine, tmps);                  device_add(machine, tmps);
785          } else {          } else {
786                  /*  This is used by Linux and NetBSD:  */                  /*  This is used by Linux and NetBSD:  */
787                  snprintf(tmps, sizeof(tmps), "ns16550 irq=%i addr=0x%x "                  snprintf(tmps, sizeof(tmps), "ns16550 irq=%s.cpu[%i]."
788                      "name2=serial", 8+VRIP_INTR_SIU, 0xc000000);                      "vrip.%i addr=0x%x name2=serial", machine->path,
789                        machine->bootstrap_cpu, VRIP_INTR_SIU, 0xc000000);
790                  device_add(machine, tmps);                  device_add(machine, tmps);
791          }          }
792    
793          /*  Hm... maybe this should not be here.  TODO  */          /*  Hm... maybe this should not be here.  TODO  */
794          device_add(machine, "pcic addr=0x140003e0");          snprintf(tmps, sizeof(tmps), "pcic irq=%s.cpu[%i].vrip.%i addr="
795                "0x140003e0", machine->path, machine->bootstrap_cpu,
796                VRIP_INTR_GIU);
797            device_add(machine, tmps);
798    
799          machine_add_tickfunction(machine, dev_vr41xx_tick, d,          machine_add_tickfunction(machine, dev_vr41xx_tick, d,
800              DEV_VR41XX_TICKSHIFT, 0.0);              DEV_VR41XX_TICKSHIFT, 0.0);

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

  ViewVC Help
Powered by ViewVC 1.1.26