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

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

revision 18 by dpavlin, Mon Oct 8 16:19:11 2007 UTC revision 34 by dpavlin, Mon Oct 8 16:21:17 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  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_bebox.c,v 1.4 2005/10/26 14:37:03 debug Exp $   *  $Id: dev_bebox.c,v 1.13 2007/02/16 19:57:56 debug Exp $
29   *   *
30   *  Emulation of BeBox motherboard registers. See the following URL for more   *  Emulation of BeBox motherboard registers (and interrupt controller).
31   *  information:   *  See the following URL for more information:
32   *   *
33   *      http://www.bebox.nu/history.php?s=history/benews/benews27   *      http://www.bebox.nu/history.php?s=history/benews/benews27
34     *
35     *  These interrupt numbers are from NetBSD's bebox/extint.c:
36     *
37     *      serial3                 6
38     *      serial4                 7
39     *      midi1                   8
40     *      midi2                   9
41     *      scsi                    10
42     *      pci1                    11
43     *      pci2                    12
44     *      pci3                    13
45     *      sound                   14
46     *      8259                    26
47     *      irda                    27
48     *      a2d                     28
49     *      geekport                29
50     *
51     *  Note that these are in IBM order, i.e. reversed. So 8259 interrupts
52     *  go to interrupt 31 - 26 = 5, when using normal numbers.
53     *
54     *  Interrupt routing should work to both CPUs, but I've only ever seen the
55     *  first CPU being used by NetBSD/bebox, so the second CPU is untested :-)
56   */   */
57    
58  #include <stdio.h>  #include <stdio.h>
# Line 39  Line 61 
61    
62  #include "cpu.h"  #include "cpu.h"
63  #include "device.h"  #include "device.h"
64    #include "interrupt.h"
65  #include "machine.h"  #include "machine.h"
66  #include "memory.h"  #include "memory.h"
67  #include "misc.h"  #include "misc.h"
68    
69    
70  struct bebox_data {  struct bebox_data {
71            struct interrupt        cpu_irq[2];
72    
73          /*  The 5 motherboard registers:  */          /*  The 5 motherboard registers:  */
74          uint32_t        cpu0_intmask;          uint32_t                cpu0_int_mask;
75          uint32_t        cpu1_intmask;          uint32_t                cpu1_int_mask;
76          uint32_t        int_source;          uint32_t                int_status;
77          uint32_t        xpi;          uint32_t                xpi;
78          uint32_t        resets;          uint32_t                resets;
79  };  };
80    
81    
82    static void bebox_interrupt_assert(struct interrupt *interrupt)
83    {
84            struct bebox_data *d = interrupt->extra;
85            d->int_status |= interrupt->line;
86    
87            /*  printf("STATUS %08x  CPU0 %08x  CPU1 %08x\n",
88                d->int_status, d->cpu0_int_mask, d->cpu1_int_mask);  */
89    
90            if (d->int_status & d->cpu0_int_mask)
91                    INTERRUPT_ASSERT(d->cpu_irq[0]);
92            if (d->int_status & d->cpu1_int_mask)
93                    INTERRUPT_ASSERT(d->cpu_irq[1]);
94    }
95    static void bebox_interrupt_deassert(struct interrupt *interrupt)
96    {
97            struct bebox_data *d = interrupt->extra;
98            d->int_status &= ~interrupt->line;
99    
100            if (!(d->int_status & d->cpu0_int_mask))
101                    INTERRUPT_DEASSERT(d->cpu_irq[0]);
102            if (!(d->int_status & d->cpu1_int_mask))
103                    INTERRUPT_DEASSERT(d->cpu_irq[1]);
104    }
105    
106    
107  /*  /*
108   *  dev_bebox_access():   *  check_cpu_masks():
109     *
110     *  BeBox interrupt enable bits are not allowed to be present in
111     *  both CPUs at the same time.
112   */   */
113  int dev_bebox_access(struct cpu *cpu, struct memory *mem,  static void check_cpu_masks(struct cpu *cpu, struct bebox_data *d)
114          uint64_t relative_addr, unsigned char *data, size_t len, int writeflag,  {
115          void *extra)          d->cpu0_int_mask &= 0x7fffffff;
116            d->cpu1_int_mask &= 0x7fffffff;
117            if ((d->cpu0_int_mask | d->cpu1_int_mask) !=
118                (d->cpu0_int_mask ^ d->cpu1_int_mask))
119                    fatal("check_cpu_masks(): BeBox cpu int masks collide!\n");
120    }
121    
122    
123    DEVICE_ACCESS(bebox)
124  {  {
125          struct bebox_data *d = extra;          struct bebox_data *d = extra;
126          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
# Line 68  int dev_bebox_access(struct cpu *cpu, st Line 129  int dev_bebox_access(struct cpu *cpu, st
129                  idata = memory_readmax64(cpu, data, len);                  idata = memory_readmax64(cpu, data, len);
130    
131          switch (relative_addr) {          switch (relative_addr) {
132    
133            case 0x0f0:
134                    if (writeflag == MEM_READ)
135                            odata = d->cpu0_int_mask;
136                    else {
137                            if (idata & 0x80000000)
138                                    d->cpu0_int_mask |= idata;
139                            else
140                                    d->cpu0_int_mask &= ~idata;
141                            check_cpu_masks(cpu, d);
142                    }
143                    break;
144    
145            case 0x1f0:
146                    if (writeflag == MEM_READ)
147                            odata = d->cpu1_int_mask;
148                    else {
149                            if (idata & 0x80000000)
150                                    d->cpu1_int_mask |= idata;
151                            else
152                                    d->cpu1_int_mask &= ~idata;
153                            check_cpu_masks(cpu, d);
154                    }
155                    break;
156    
157            case 0x2f0:
158                    if (writeflag == MEM_READ)
159                            odata = d->int_status;
160                    else {
161                            if (idata & 0x80000000)
162                                    d->int_status |= idata;
163                            else
164                                    d->int_status &= ~idata;
165                            d->int_status &= 0x7fffffff;
166                    }
167                    break;
168    
169          case 0x3f0:          case 0x3f0:
170                  if (writeflag == MEM_READ) {                  if (writeflag == MEM_READ) {
171                          odata = d->xpi;                          odata = d->xpi;
# Line 98  int dev_bebox_access(struct cpu *cpu, st Line 196  int dev_bebox_access(struct cpu *cpu, st
196  }  }
197    
198    
199  /*  DEVINIT(bebox)
  *  devinit_bebox():  
  */  
 int devinit_bebox(struct devinit *devinit)  
200  {  {
201          struct bebox_data *d;          struct bebox_data *d;
202            int i;
203            char n[300];
204            struct machine *machine = devinit->machine;
205    
206          d = malloc(sizeof(struct bebox_data));          d = malloc(sizeof(struct bebox_data));
207          if (d == NULL) {          if (d == NULL) {
# Line 112  int devinit_bebox(struct devinit *devini Line 210  int devinit_bebox(struct devinit *devini
210          }          }
211          memset(d, 0, sizeof(struct bebox_data));          memset(d, 0, sizeof(struct bebox_data));
212    
213          memory_device_register(devinit->machine->memory, devinit->name,          /*  Connect to the two BeBox CPUs:  */
214              0x7ffff000, 0x500, dev_bebox_access, d, MEM_DEFAULT, NULL);          for (i=0; i<2; i++) {
215                    if (i >= machine->ncpus) {
216                            fatal("FATAL ERROR: The machine seem to be "
217                                "lacking cpu nr %i (0-based)\n", i);
218                            exit(1);
219                    }
220    
221                    snprintf(n, sizeof(n), "%s.cpu[%i]", machine->path, i);
222                    INTERRUPT_CONNECT(n, d->cpu_irq[i]);
223            }
224    
225            /*
226             *  Register the 32 BeBox interrupts:
227             *
228             *  NOTE: They are registered on cpu[0], but the interrupt assert/
229             *  deassert routines in this file make sure that the interrupts
230             *  are routed to the correct cpu!
231             */
232            for (i=0; i<32; i++) {
233                    struct interrupt template;
234                    snprintf(n, sizeof(n), "%s.bebox.%i",
235                        devinit->interrupt_path, i);
236                    memset(&template, 0, sizeof(template));
237                    template.line = 1 << i;
238                    template.name = n;
239                    template.extra = d;
240                    template.interrupt_assert = bebox_interrupt_assert;
241                    template.interrupt_deassert = bebox_interrupt_deassert;
242                    interrupt_handler_register(&template);
243            }
244    
245            memory_device_register(machine->memory, devinit->name,
246                0x7ffff000, 0x500, dev_bebox_access, d, DM_DEFAULT, NULL);
247    
248            devinit->return_ptr = d;
249    
250          return 1;          return 1;
251  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26