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

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

revision 10 by dpavlin, Mon Oct 8 16:18:27 2007 UTC revision 44 by dpavlin, Mon Oct 8 16:22:56 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  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:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_gt.c,v 1.22 2005/06/20 08:19:58 debug Exp $   *  $Id: dev_gt.c,v 1.53 2007/06/16 05:09:55 debug Exp $
29   *     *  
30   *  Galileo Technology GT-64xxx PCI controller.   *  COMMENT: Galileo Technology GT-64xxx PCI controller
31   *   *
32   *      GT-64011        Used in Cobalt machines.   *      GT-64011        Used in Cobalt machines.
33   *      GT-64120        Used in evbmips machines (Malta).   *      GT-64120        Used in evbmips machines (Malta).
34   *   *      GT-64260        Used in mvmeppc machines.
  *  TODO:  This more or less just a dummy device, so far.  
35   */   */
36    
37  #include <stdio.h>  #include <stdio.h>
# Line 42  Line 41 
41  #include "bus_pci.h"  #include "bus_pci.h"
42  #include "cpu.h"  #include "cpu.h"
43  #include "devices.h"  #include "devices.h"
44    #include "interrupt.h"
45  #include "machine.h"  #include "machine.h"
46  #include "memory.h"  #include "memory.h"
47  #include "misc.h"  #include "misc.h"
48    #include "timer.h"
49    
50    #include "gtreg.h"
51    
52    
53    #define TICK_SHIFT              14
54    
55  #define TICK_STEPS_SHIFT        16  /*  #define debug fatal  */
56    
57    #define PCI_PRODUCT_GALILEO_GT64011  0x4146    /*  GT-64011  */
58    #define PCI_PRODUCT_GALILEO_GT64120  0x4620    /*  GT-64120  */
59    #define PCI_PRODUCT_GALILEO_GT64260  0x6430    /*  GT-64260  */
60    
 #define PCI_VENDOR_GALILEO           0x11ab    /* Galileo Technology */  
 #define PCI_PRODUCT_GALILEO_GT64011  0x4146    /* GT-64011 System Controller */  
 #define PCI_PRODUCT_GALILEO_GT64120  0x4620    /* GT-64120 */  
61    
62  struct gt_data {  struct gt_data {
63          int     reg[8];          int             type;
64          int     irqnr;  
65          int     pciirq;          struct timer    *timer;
66          int     type;          struct interrupt timer0_irq;
67            int             interrupt_hz;
68            int             pending_timer0_interrupts;
69    
70          struct pci_data *pci_data;          /*  Address decode registers:  */
71            uint32_t        decode[GT_N_DECODE_REGS];
72    
73            struct pci_data *pci_data;
74  };  };
75    
76    
77  /*  /*
78   *  dev_gt_tick():   *  timer_tick():
79     *
80     *  Called d->interrupt_hz times per (real-world) second.
81   */   */
82  void dev_gt_tick(struct cpu *cpu, void *extra)  static void timer_tick(struct timer *timer, void *extra)
83  {  {
84          struct gt_data *gt_data = extra;          struct gt_data *d = extra;
85            d->pending_timer0_interrupts ++;
86    }
87    
88          cpu_interrupt(cpu, gt_data->irqnr);  
89    DEVICE_TICK(gt)
90    {
91            struct gt_data *d = extra;
92            if (d->pending_timer0_interrupts > 0)
93                    INTERRUPT_ASSERT(d->timer0_irq);
94  }  }
95    
96    
97  /*  DEVICE_ACCESS(gt)
  *  dev_gt_access():  
  */  
 int dev_gt_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,  
         unsigned char *data, size_t len, int writeflag, void *extra)  
