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

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

revision 31 by dpavlin, Mon Oct 8 16:19:56 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: dev_lca.c,v 1.1 2006/05/30 19:49:39 debug Exp $   *  $Id: dev_lca.c,v 1.4 2006/08/29 15:55:10 debug Exp $
29   *   *
30   *  LCA bus (for Alpha machines).   *  LCA PCI bus (for Alpha machines).
31   */   */
32    
33  #include <stdio.h>  #include <stdio.h>
# Line 35  Line 35 
35  #include <string.h>  #include <string.h>
36    
37  #include "bus_isa.h"  #include "bus_isa.h"
38    #include "bus_pci.h"
39  #include "cpu.h"  #include "cpu.h"
40  #include "device.h"  #include "device.h"
41  #include "emul.h"  #include "emul.h"
# Line 50  Line 51 
51    
52    
53  struct lca_data {  struct lca_data {
54          int             dummy;          struct pci_data         *pci_data;
55    
56            uint64_t                ioc_conf;
57            uint64_t                tlb_enable;
58            uint64_t                window_base_0;
59            uint64_t                window_mask_0;
60            uint64_t                window_t_base_0;
61            uint64_t                window_base_1;
62            uint64_t                window_mask_1;
63            uint64_t                window_t_base_1;
64  };  };
65    
66    
67    DEVICE_ACCESS(lca_pci_conf)
68    {
69            uint64_t idata = 0, odata = 0;
70            int tag, bus, dev, func, reg;
71            struct lca_data *d = extra;
72    
73            if (writeflag == MEM_WRITE)
74                    idata = memory_readmax64(cpu, data, len);
75    
76            /*
77             *  1. Decompose the address into a tag.
78             *
79             *  According to NetBSD's lca_pci.c, the address is composed like this:
80             *
81             *      addr = tag << 5 | (regoffset & ~0x03) << 5 | 0x3 << 3
82             */
83            reg = (relative_addr >> 5) & 0xfc;
84            tag = (relative_addr >> 5) & ~0xff;
85    
86            /*
87             *  2. Decompose the tag into bus, dev, and func.
88             *
89             *  The tag can be constructed in one of two ways. On the primary
90             *  bus (nr 0):
91             *
92             *      tag = (1 << (device + 11)) | (function << 8);
93             *
94             *  and on other busses, the tag is a normal:
95             *
96             *      tag = (bus << 16) | (device << 11) | (function << 8)
97             */
98            /*  printf("tag = 0x%x\n", (int)tag);  */
99            bus = d->ioc_conf & 1;
100    
101            if (bus == 0) {
102                    for (dev=0; dev<21; dev++)
103                            if (tag & (0x800 << dev))
104                                    break;
105                    if (dev >= 21) {
106                            /*  fatal("[ LCA: No bus 0 device? TODO ]\n");
107                            exit(1);  */
108                            dev = 0;
109                    }
110            } else {
111                    fatal("TODO. Non-zero bus.\n");
112                    exit(1);
113            }
114    
115            func = (tag >> 8) & 7;
116            /*  printf("bus=%i dev=%i func=%i reg=%i\n", bus,dev,func,reg);  */
117    
118            /*  Pass PCI accesses onto bus_pci:  */
119            bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, reg);
120            bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ?
121                &odata : &idata, len, writeflag);
122    
123            if (writeflag == MEM_READ)
124                    memory_writemax64(cpu, data, len, odata);
125    
126            return 1;
127    }
128    
129    
130  DEVICE_ACCESS(lca_isa)  DEVICE_ACCESS(lca_isa)
131  {  {
132          int ofs, i;          int ofs, i;
# Line 84  DEVICE_ACCESS(lca_isa) Line 157  DEVICE_ACCESS(lca_isa)
157  }  }
158    
159    
160    DEVICE_ACCESS(lca_ioc)
161    {
162            uint64_t idata = 0, odata = 0;
163            struct lca_data *d = extra;
164    
165            if (writeflag == MEM_WRITE)
166                    idata = memory_readmax64(cpu, data, len);
167    
168            switch (relative_addr + LCA_IOC_BASE) {
169    
170            case LCA_IOC_BASE:
171                    /*  Ignore? Linux reads from the base at startup.  */
172                    break;
173    
174            case LCA_IOC_CONF:
175                    if (writeflag == MEM_READ) {
176                            odata = d->ioc_conf;
177                    } else {
178                            d->ioc_conf = idata;
179                            /*  Only bit 0 is implemented so far, the PCI bus 0 vs
180                                bus non-0 selection bit.  */
181                            if (idata & ~1) {
182                                    fatal("TODO: Write to unimplemented bit of"
183                                        " IOC_CONF: 0x%x\n", (int)idata);
184                                    exit(1);
185                            }
186                    }
187                    break;
188    
189            case LCA_IOC_TBIA:
190                    /*  TLB Invalidate All.  */
191                    /*  TODO: For now, let's just ignore it.  */
192                    break;
193    
194            case LCA_IOC_TB_ENA:
195                    if (writeflag == MEM_READ) {
196                            odata = d->tlb_enable;
197                    } else {
198                            d->tlb_enable = idata;
199                            /*  TODO: Actually implement this.  */
200                            if (idata & ~IOC_TB_ENA_TEN) {
201                                    fatal("TODO: LCA_IOC_TB_ENA value "
202                                        " (0x%"PRIx64") has unimplemented "
203                                        "bits.\n", (uint64_t)idata);
204                                    exit(1);
205                            }
206                    }
207                    break;
208    
209            case LCA_IOC_W_BASE0:
210                    if (writeflag == MEM_READ) {
211                            odata = d->window_base_0;
212                    } else {
213                            d->window_base_0 = idata;
214                            /*  TODO: Actually implement this.  */
215                            if (idata != 0ULL && idata != 0x300800000ULL) {
216                                    fatal("TODO: LCA_IOC_W_BASE0 value differs"
217                                        " (0x%"PRIx64") from the only implemented"
218                                        " values\n", (uint64_t)idata);
219                                    exit(1);
220                            }
221                    }
222                    break;
223    
224            case LCA_IOC_W_MASK0:
225                    if (writeflag == MEM_READ) {
226                            odata = d->window_mask_0;
227                    } else {
228                            d->window_mask_0 = idata;
229                            /*  TODO: Actually implement this.  */
230                            if (idata != 0x700000ULL) {
231                                    fatal("TODO: LCA_IOC_W_MASK0 value differs"
232                                        " (0x%"PRIx64") from the only implemented"
233                                        " value\n", (uint64_t)idata);
234                                    exit(1);
235                            }
236                    }
237                    break;
238    
239            case LCA_IOC_W_T_BASE0:
240                    if (writeflag == MEM_READ) {
241                            odata = d->window_t_base_0;
242                    } else {
243                            d->window_t_base_0 = idata;
244                            /*  TODO: Actually implement this.  */
245                    }
246                    break;
247    
248            case LCA_IOC_W_BASE1:
249                    if (writeflag == MEM_READ) {
250                            odata = d->window_base_1;
251                    } else {
252                            d->window_base_1 = idata;
253                            /*  TODO: Actually implement this.  */
254                            if (idata != 0x240000000ULL) {
255                                    fatal("TODO: LCA_IOC_W_BASE1 value differs"
256                                        " (0x%"PRIx64") from the only implemented"
257                                        " value\n", (uint64_t)idata);
258                                    exit(1);
259                            }
260                    }
261                    break;
262    
263            case LCA_IOC_W_MASK1:
264                    if (writeflag == MEM_READ) {
265                            odata = d->window_mask_1;
266                    } else {
267                            d->window_mask_1 = idata;
268                            /*  TODO: Actually implement this.  */
269                            if (idata != 0x3ff00000ULL) {
270                                    fatal("TODO: LCA_IOC_W_MASK1 value differs"
271                                        " (0x%"PRIx64") from the only implemented"
272                                        " value\n", (uint64_t)idata);
273                                    exit(1);
274                            }
275                    }
276                    break;
277    
278            case LCA_IOC_W_T_BASE1:
279                    if (writeflag == MEM_READ) {
280                            odata = d->window_t_base_1;
281                    } else {
282                            d->window_t_base_1 = idata;
283                            /*  TODO: Actually implement this.  */
284                    }
285                    break;
286    
287            default:fatal("[ lca_ioc: unimplemented %s to offset 0x%x",
288                        writeflag == MEM_WRITE? "write" : "read", (int)
289                        relative_addr);
290                    if (writeflag == MEM_WRITE)
291                            fatal(": 0x%x", (int)idata);
292                    fatal(" ]\n");
293                    exit(1);
294            }
295    
296            if (writeflag == MEM_READ)
297                    memory_writemax64(cpu, data, len, odata);
298    
299            return 1;
300    }
301    
302    
303  DEVINIT(lca)  DEVINIT(lca)
304  {  {
305          struct lca_data *d = malloc(sizeof(struct lca_data));          struct lca_data *d = malloc(sizeof(struct lca_data));
# Line 93  DEVINIT(lca) Line 309  DEVINIT(lca)
309          }          }
310          memset(d, 0, sizeof(struct lca_data));          memset(d, 0, sizeof(struct lca_data));
311    
312            /*  Register a PCI bus:  */
313            d->pci_data = bus_pci_init(
314                devinit->machine,
315                0                   /*  pciirq: TODO  */,
316                LCA_PCI_SIO,        /*  pci device io offset  */
317                0x00000000,         /*  pci device mem offset: TODO  */
318                0x00000000,         /*  PCI portbase: TODO  */
319                0x00000000,         /*  PCI membase: TODO  */
320                0x00000000,         /*  PCI irqbase: TODO  */
321                LCA_ISA_BASE,       /*  ISA portbase  */
322                LCA_ISA_MEMBASE,    /*  ISA membase  */
323                8);                 /*  ISA irqbase: TODO  */
324    
325            /*  Add the "sio0" controller (as seen by NetBSD):  */
326            bus_pci_add(devinit->machine, d->pci_data, devinit->machine->memory,
327                0, 7, 0, "i82378zb");
328    
329            memory_device_register(devinit->machine->memory, "lca_pci_conf",
330                LCA_PCI_CONF, 0x20000000, dev_lca_pci_conf_access, (void *)d,
331                DM_DEFAULT, NULL);
332    
333          memory_device_register(devinit->machine->memory, "lca_isa",          memory_device_register(devinit->machine->memory, "lca_isa",
334              LCA_PCI_SIO, 0x10000 << 5, dev_lca_isa_access, (void *)d,              LCA_PCI_SIO, 0x10000 << 5, dev_lca_isa_access, (void *)d,
335              DM_DEFAULT, NULL);              DM_DEFAULT, NULL);
336    
337            memory_device_register(devinit->machine->memory, "lca_ioc",
338                LCA_IOC_BASE, 0x20000000, dev_lca_ioc_access, (void *)d,
339                DM_DEFAULT, NULL);
340    
341          /*  TODO: IRQs etc.  */          /*  TODO: IRQs etc.  */
342          bus_isa_init(devinit->machine, BUS_ISA_IDE0 | BUS_ISA_IDE1,          bus_isa_init(devinit->machine, BUS_ISA_IDE0 | BUS_ISA_IDE1,
343              LCA_ISA_BASE, LCA_ISA_MEMBASE, 32, 48);              LCA_ISA_BASE, LCA_ISA_MEMBASE, 32, 48);

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

  ViewVC Help
Powered by ViewVC 1.1.26