dev_v3.cc Source File

Back to the index.

dev_v3.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2009 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * COMMENT: V3 Semiconductor PCI controller
29  *
30  * The ISA interrupt controller part forwards ISA interrupts as follows
31  * (on Algor P5064):
32  *
33  * ISA interrupt 3 and 4 -> MIPS interrupt 4 ("Local")
34  * All other ISA interrupts -> MIPS interrupt 2 ("ISA")
35  *
36  * See NetBSD's src/sys/arch/algor/pci/ for details.
37  */
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 #include "bus_pci.h"
44 #include "cpu.h"
45 #include "device.h"
46 #include "devices.h"
47 #include "interrupt.h"
48 #include "machine.h"
49 #include "memory.h"
50 #include "misc.h"
51 
52 
53 struct v3_data {
54  struct interrupt irq_isa;
55  struct interrupt irq_local;
56  uint8_t secondary_mask1;
57 
58  struct pic8259_data* pic1;
59  struct pic8259_data* pic2;
61 
62  struct pci_data *pci_data;
63  uint16_t lb_map0;
64 };
65 
66 
67 /*
68  * v3_isa_interrupt_common():
69  */
70 void v3_isa_interrupt_common(struct v3_data *d, int old_isa_assert)
71 {
72  int new_isa_assert;
73 
74  /* Any interrupt assertions on PIC2 go to irq 2 on PIC1 */
75  /* (TODO: don't hardcode this here) */
76  if (d->pic2->irr & ~d->pic2->ier)
77  d->pic1->irr |= 0x04;
78  else
79  d->pic1->irr &= ~0x04;
80 
81  new_isa_assert = d->pic1->irr & ~d->pic1->ier;
82 
83  if (old_isa_assert == new_isa_assert)
84  return;
85 
86  if (new_isa_assert & d->secondary_mask1)
88  else
90 
91  if (new_isa_assert & ~d->secondary_mask1)
93  else
95 }
96 
97 
98 /*
99  * v3_isa_interrupt_assert():
100  *
101  * Called whenever an ISA device asserts an interrupt (0..15).
102  * If the interrupt number is 16, then it is a re-assert.
103  */
105 {
106  struct v3_data *d = (struct v3_data *) interrupt->extra;
107  int old_isa_assert, line = interrupt->line;
108  int mask = 1 << (line & 7);
109 
110  old_isa_assert = d->pic1->irr & ~d->pic1->ier;
111 
112  if (line < 8)
113  d->pic1->irr |= mask;
114  else if (line < 16)
115  d->pic2->irr |= mask;
116 
117  v3_isa_interrupt_common(d, old_isa_assert);
118 }
119 
120 
121 /*
122  * v3_isa_interrupt_deassert():
123  *
124  * Called whenever an ISA device deasserts an interrupt (0..15).
125  * If the interrupt number is 16, then it is a re-assert.
126  */
128 {
129  struct v3_data *d = (struct v3_data *) interrupt->extra;
130  int line = interrupt->line, mask = 1 << (line & 7);
131  int old_irr1 = d->pic1->irr, old_isa_assert;
132 
133  old_isa_assert = old_irr1 & ~d->pic1->ier;
134 
135  if (line < 8)
136  d->pic1->irr &= ~mask;
137  else if (line < 16)
138  d->pic2->irr &= ~mask;
139 
140  /* If IRQ 0 has been cleared, then this is a timer interrupt.
141  Let's ack it here: */
142  if (old_irr1 & 1 && !(d->pic1->irr & 1) &&
143  d->ptr_to_pending_timer_interrupts != NULL &&
146 
147  v3_isa_interrupt_common(d, old_isa_assert);
148 }
149 
150 
152 {
153  uint64_t idata = 0, odata = 0;
154  int bus, dev, func, reg;
155  struct v3_data *d = (struct v3_data *) extra;
156 
157  if (writeflag == MEM_WRITE)
159 
160  /* Decompose the tag: */
161  relative_addr &= 0xfffff;
162  relative_addr |= ((d->lb_map0 & 0xfff0) << 16);
163  bus = 0;
164  for (dev=24; dev<32; dev++)
165  if (relative_addr & (1 << dev))
166  break;
167  dev -= 24;
168  if (dev == 8) {
169  fatal("[ v3_pci: NO DEVICE? ]\n");
170  dev = 0;
171  }
172  func = (relative_addr >> 8) & 7;
173  reg = relative_addr & 0xfc;
174  bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, reg);
175 
176  /* Pass semi-direct PCI accesses onto bus_pci: */
177  bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ?
178  &odata : &idata, len, writeflag);
179 
180  if (writeflag == MEM_READ)
182 
183  return 1;
184 }
185 
186 
188 {
189  struct v3_data *d = (struct v3_data *) extra;
190  uint64_t idata = 0, odata = 0;
191 
192  if (writeflag == MEM_WRITE)
193  idata = memory_readmax64(cpu, data, len);
194 
195  switch (relative_addr) {
196 
197  case 0x06: /* PCI stat */
198  break;
199 
200  case 0x08: /* Revision */
201  odata = 4;
202  break;
203 
204  case 0x18: /* PCI DMA base 1 */
205  odata = 0x11000000;
206  break;
207 
208  case 0x5e: /* LB MAP0 */
209  if (writeflag == MEM_READ)
210  odata = d->lb_map0;
211  else
212  d->lb_map0 = idata;
213  break;
214 
215  case 0x62: /* PCI mem base 1 */
216  odata = 0x1100;
217  break;
218 
219  case 0x64: /* L2 BASE */
220  odata = 1; /* pci i/o enable */
221  break;
222 
223  case 0x66: /* Map 2 */
224  odata = 0x1d00;
225  break;
226 
227  default:if (writeflag == MEM_WRITE) {
228  fatal("[ v3: unimplemented write to "
229  "offset 0x%x: data=0x%x ]\n", (int)
230  relative_addr, (int)idata);
231  } else {
232  fatal("[ v3: unimplemented read from "
233  "offset 0x%x ]\n", (int)relative_addr);
234  }
235  }
236 
237  if (writeflag == MEM_READ)
238  memory_writemax64(cpu, data, len, odata);
239 
240  return 1;
241 }
242 
243 
245 {
246  struct v3_data *d;
247  uint32_t isa_port_base = 0x1d000000;
248  char tmpstr[200];
249  char isa_irq_base[200];
250  char pci_irq_base[200];
251  int i;
252 
253  CHECK_ALLOCATION(d = (struct v3_data *) malloc(sizeof(struct v3_data)));
254  memset(d, 0, sizeof(struct v3_data));
255 
256  switch (devinit->machine->machine_type) {
257  case MACHINE_ALGOR:
258  snprintf(tmpstr, sizeof(tmpstr), "%s.4",
260  INTERRUPT_CONNECT(tmpstr, d->irq_local);
261 
262  snprintf(tmpstr, sizeof(tmpstr), "%s.2",
264  INTERRUPT_CONNECT(tmpstr, d->irq_isa);
265 
266  d->secondary_mask1 = 0x18;
267  break;
268 
269  default:fatal("!\n! WARNING: v3 for non-implemented machine"
270  " type %i\n!\n", devinit->machine->machine_type);
271  exit(1);
272  }
273 
274  /*
275  * Register the 16 possible ISA interrupts, plus a dummy. The
276  * dummy is used by re-asserts.
277  */
278  for (i=0; i<17; i++) {
279  struct interrupt templ;
280  char n[300];
281  snprintf(n, sizeof(n), "%s.v3.isa.%i",
282  devinit->interrupt_path, i);
283  memset(&templ, 0, sizeof(templ));
284  templ.line = i;
285  templ.name = n;
286  templ.extra = d;
290  }
291 
292  /* Register two 8259 PICs: */
293  snprintf(tmpstr, sizeof(tmpstr), "8259 irq=%s.v3.isa.16 addr=0x%llx",
294  devinit->interrupt_path, (long long)(isa_port_base + 0x20));
295  d->pic1 = devinit->machine->isa_pic_data.pic1 = (struct pic8259_data *)
296  device_add(devinit->machine, tmpstr);
299 
300  snprintf(tmpstr, sizeof(tmpstr), "8259 irq=%s.v3.isa.2 addr=0x%llx",
301  devinit->interrupt_path, (long long)(isa_port_base + 0xa0));
302  d->pic2 = devinit->machine->isa_pic_data.pic2 = (struct pic8259_data *)
303  device_add(devinit->machine, tmpstr);
304 
305  snprintf(isa_irq_base, sizeof(isa_irq_base), "%s.v3",
307  snprintf(pci_irq_base, sizeof(pci_irq_base), "%s.v3",
309 
310  /* Register a PCI bus: */
311  d->pci_data = bus_pci_init(
312  devinit->machine,
313  pci_irq_base /* pciirq: TODO */,
314  0x1d000000, /* pci device io offset */
315  0x11000000, /* pci device mem offset: TODO */
316  0x00000000, /* PCI portbase: TODO */
317  0x00000000, /* PCI membase: TODO */
318  pci_irq_base, /* PCI irqbase */
319  isa_port_base, /* ISA portbase */
320  0x10000000, /* ISA membase */
321  isa_irq_base); /* ISA irqbase */
322 
323  switch (devinit->machine->machine_type) {
324  case MACHINE_ALGOR:
326  devinit->machine->memory, 0, 2, 0, "piix3_isa");
328  devinit->machine->memory, 0, 2, 1, "piix3_ide");
329  break;
330  default:fatal("!\n! WARNING: v3 for non-implemented machine"
331  " type %i\n!\n", devinit->machine->machine_type);
332  exit(1);
333  }
334 
335  /* PCI configuration space: */
337  0x1ee00000, 0x100000, dev_v3_pci_access, d, DM_DEFAULT, NULL);
338 
339  /* PCI controller: */
341  0x1ef00000, 0x1000, dev_v3_access, d, DM_DEFAULT, NULL);
342 
344 
345  return 1;
346 }
347 
data
u_short data
Definition: siireg.h:79
isa_pic_data::pending_timer_interrupts
int * pending_timer_interrupts
Definition: machine.h:51
v3_isa_interrupt_common
void v3_isa_interrupt_common(struct v3_data *d, int old_isa_assert)
Definition: dev_v3.cc:70
INTERRUPT_CONNECT
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
v3_data
Definition: dev_v3.cc:53
INTERRUPT_ASSERT
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
v3_data::irq_isa
struct interrupt irq_isa
Definition: dev_v3.cc:54
interrupt::interrupt_deassert
void(* interrupt_deassert)(struct interrupt *)
Definition: interrupt.h:39
v3_isa_interrupt_assert
void v3_isa_interrupt_assert(struct interrupt *interrupt)
Definition: dev_v3.cc:104
bus_pci_setaddr
void bus_pci_setaddr(struct cpu *cpu, struct pci_data *pci_data, int bus, int device, int function, int reg)
Definition: bus_pci.cc:196
isa_pic_data::pic2
struct pic8259_data * pic2
Definition: machine.h:49
memory_device_register
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
bus_pci_data_access
void bus_pci_data_access(struct cpu *cpu, struct pci_data *pci_data, uint64_t *data, int len, int writeflag)
Definition: bus_pci.cc:95
MEM_READ
#define MEM_READ
Definition: memory.h:116
DM_DEFAULT
#define DM_DEFAULT
Definition: memory.h:130
interrupt::extra
void * extra
Definition: interrupt.h:59
isa_pic_data::pic1
struct pic8259_data * pic1
Definition: machine.h:48
devinit::machine
struct machine * machine
Definition: device.h:41
v3_data::pic1
struct pic8259_data * pic1
Definition: dev_v3.cc:58
v3_data::pci_data
struct pci_data * pci_data
Definition: dev_v3.cc:62
device.h
bus_pci_init
struct pci_data * bus_pci_init(struct machine *machine, const char *irq_path, uint64_t pci_actual_io_offset, uint64_t pci_actual_mem_offset, uint64_t pci_portbase, uint64_t pci_membase, const char *pci_irqbase, uint64_t isa_portbase, uint64_t isa_membase, const char *isa_irqbase)
Definition: bus_pci.cc:355
v3_data::irq_local
struct interrupt irq_local
Definition: dev_v3.cc:55
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
devinit::interrupt_path
char * interrupt_path
Definition: device.h:50
interrupt.h
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
machine::isa_pic_data
struct isa_pic_data isa_pic_data
Definition: machine.h:190
misc.h
memory_readmax64
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
device_add
void * device_add(struct machine *machine, const char *name_and_params)
Definition: device.cc:252
machine.h
v3_data::secondary_mask1
uint8_t secondary_mask1
Definition: dev_v3.cc:56
pic8259_data
Definition: devices.h:63
devinit
Definition: device.h:40
v3_data::ptr_to_pending_timer_interrupts
int * ptr_to_pending_timer_interrupts
Definition: dev_v3.cc:60
cpu.h
MACHINE_ALGOR
#define MACHINE_ALGOR
Definition: machine.h:220
machine::memory
struct memory * memory
Definition: machine.h:126
bus_pci.h
pic8259_data::irr
uint8_t irr
Definition: devices.h:72
devinit::return_ptr
void * return_ptr
Definition: device.h:56
reg
#define reg(x)
Definition: tmp_alpha_tail.cc:53
pic8259_data::ier
uint8_t ier
Definition: devices.h:74
DEVICE_ACCESS
DEVICE_ACCESS(v3_pci)
Definition: dev_v3.cc:151
v3_data::lb_map0
uint16_t lb_map0
Definition: dev_v3.cc:63
DEVINIT
DEVINIT(v3)
Definition: dev_v3.cc:244
INTERRUPT_DEASSERT
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
machine::machine_type
int machine_type
Definition: machine.h:111
interrupt::line
uint32_t line
Definition: interrupt.h:51
interrupt::interrupt_assert
void(* interrupt_assert)(struct interrupt *)
Definition: interrupt.h:38
interrupt_handler_register
void interrupt_handler_register(struct interrupt *templ)
Definition: interrupt.cc:81
MEM_PCI_LITTLE_ENDIAN
#define MEM_PCI_LITTLE_ENDIAN
Definition: memory.h:97
interrupt::name
char * name
Definition: interrupt.h:66
interrupt
Definition: interrupt.h:36
memory_writemax64
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
v3_isa_interrupt_deassert
void v3_isa_interrupt_deassert(struct interrupt *interrupt)
Definition: dev_v3.cc:127
devices.h
cpu
Definition: cpu.h:326
v3_data::pic2
struct pic8259_data * pic2
Definition: dev_v3.cc:59
bus_pci_add
void bus_pci_add(struct machine *machine, struct pci_data *pci_data, struct memory *mem, int bus, int device, int function, const char *name)
Definition: bus_pci.cc:216
memory.h
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18