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

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

revision 14 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 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_footbridge.c,v 1.22 2005/10/07 15:10:02 debug Exp $   *  $Id: dev_footbridge.c,v 1.57 2007/06/15 19:11:15 debug Exp $
29   *   *
30   *  Footbridge. Used in Netwinder and Cats.   *  COMMENT: DC21285 "Footbridge" controller; used in Netwinder and Cats
  *  
  *  TODO: Most things. For example:  
31   *   *
32     *  TODO:
33   *      o)  Add actual support for the fcom serial port.   *      o)  Add actual support for the fcom serial port.
34   *      o)  FIQs.   *      o)  FIQs.
35   *      o)  Lots of other things.   *      o)  Pretty much everything else as well :)  (This entire thing
36     *          is a quick hack to work primarily with NetBSD and OpenBSD
37     *          as guest OSes.)
38   */   */
39    
40  #include <stdio.h>  #include <stdio.h>
# Line 44  Line 45 
45  #include "console.h"  #include "console.h"
46  #include "cpu.h"  #include "cpu.h"
47  #include "device.h"  #include "device.h"
48  #include "devices.h"    /*  for struct footbridge_data  */  #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 "dc21285reg.h"  #include "dc21285reg.h"
# Line 55  Line 57 
57  #define DEV_FOOTBRIDGE_TICK_SHIFT       14  #define DEV_FOOTBRIDGE_TICK_SHIFT       14
58  #define DEV_FOOTBRIDGE_LENGTH           0x400  #define DEV_FOOTBRIDGE_LENGTH           0x400
59    
60    #define N_FOOTBRIDGE_TIMERS             4
61    
62    struct footbridge_data {
63            struct interrupt irq;
64    
65            struct pci_data *pcibus;
66    
67            int             console_handle;
68    
69            uint32_t        timer_load[N_FOOTBRIDGE_TIMERS];
70            uint32_t        timer_value[N_FOOTBRIDGE_TIMERS];
71            uint32_t        timer_control[N_FOOTBRIDGE_TIMERS];
72    
73            struct interrupt timer_irq[N_FOOTBRIDGE_TIMERS];
74            struct timer    *timer[N_FOOTBRIDGE_TIMERS];
75            int             pending_timer_interrupts[N_FOOTBRIDGE_TIMERS];
76    
77            int             irq_asserted;
78    
79            uint32_t        irq_status;
80            uint32_t        irq_enable;
81    
82            uint32_t        fiq_status;
83            uint32_t        fiq_enable;
84    };
85    
86    
87    static void timer_tick0(struct timer *t, void *extra)
88    { ((struct footbridge_data *)extra)->pending_timer_interrupts[0] ++; }
89    static void timer_tick1(struct timer *t, void *extra)
90    { ((struct footbridge_data *)extra)->pending_timer_interrupts[1] ++; }
91    static void timer_tick2(struct timer *t, void *extra)
92    { ((struct footbridge_data *)extra)->pending_timer_interrupts[2] ++; }
93    static void timer_tick3(struct timer *t, void *extra)
94    { ((struct footbridge_data *)extra)->pending_timer_interrupts[3] ++; }
95    
96    
97    static void reload_timer_value(struct cpu *cpu, struct footbridge_data *d,
98            int timer_nr)
99    {
100            double freq = (double)cpu->machine->emulated_hz;
101            int cycles = d->timer_load[timer_nr];
102    
103            if (d->timer_control[timer_nr] & TIMER_FCLK_16)
104                    cycles <<= 4;
105            else if (d->timer_control[timer_nr] & TIMER_FCLK_256)
106                    cycles <<= 8;
107            freq /= (double)cycles;
108    
109            d->timer_value[timer_nr] = d->timer_load[timer_nr];
110    
111            /*  printf("%i: %i -> %f Hz\n", timer_nr,
112                d->timer_load[timer_nr], freq);  */
113    
114            if (d->timer[timer_nr] == NULL) {
115                    switch (timer_nr) {
116                    case 0: d->timer[0] = timer_add(freq, timer_tick0, d); break;
117                    case 1: d->timer[1] = timer_add(freq, timer_tick1, d); break;
118                    case 2: d->timer[2] = timer_add(freq, timer_tick2, d); break;
119                    case 3: d->timer[3] = timer_add(freq, timer_tick3, d); break;
120                    }
121            } else {
122                    timer_update_frequency(d->timer[timer_nr], freq);
123            }
124    }
125    
126    
127  /*  /*
128   *  dev_footbridge_tick():   *  The 4 footbridge timers should decrease and cause interrupts. Periodic
129     *  interrupts restart as soon as they are acknowledged, non-periodic
130     *  interrupts need to be "reloaded" to restart.
131   *   *
132   *  The 4 footbridge timers should decrease every now and then, and cause   *  TODO: Hm. I thought I had solved this, but it didn't quite work.
133   *  interrupts. Periodic interrupts restart as soon as they are acknowledged,   *        This needs to be re-checked against documentation, sometime.
  *  non-periodic interrupts need to be "reloaded" to restart.  
134   */   */
135  void dev_footbridge_tick(struct cpu *cpu, void *extra)  DEVICE_TICK(footbridge)
136  {  {
137            struct footbridge_data *d = extra;
138          int i;          int i;
         struct footbridge_data *d = (struct footbridge_data *) extra;  
139    
140          for (i=0; i<N_FOOTBRIDGE_TIMERS; i++) {          for (i=0; i<N_FOOTBRIDGE_TIMERS; i++) {
141                  int amount = 1 << DEV_FOOTBRIDGE_TICK_SHIFT;                  if (d->timer_control[i] & TIMER_ENABLE) {
142                  if (d->timer_control[i] & TIMER_FCLK_16)                          if (d->pending_timer_interrupts[i] > 0) {
143                          amount >>= 4;                                  d->timer_value[i] = random() % d->timer_load[i];
144                  else if (d->timer_control[i] & TIMER_FCLK_256)                                  INTERRUPT_ASSERT(d->timer_irq[i]);
145                          amount >>= 8;                          }
146                    }
147            }
148    }
149    
                 if (d->timer_tick_countdown[i] == 0)  
                         continue;  
150    
151                  if (d->timer_value[i] > amount)  /*
152                          d->timer_value[i] -= amount;   *  footbridge_interrupt_assert():
153                  else   */
154                          d->timer_value[i] = 0;  void footbridge_interrupt_assert(struct interrupt *interrupt)
155    {
156            struct footbridge_data *d = (struct footbridge_data *) interrupt->extra;
157            d->irq_status |= interrupt->line;
158    
159                  if (d->timer_value[i] == 0) {          if ((d->irq_status & d->irq_enable) && !d->irq_asserted) {
160                          d->timer_tick_countdown[i] --;                  d->irq_asserted = 1;
161                          if (d->timer_tick_countdown[i] > 0)                  INTERRUPT_ASSERT(d->irq);
                                 continue;  
   
                         if (d->timer_control[i] & TIMER_ENABLE)  
                                 cpu_interrupt(cpu, IRQ_TIMER_1 + i);  
                         d->timer_tick_countdown[i] = 0;  
                 }  
162          }          }
163  }  }
164    
165    
166  /*  /*
167   *  dev_footbridge_isa_access():   *  footbridge_interrupt_deassert():
168   *   */
169   *  NetBSD seems to read 0x79000000 to find out which ISA interrupt occurred,  void footbridge_interrupt_deassert(struct interrupt *interrupt)
170   *  a quicker way than dealing with legacy 0x20/0xa0 ISA ports.  {
171            struct footbridge_data *d = (struct footbridge_data *) interrupt->extra;
172            d->irq_status &= ~interrupt->line;
173    
174            if (!(d->irq_status & d->irq_enable) && d->irq_asserted) {
175                    d->irq_asserted = 0;
176                    INTERRUPT_DEASSERT(d->irq);
177            }
178    }
179    
180    
181    /*
182     *  Reading the byte at 0x79000000 is a quicker way to figure out which ISA
183     *  interrupt has occurred (and acknowledging it at the same time), than
184     *  dealing with the legacy 0x20/0xa0 ISA ports.
185   */   */
186  int dev_footbridge_isa_access(struct cpu *cpu, struct memory *mem,  DEVICE_ACCESS(footbridge_isa)
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
187  {  {
188          /*  struct footbridge_data *d = extra;  */          /*  struct footbridge_data *d = extra;  */
189          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
190          int x;          int x;
191    
192          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE) {
193                    idata = memory_readmax64(cpu, data, len);
         if (writeflag == MEM_WRITE)  
194                  fatal("[ footbridge_isa: WARNING/TODO: write! ]\n");                  fatal("[ footbridge_isa: WARNING/TODO: write! ]\n");
   
         /*  
          *  NetBSD seems to want a value of 0x20 + x, where x is the highest  
          *  priority ISA interrupt which is currently asserted and not masked.  
          */  
   
         for (x=0; x<16; x++) {  
                 if (x == 2)  
                         continue;  
                 if (x < 8 && (cpu->machine->isa_pic_data.pic1->irr &  
                     ~cpu->machine->isa_pic_data.pic1->ier &  
                     (1 << x)))  
                         break;  
                 if (x >= 8 && (cpu->machine->isa_pic_data.pic2->irr &  
                     ~cpu->machine->isa_pic_data.pic2->ier &  
                     (1 << (x&7))))  
                         break;  
195          }          }
196    
197          if (x == 16)          x = cpu->machine->isa_pic_data.last_int;
198                  fatal("_\n_  SPORADIC but INVALID ISA interrupt\n_\n");          if (x < 8)
199                    odata = cpu->machine->isa_pic_data.pic1->irq_base + x;
200          odata = 0x20 + (x & 15);          else
201                    odata = cpu->machine->isa_pic_data.pic2->irq_base + x - 8;
202    
203          if (writeflag == MEM_READ)          if (writeflag == MEM_READ)
204                  memory_writemax64(cpu, data, len, odata);                  memory_writemax64(cpu, data, len, odata);
# Line 146  int dev_footbridge_isa_access(struct cpu Line 208  int dev_footbridge_isa_access(struct cpu
208    
209    
210  /*  /*
211   *  dev_footbridge_pci_access():   *  Reset pin at ISA port 0x338, at least in the NetWinder:
212   *   *
213   *  The Footbridge PCI configuration space is not implemented as "address +   *  TODO: NOT WORKING YET!
  *  data port" pair, but instead a 24-bit (16 MB) chunk of physical memory  
  *  decodes as the address. This function translates that into bus_pci_access  
  *  calls.  
214   */   */
215  int dev_footbridge_pci_access(struct cpu *cpu, struct memory *mem,  DEVICE_ACCESS(footbridge_reset)
216          uint64_t relative_addr, unsigned char *data, size_t len,  {
217          int writeflag, void *extra)          uint64_t idata = 0;
218    
219            if (writeflag == MEM_WRITE) {
220                    idata = memory_readmax64(cpu, data, len);
221                    if (idata & 0x40) {
222                            debug("[ footbridge_reset: GP16: Halting. ]\n");
223                            cpu->running = 0;
224    exit(1);
225                    }
226            }
227    
228            return 1;
229    }
230    
231    
232    /*
233     *  The Footbridge PCI configuration space is implemented as a direct memory
234     *  space (i.e. not one port for addr and one port for data). This function
235     *  translates that into bus_pci calls.
236     */
237    DEVICE_ACCESS(footbridge_pci)
238  {  {
239          struct footbridge_data *d = extra;          struct footbridge_data *d = extra;
240          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
241          int bus, device, function, regnr, res;          int bus, dev, func, reg;
         uint64_t pci_word;  
242    
243          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
244                    idata = memory_readmax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN);
245    
246          bus      = (relative_addr >> 16) & 0xff;          /*  Decompose the (direct) address into its components:  */
247          device   = (relative_addr >> 11) & 0x1f;          bus_pci_decompose_1(relative_addr, &bus, &dev, &func, &reg);
248          function = (relative_addr >> 8) & 0x7;          bus_pci_setaddr(cpu, d->pcibus, bus, dev, func, reg);
         regnr    = relative_addr & 0xff;  
249    
250          if (bus == 255) {          if (bus == 255) {
251                  fatal("[ footbridge DEBUG ERROR: bus 255 unlikely,"                  fatal("[ footbridge DEBUG ERROR: bus 255 unlikely,"
# Line 175  int dev_footbridge_pci_access(struct cpu Line 253  int dev_footbridge_pci_access(struct cpu
253                  exit(1);                  exit(1);
254          }          }
255    
256          debug("[ footbridge_pci: %s bus %i, device %i, function "          debug("[ footbridge pci: %s bus %i, device %i, function %i, register "
257              "%i, register %i ]\n", writeflag == MEM_READ? "read from"              "%i ]\n", writeflag == MEM_READ? "read from" : "write to", bus,
258              : "write to", bus, device, function, regnr);              dev, func, reg);
259    
260          if (d->pcibus == NULL) {          bus_pci_data_access(cpu, d->pcibus, writeflag == MEM_READ?
261                  fatal("dev_footbridge_pci_access(): no PCI bus?\n");              &odata : &idata, len, writeflag);
                 return 0;  
         }  
   
         pci_word = relative_addr & 0x00ffffff;  
   
         res = bus_pci_access(cpu, mem, BUS_PCI_ADDR,  
             &pci_word, MEM_WRITE, d->pcibus);  
         if (writeflag == MEM_READ) {  
                 res = bus_pci_access(cpu, mem, BUS_PCI_DATA,  
                     &pci_word, MEM_READ, d->pcibus);  
                 odata = pci_word;  
         } else {  
                 pci_word = idata;  
                 res = bus_pci_access(cpu, mem, BUS_PCI_DATA,  
                     &pci_word, MEM_WRITE, d->pcibus);  
         }  
262    
263          if (writeflag == MEM_READ)          if (writeflag == MEM_READ)
264                  memory_writemax64(cpu, data, len, odata);                  memory_writemax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN, odata);
265    
266          return 1;          return 1;
267  }  }
268    
269    
270  /*  DEVICE_ACCESS(footbridge)
  *  dev_footbridge_access():  
  *  
  *  The DC21285 registers.  
  */  
 int dev_footbridge_access(struct cpu *cpu, struct memory *mem,  
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
271  {  {
272          struct footbridge_data *d = extra;          struct footbridge_data *d = extra;
273          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
274          int timer_nr = 0;          int timer_nr = 0;
275    
276          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
277                    idata = memory_readmax64(cpu, data, len);
278    
279          if (relative_addr >= TIMER_1_LOAD && relative_addr <= TIMER_4_CLEAR) {          if (relative_addr >= TIMER_1_LOAD && relative_addr <= TIMER_4_CLEAR) {
280                  timer_nr = (relative_addr >> 5) & (N_FOOTBRIDGE_TIMERS - 1);                  timer_nr = (relative_addr >> 5) & (N_FOOTBRIDGE_TIMERS - 1);
# Line 235  int dev_footbridge_access(struct cpu *cp Line 291  int dev_footbridge_access(struct cpu *cp
291                  odata = 0x1065;  /*  DC21285_DEVICE_ID  */                  odata = 0x1065;  /*  DC21285_DEVICE_ID  */
292                  break;                  break;
293    
294            case 0x04:
295            case 0x0c:
296            case 0x10:
297            case 0x14:
298            case 0x18:
299                    /*  TODO. Written to by Linux.  */
300                    break;
301    
302          case REVISION:          case REVISION:
303                  odata = 3;  /*  footbridge revision number  */                  odata = 3;  /*  footbridge revision number  */
304                  break;                  break;
305    
306            case PCI_ADDRESS_EXTENSION:
307                    /*  TODO: Written to by Linux.  */
308                    if (writeflag == MEM_WRITE && idata != 0)
309                            fatal("[ footbridge: TODO: write to PCI_ADDRESS_"
310                                "EXTENSION: 0x%llx ]\n", (long long)idata);
311                    break;
312    
313            case SA_CONTROL:
314                    /*  Read by Linux:  */
315                    odata = PCI_CENTRAL_FUNCTION;
316                    break;
317    
318          case UART_DATA:          case UART_DATA:
319                  if (writeflag == MEM_WRITE)                  if (writeflag == MEM_WRITE)
320                          console_putchar(d->console_handle, idata);                          console_putchar(d->console_handle, idata);
# Line 274  int dev_footbridge_access(struct cpu *cp Line 350  int dev_footbridge_access(struct cpu *cp
350          case IRQ_ENABLE_SET:          case IRQ_ENABLE_SET:
351                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
352                          d->irq_enable |= idata;                          d->irq_enable |= idata;
353                          cpu_interrupt(cpu, 64);                          if (d->irq_status & d->irq_enable)
354                                    INTERRUPT_ASSERT(d->irq);
355                            else
356                                    INTERRUPT_DEASSERT(d->irq);
357                  } else {                  } else {
358                            odata = d->irq_enable;
359                          fatal("[ WARNING: footbridge read from "                          fatal("[ WARNING: footbridge read from "
360                              "ENABLE SET? ]\n");                              "ENABLE SET? ]\n");
361                          exit(1);                          exit(1);
                         odata = d->irq_enable;  
362                  }                  }
363                  break;                  break;
364    
365          case IRQ_ENABLE_CLEAR:          case IRQ_ENABLE_CLEAR:
366                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
367                          d->irq_enable &= ~idata;                          d->irq_enable &= ~idata;
368                          cpu_interrupt(cpu, 64);                          if (d->irq_status & d->irq_enable)
369                                    INTERRUPT_ASSERT(d->irq);
370                            else
371                                    INTERRUPT_DEASSERT(d->irq);
372                  } else {                  } else {
373                            odata = d->irq_enable;
374                          fatal("[ WARNING: footbridge read from "                          fatal("[ WARNING: footbridge read from "
375                              "ENABLE CLEAR? ]\n");                              "ENABLE CLEAR? ]\n");
376                          exit(1);                          exit(1);
                         odata = d->irq_enable;  
377                  }                  }
378                  break;                  break;
379    
# Line 327  int dev_footbridge_access(struct cpu *cp Line 409  int dev_footbridge_access(struct cpu *cp
409                  if (writeflag == MEM_READ)                  if (writeflag == MEM_READ)
410                          odata = d->timer_load[timer_nr];                          odata = d->timer_load[timer_nr];
411                  else {                  else {
412                          d->timer_value[timer_nr] =                          d->timer_load[timer_nr] = idata & TIMER_MAX_VAL;
413                              d->timer_load[timer_nr] = idata & TIMER_MAX_VAL;                          reload_timer_value(cpu, d, timer_nr);
414                          debug("[ footbridge: timer %i (1-based), value %i ]\n",                          /*  debug("[ footbridge: timer %i (1-based), "
415                              timer_nr + 1, (int)d->timer_value[timer_nr]);                              "value %i ]\n", timer_nr + 1,
416                          d->timer_tick_countdown[timer_nr] = 1;                              (int)d->timer_value[timer_nr]);  */
417                          cpu_interrupt_ack(cpu, IRQ_TIMER_1 + timer_nr);                          INTERRUPT_DEASSERT(d->timer_irq[timer_nr]);
418                  }                  }
419                  break;                  break;
420    
421          case TIMER_1_VALUE:          case TIMER_1_VALUE:
422                  if (writeflag == MEM_READ) {                  if (writeflag == MEM_READ)
                         dev_footbridge_tick(cpu, d);  
423                          odata = d->timer_value[timer_nr];                          odata = d->timer_value[timer_nr];
424                  } else                  else
425                          d->timer_value[timer_nr] = idata & TIMER_MAX_VAL;                          d->timer_value[timer_nr] = idata & TIMER_MAX_VAL;
426                  break;                  break;
427    
# Line 356  int dev_footbridge_access(struct cpu *cp Line 437  int dev_footbridge_access(struct cpu *cp
437                                  exit(1);                                  exit(1);
438                          }                          }
439                          if (idata & TIMER_ENABLE) {                          if (idata & TIMER_ENABLE) {
440                                  d->timer_value[timer_nr] =                                  reload_timer_value(cpu, d, timer_nr);
441                                      d->timer_load[timer_nr];                          } else {
442                                  d->timer_tick_countdown[timer_nr] = 1;                                  d->pending_timer_interrupts[timer_nr] = 0;
443                          }                          }
444                          cpu_interrupt_ack(cpu, IRQ_TIMER_1 + timer_nr);                          INTERRUPT_DEASSERT(d->timer_irq[timer_nr]);
445                  }                  }
446                  break;                  break;
447    
448          case TIMER_1_CLEAR:          case TIMER_1_CLEAR:
449                  if (d->timer_control[timer_nr] & TIMER_MODE_PERIODIC) {                  if (d->timer_control[timer_nr] & TIMER_MODE_PERIODIC) {
450                          d->timer_value[timer_nr] = d->timer_load[timer_nr];                          reload_timer_value(cpu, d, timer_nr);
                         d->timer_tick_countdown[timer_nr] = 1;  
451                  }                  }
452                  cpu_interrupt_ack(cpu, IRQ_TIMER_1 + timer_nr);  
453                    if (d->pending_timer_interrupts[timer_nr] > 0) {
454                            d->pending_timer_interrupts[timer_nr] --;
455                    }
456    
457                    INTERRUPT_DEASSERT(d->timer_irq[timer_nr]);
458                  break;                  break;
459    
460          default:if (writeflag == MEM_READ) {          default:if (writeflag == MEM_READ) {
# Line 388  int dev_footbridge_access(struct cpu *cp Line 473  int dev_footbridge_access(struct cpu *cp
473  }  }
474    
475    
476  /*  DEVINIT(footbridge)
  *  devinit_footbridge():  
  */  
 int devinit_footbridge(struct devinit *devinit)  