98  {  {
         uint64_t idata = 0, odata = 0;  
         int i;  
99          struct gt_data *d = extra;          struct gt_data *d = extra;
100            uint64_t idata = 0, odata = 0;
101            int bus, dev, func, reg;
102            size_t i;
103    
104          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
105                    idata = memory_readmax64(cpu, data, len);
106    
107          switch (relative_addr) {          switch (relative_addr) {
108          case 0xc18:  
109            case GT_PCI0IOLD_OFS:
110            case GT_PCI0IOHD_OFS:
111            case GT_PCI0M0LD_OFS:
112            case GT_PCI0M0HD_OFS:
113            case GT_PCI0M1LD_OFS:
114            case GT_PCI0M1HD_OFS:
115            case GT_PCI0IOREMAP_OFS:
116            case GT_PCI0M0REMAP_OFS:
117            case GT_PCI0M1REMAP_OFS:
118                    if (writeflag == MEM_READ) {
119                            odata = d->decode[relative_addr / 8];
120                            debug("[ gt: read from offset 0x%x: 0x%x ]\n",
121                                (int)relative_addr, (int)odata);
122                    } else {
123                            d->decode[relative_addr / 8] = idata;
124                            fatal("[ gt: write to offset 0x%x: 0x%x (TODO) ]\n",
125                                (int)relative_addr, (int)idata);
126                    }
127                    break;
128    
129            case GT_PCI0_CMD_OFS:
130                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
131                          debug("[ gt write to  0xc18: data = 0x%08lx ]\n",                          debug("[ gt: write to GT_PCI0_CMD: 0x%08x (TODO) ]\n",
132                              (long)idata);                              (int)idata);
                         return 1;  
133                  } else {                  } else {
134                          odata = 0xffffffffULL;                          debug("[ gt: read from GT_PCI0_CMD (0x%08x) (TODO) ]\n",
135                          /*  ???  interrupt something...  */                              (int)odata);
136                    }
137                    break;
138    
139  odata = 0x00000100;     /*  netbsd/cobalt cobalt/machdep.c:cpu_intr()  */          case GT_INTR_CAUSE:
140                    if (writeflag == MEM_WRITE) {
141                            debug("[ gt: write to GT_INTR_CAUSE: 0x%08x ]\n",
142                                (int)idata);
143                            return 1;
144                    } else {
145                            odata = GTIC_T0EXP;
146                            INTERRUPT_DEASSERT(d->timer0_irq);
147    
148  cpu_interrupt_ack(cpu, d->irqnr);                          if (d->pending_timer0_interrupts > 0)
149                                    d->pending_timer0_interrupts --;
150    
151                          debug("[ gt read from 0xc18 (data = 0x%08lx) ]\n",                          debug("[ gt: read from GT_INTR_CAUSE (0x%08x) ]\n",
152                              (long)odata);                              (int)odata);
153                  }                  }
154                  break;                  break;
155          case 0xcf8:     /*  PCI ADDR  */  
156          case 0xcfc:     /*  PCI DATA  */          case GT_PCI0_INTR_ACK:
157                    odata = cpu->machine->isa_pic_data.last_int;
158                    /*  TODO: Actually ack the interrupt?  */
159                    break;
160    
161            case GT_TIMER_CTRL:
162                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
163                          bus_pci_access(cpu, mem, relative_addr, &idata,                          if (idata & ENTC0) {
164                              writeflag, d->pci_data);                                  /*  TODO: Don't hardcode this.  */
165                  } else {                                  d->interrupt_hz = 100;
166                          bus_pci_access(cpu, mem, relative_addr, &odata,                                  if (d->timer == NULL)
167                              writeflag, d->pci_data);                                          d->timer = timer_add(d->interrupt_hz,
168                                                timer_tick, d);
169                                    else
170                                            timer_update_frequency(d->timer,
171                                                d->interrupt_hz);
172                            }
173                    }
174                    break;
175    
176            case GT_PCI0_CFG_ADDR:
177                    if (cpu->byte_order != EMUL_LITTLE_ENDIAN) {
178                            fatal("[ gt: TODO: big endian PCI access ]\n");
179                            exit(1);
180                  }                  }
181                    bus_pci_decompose_1(idata, &bus, &dev, &func, &reg);
182                    bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, reg);
183                  break;                  break;
184    
185            case GT_PCI0_CFG_DATA:
186                    if (cpu->byte_order != EMUL_LITTLE_ENDIAN) {
187                            fatal("[ gt: TODO: big endian PCI access ]\n");
188                            exit(1);
189                    }
190                    bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ?
191                        &odata : &idata, len, writeflag);
192                    break;
193    
194          default:          default:
195                  if (writeflag==MEM_READ) {                  if (writeflag == MEM_READ) {
196                          debug("[ gt read from addr 0x%x ]\n",                          debug("[ gt: read from addr 0x%x ]\n",
197                              (int)relative_addr);                              (int)relative_addr);
                         odata = d->reg[relative_addr];  
198                  } else {                  } else {
199                          debug("[ gt write to addr 0x%x:", (int)relative_addr);                          debug("[ gt: write to addr 0x%x:", (int)relative_addr);
200                          for (i=0; i<len; i++)                          for (i=0; i<len; i++)
201                                  debug(" %02x", data[i]);                                  debug(" %02x", data[i]);
202                          debug(" ]\n");                          debug(" ]\n");
                         d->reg[relative_addr] = idata;  
203                  }                  }
204          }          }
205    
# Line 136  cpu_interrupt_ack(cpu, d->irqnr); Line 211  cpu_interrupt_ack(cpu, d->irqnr);
211    
212    
213  /*  /*
  *  pci_gt_rr_011():  
  */  
 static uint32_t pci_gt_rr_011(int reg)  
 {  
         switch (reg) {  
         case 0x00:  
                 return PCI_VENDOR_GALILEO + (PCI_PRODUCT_GALILEO_GT64011 << 16);  
         case 0x08:  
                 return 0x06000001;      /*  Revision 1  */  
         default:  
                 return 0;  
         }  
 }  
   
   
 /*  
  *  pci_gt_rr_120():  
  */  
 static uint32_t pci_gt_rr_120(int reg)  
 {  
         switch (reg) {  
         case 0x00:  
                 return PCI_VENDOR_GALILEO + (PCI_PRODUCT_GALILEO_GT64120 << 16);  
         case 0x08:  
                 return 0x06000002;      /*  Revision 2?  */  
         default:  
                 return 0;  
         }  
 }  
   
   
 /*  
  *  pci_gt_init():  
  */  
 void pci_gt_init(struct machine *machine, struct memory *mem)  
 {  
 }  
   
   
 /*  
214   *  dev_gt_init():   *  dev_gt_init():
215   *   *
216   *  Initialize a GT device.  Return a pointer to the pci_data used, so that   *  Initialize a Gallileo PCI controller device. First, the controller itself
217   *  the caller may add PCI devices.  First, however, we add the GT device   *  is added to the bus, then a pointer to the bus is returned.
  *  itself.  
218   */   */
219  struct pci_data *dev_gt_init(struct machine *machine, struct memory *mem,  struct pci_data *dev_gt_init(struct machine *machine, struct memory *mem,
220          uint64_t baseaddr, int irq_nr, int pciirq, int type)          uint64_t baseaddr, char *timer_irq_path, char *isa_irq_path, int type)
221  {  {
222          struct gt_data *d;          struct gt_data *d;
223            uint64_t pci_portbase = 0, pci_membase = 0;
224            uint64_t isa_portbase = 0, isa_membase = 0;
225            uint64_t pci_io_offset = 0, pci_mem_offset = 0;
226            char *gt_name = "NO";
227    
228          d = malloc(sizeof(struct gt_data));          CHECK_ALLOCATION(d = malloc(sizeof(struct gt_data)));
         if (d == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
229          memset(d, 0, sizeof(struct gt_data));          memset(d, 0, sizeof(struct gt_data));
230          d->irqnr    = irq_nr;  
231          d->pciirq   = pciirq;          INTERRUPT_CONNECT(timer_irq_path, d->timer0_irq);
         d->pci_data = bus_pci_init(pciirq);  
232    
233          switch (type) {          switch (type) {
234          case 11:          case 11:
235                    /*  Cobalt:  */
236                  d->type = PCI_PRODUCT_GALILEO_GT64011;                  d->type = PCI_PRODUCT_GALILEO_GT64011;
237                    gt_name = "gt64011";
238                    pci_io_offset = 0;
239                    pci_mem_offset = 0;
240                    pci_portbase = 0x10000000ULL;
241                    pci_membase = 0x10100000ULL;
242                    isa_portbase = 0x10000000ULL;
243                    isa_membase = 0x10100000ULL;
244                  break;                  break;
245          case 120:          case 120:
246                    /*  EVBMIPS (Malta):  */
247                  d->type = PCI_PRODUCT_GALILEO_GT64120;                  d->type = PCI_PRODUCT_GALILEO_GT64120;
248                    gt_name = "gt64120";
249                    pci_io_offset = 0;
250                    pci_mem_offset = 0;
251                    pci_portbase = 0x18000000ULL;
252                    pci_membase = 0x10000000ULL;
253                    isa_portbase = 0x18000000ULL;
254                    isa_membase = 0x10000000ULL;
255                    break;
256            case 260:
257                    /*  MVMEPPC (mvme5500):  */
258                    d->type = PCI_PRODUCT_GALILEO_GT64260;
259                    gt_name = "gt64260";
260                    pci_io_offset = 0;
261                    pci_mem_offset = 0;
262                    pci_portbase = 0x18000000ULL;
263                    pci_membase = 0x10000000ULL;
264                    isa_portbase = 0x18000000ULL;
265                    isa_membase = 0x10000000ULL;
266                  break;                  break;
267          default:fatal("dev_gt_init(): type must be 11 or 120.\n");          default:fatal("dev_gt_init(): unimplemented GT type (%i).\n", type);
268                  exit(1);                  exit(1);
269          }          }
270    
271    
272            /*
273             *  TODO: FIX THESE! Hardcoded numbers = bad.
274             */
275            d->decode[GT_PCI0IOLD_OFS / 8] = pci_portbase >> 21;
276            d->decode[GT_PCI0IOHD_OFS / 8] = 0x40;
277            d->decode[GT_PCI0M0LD_OFS / 8] = 0x80;
278            d->decode[GT_PCI0M0HD_OFS / 8] = 0x3f;
279            d->decode[GT_PCI0M1LD_OFS / 8] = 0xc1;
280            d->decode[GT_PCI0M1HD_OFS / 8] = 0x5e;
281            d->decode[GT_PCI0IOREMAP_OFS / 8] = d->decode[GT_PCI0IOLD_OFS / 8];
282            d->decode[GT_PCI0M0REMAP_OFS / 8] = d->decode[GT_PCI0M0LD_OFS / 8];
283            d->decode[GT_PCI0M1REMAP_OFS / 8] = d->decode[GT_PCI0M1LD_OFS / 8];
284    
285            d->pci_data = bus_pci_init(machine,
286                "TODO_gt_irq", pci_io_offset, pci_mem_offset,
287                pci_portbase, pci_membase, "TODO_pci_irqbase",
288                isa_portbase, isa_membase, isa_irq_path);
289    
290          /*          /*
291           *  According to NetBSD/cobalt:           *  According to NetBSD/cobalt:
292           *  pchb0 at pci0 dev 0 function 0: Galileo GT-64011           *  pchb0 at pci0 dev 0 function 0: Galileo GT-64011
293           *  System Controller, rev 1           *  System Controller, rev 1
294           */           */
295          bus_pci_add(machine, d->pci_data, mem, 0, 0, 0, pci_gt_init,          bus_pci_add(machine, d->pci_data, mem, 0, 0, 0, gt_name);
             d->type == PCI_PRODUCT_GALILEO_GT64011?  
             pci_gt_rr_011 : pci_gt_rr_120);  
296    
297          memory_device_register(mem, "gt", baseaddr, DEV_GT_LENGTH,          memory_device_register(mem, "gt", baseaddr, DEV_GT_LENGTH,
298              dev_gt_access, d, MEM_DEFAULT, NULL);              dev_gt_access, d, DM_DEFAULT, NULL);
299          machine_add_tickfunction(machine, dev_gt_tick, d, TICK_STEPS_SHIFT);          machine_add_tickfunction(machine, dev_gt_tick, d, TICK_SHIFT);
300    
301          return d->pci_data;          return d->pci_data;
302  }  }

Legend:
Removed from v.10  
changed lines
  Added in v.44

  ViewVC Help
Powered by ViewVC 1.1.26