477  {  {
478          struct footbridge_data *d;          struct footbridge_data *d;
479            char irq_path[300], irq_path_isa[300];
480          uint64_t pci_addr = 0x7b000000;          uint64_t pci_addr = 0x7b000000;
481          int i;          int i;
482    
483          d = malloc(sizeof(struct footbridge_data));          CHECK_ALLOCATION(d = malloc(sizeof(struct footbridge_data)));
         if (d == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
484          memset(d, 0, sizeof(struct footbridge_data));          memset(d, 0, sizeof(struct footbridge_data));
485    
486            /*  Connect to the CPU which this footbridge will interrupt:  */
487            INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
488    
489          /*  DC21285 register access:  */          /*  DC21285 register access:  */
490          memory_device_register(devinit->machine->memory, devinit->name,          memory_device_register(devinit->machine->memory, devinit->name,
491              devinit->addr, DEV_FOOTBRIDGE_LENGTH,              devinit->addr, DEV_FOOTBRIDGE_LENGTH,
492              dev_footbridge_access, d, MEM_DEFAULT, NULL);              dev_footbridge_access, d, DM_DEFAULT, NULL);
493    
494          /*  ISA interrupt status word:  */          /*  ISA interrupt status/acknowledgement:  */
495          memory_device_register(devinit->machine->memory, "footbridge_isa",          memory_device_register(devinit->machine->memory, "footbridge_isa",
496              0x79000000, 8, dev_footbridge_isa_access, d, MEM_DEFAULT, NULL);              0x79000000, 8, dev_footbridge_isa_access, d, DM_DEFAULT, NULL);
497    
498          /*  The "fcom" console:  */          /*  The "fcom" console:  */
499          d->console_handle = console_start_slave(devinit->machine, "fcom");          d->console_handle = console_start_slave(devinit->machine, "fcom", 0);
500    
501            /*  Register 32 footbridge interrupts:  */
502            snprintf(irq_path, sizeof(irq_path), "%s.footbridge",
503                devinit->interrupt_path);
504            for (i=0; i<32; i++) {
505                    struct interrupt interrupt_template;
506                    char tmpstr[200];
507    
508                    memset(&interrupt_template, 0, sizeof(interrupt_template));
509                    interrupt_template.line = 1 << i;
510                    snprintf(tmpstr, sizeof(tmpstr), "%s.%i", irq_path, i);
511                    interrupt_template.name = tmpstr;
512    
513                    interrupt_template.extra = d;
514                    interrupt_template.interrupt_assert =
515                        footbridge_interrupt_assert;
516                    interrupt_template.interrupt_deassert =
517                        footbridge_interrupt_deassert;
518                    interrupt_handler_register(&interrupt_template);
519    
520                    /*  Connect locally to some interrupts:  */
521                    if (i>=IRQ_TIMER_1 && i<=IRQ_TIMER_4)
522                            INTERRUPT_CONNECT(tmpstr, d->timer_irq[i-IRQ_TIMER_1]);
523            }
524    
525            switch (devinit->machine->machine_type) {
526            case MACHINE_CATS:
527                    snprintf(irq_path_isa, sizeof(irq_path_isa), "%s.10", irq_path);
528                    break;
529            case MACHINE_NETWINDER:
530                    snprintf(irq_path_isa, sizeof(irq_path_isa), "%s.11", irq_path);
531                    break;
532            default:fatal("footbridge unimpl machine type\n");
533                    exit(1);
534            }
535    
536          /*  A PCI bus:  */          /*  A PCI bus:  */
537          d->pcibus = bus_pci_init(devinit->irq_nr);          d->pcibus = bus_pci_init(
538                devinit->machine,
539                irq_path,
540                0x7c000000,         /*  PCI device io offset  */
541                0x80000000,         /*  PCI device mem offset  */
542                0x00000000,         /*  PCI port base  */
543                0x00000000,         /*  PCI mem base  */
544                irq_path,           /*  PCI irq base  */
545                0x7c000000,         /*  ISA port base  */
546                0x80000000,         /*  ISA mem base  */
547                irq_path_isa);      /*  ISA port base  */
548    
549          /*  ... with some default devices for known machine types:  */          /*  ... with some default devices for known machine types:  */
550          switch (devinit->machine->machine_type) {          switch (devinit->machine->machine_type) {
551          case MACHINE_CATS:          case MACHINE_CATS:
552                  bus_pci_add(devinit->machine, d->pcibus,                  bus_pci_add(devinit->machine, d->pcibus,
553                      devinit->machine->memory, 0xc0, 7, 0,                      devinit->machine->memory, 0xc0, 7, 0, "ali_m1543");
                     pci_ali_m1543_init, pci_ali_m1543_rr);  
554                  bus_pci_add(devinit->machine, d->pcibus,                  bus_pci_add(devinit->machine, d->pcibus,
555                      devinit->machine->memory, 0xc0, 16, 0,                      devinit->machine->memory, 0xc0, 10, 0, "dec21143");
556                      pci_ali_m5229_init, pci_ali_m5229_rr);                  bus_pci_add(devinit->machine, d->pcibus,
557                        devinit->machine->memory, 0xc0, 16, 0, "ali_m5229");
558                  break;                  break;
559          case MACHINE_NETWINDER:          case MACHINE_NETWINDER:
560                  bus_pci_add(devinit->machine, d->pcibus,                  bus_pci_add(devinit->machine, d->pcibus,
561                      devinit->machine->memory, 0xc0, 11, 0,                      devinit->machine->memory, 0xc0, 11, 0, "symphony_83c553");
                     pci_symphony_83c553_init, pci_symphony_83c553_rr);  
562                  bus_pci_add(devinit->machine, d->pcibus,                  bus_pci_add(devinit->machine, d->pcibus,
563                      devinit->machine->memory, 0xc0, 11, 1,                      devinit->machine->memory, 0xc0, 11, 1, "symphony_82c105");
564                      pci_symphony_82c105_init, pci_symphony_82c105_rr);                  memory_device_register(devinit->machine->memory,
565                        "footbridge_reset", 0x7c000338, 1,
566                        dev_footbridge_reset_access, d, DM_DEFAULT, NULL);
567                  break;                  break;
568          default:fatal("footbridge: unimplemented machine type.\n");          default:fatal("footbridge: unimplemented machine type.\n");
569                  exit(1);                  exit(1);
# Line 444  int devinit_footbridge(struct devinit *d Line 572  int devinit_footbridge(struct devinit *d
572          /*  PCI configuration space:  */          /*  PCI configuration space:  */
573          memory_device_register(devinit->machine->memory,          memory_device_register(devinit->machine->memory,
574              "footbridge_pci", pci_addr, 0x1000000,              "footbridge_pci", pci_addr, 0x1000000,
575              dev_footbridge_pci_access, d, MEM_DEFAULT, NULL);              dev_footbridge_pci_access, d, DM_DEFAULT, NULL);
576    
577          /*  Timer ticks:  */          /*  Timer ticks:  */
578          for (i=0; i<N_FOOTBRIDGE_TIMERS; i++) {          for (i=0; i<N_FOOTBRIDGE_TIMERS; i++) {
579                  d->timer_control[i] = TIMER_MODE_PERIODIC;                  d->timer_control[i] = TIMER_MODE_PERIODIC;
580                  d->timer_load[i] = TIMER_MAX_VAL;                  d->timer_load[i] = TIMER_MAX_VAL;
581          }          }
582    
583          machine_add_tickfunction(devinit->machine,          machine_add_tickfunction(devinit->machine,
584              dev_footbridge_tick, d, DEV_FOOTBRIDGE_TICK_SHIFT);              dev_footbridge_tick, d, DEV_FOOTBRIDGE_TICK_SHIFT);
585    
586          devinit->return_ptr = d;          devinit->return_ptr = d->pcibus;
587          return 1;          return 1;
588  }  }
589    

Legend:
Removed from v.14  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26