dev_turbochannel.cc Source File

Back to the index.

dev_turbochannel.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-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: TURBOchannel bus framework, used in DECstation machines
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "devices.h"
36 #include "machine.h"
37 #include "memory.h"
38 #include "misc.h"
39 
40 #include "thirdparty/sfbreg.h"
41 
42 
43 #define DEVICE_MAX_NAMELEN 9
44 #define CARD_NAME_BUFLEN 9
45 #define CARD_FIRMWARE_BUFLEN 5
46 
48  int slot_nr;
49  uint64_t baseaddr;
50  uint64_t endaddr;
51 
52  int rom_skip;
53 
54  char device_name[DEVICE_MAX_NAMELEN]; /* NUL-terminated */
55 
56  /* These should be terminated with spaces */
61 };
62 
63 
64 DEVICE_ACCESS(turbochannel)
65 {
66  struct turbochannel_data *d = (struct turbochannel_data *) extra;
67  uint64_t idata = 0, odata = 0;
68 
69  if (writeflag == MEM_WRITE)
70  idata = memory_readmax64(cpu, data, len);
71 
72  relative_addr += d->rom_skip;
73 
74  if (writeflag == MEM_READ) {
75  debug("[ turbochannel: read from slot %i addr 0x%08lx (",
76  d->slot_nr, (long)relative_addr);
77 
78  relative_addr &= 0x7fff;
79 
80  switch (relative_addr) {
81  case 0x3e0:
82  odata = 0x00000001; debug("ROM width");
83  break;
84  case 0x3e4:
85  odata = 0x00000004; debug("ROM stride");
86  break;
87  case 0x3e8:
88  /* 8KB * romsize */
89  odata = 0x00000001; debug("ROM size");
90  break;
91  case 0x3ec:
92  /* 4MB * slotsize */
93  odata = 0x00000001; debug("slot size");
94  break;
95  case 0x3f0:
96  odata = 0x55555555; debug("ROM signature byte 0");
97  break;
98  case 0x3f4:
99  odata = 0x00000000; debug("ROM signature byte 1");
100  break;
101  case 0x3f8:
102  odata = 0xaaaaaaaa; debug("ROM signature byte 2");
103  break;
104  case 0x3fc:
105  odata = 0xffffffff; debug("ROM signature byte 3");
106  break;
107  case 0x470:
108  /* 0=nothing, 1=parity */
109  odata = 0x00000000; debug("flags"); break;
110  default:
111  if (relative_addr >= 0x400 && relative_addr < 0x420)
112  odata = d->card_firmware_version[
113  (relative_addr-0x400)/4];
114  else if (relative_addr >= 0x420 &&
115  relative_addr < 0x440)
116  odata = d->card_vendor_name[
117  (relative_addr-0x420)/4];
118  else if (relative_addr >= 0x440 &&
119  relative_addr < 0x460)
120  odata = d->card_module_name[
121  (relative_addr-0x440)/4];
122  else if (relative_addr >= 0x460 &&
123  relative_addr < 0x470)
124  odata = d->card_firmware_type[
125  (relative_addr-0x460)/4];
126  else {
127  debug("?");
128  }
129  }
130 
131  /*
132  * If this slot is empty, return an error so that a DBE
133  * exception is caused. (This is the way DECstation operating
134  * systems have to detect the absence of cards in a
135  * TURBOchannel slot.)
136  *
137  * NOTE: The Sprite kernel reads from offsets 0x3e0..0x400
138  * without handling the DBE exception, and both Ultrix and
139  * NetBSD seem to detect the DBE exception using addresses
140  * around offset 0x0 or 0x3c0000. This code seems to work
141  * with all of the those OS kernels:
142  */
143  if (d->card_module_name[0] == ' ') {
144  /* Return no data for empty slot: */
145  odata = 0;
146 
147  /* Return DBE exception in some cases: */
148  if (relative_addr < 0x3e0 || relative_addr >= 0x500)
149  return 0;
150  }
151 
152  debug(") ]\n");
153  } else {
154  /* debug("[ turbochannel: write to 0x%08lx: 0x%08x ]\n",
155  (long)relative_addr, (int)idata); */
156  }
157 
158  if (writeflag == MEM_READ)
159  memory_writemax64(cpu, data, len, odata);
160 
161  return 1;
162 }
163 
164 
165 /*
166  * dev_turbochannel_init():
167  *
168  * This is a generic turbochannel card device. device_name should point
169  * to a string such as "PMAG-BA".
170  *
171  * TODO: When running for example dual-head, maybe the name of each
172  * framebuffer should include the card slot number?
173  */
174 void dev_turbochannel_init(struct machine *machine, struct memory *mem,
175  int slot_nr, uint64_t baseaddr, uint64_t endaddr,
176  const char *device_name, const char *irq_path)
177 {
178  struct vfb_data *fb;
179  struct turbochannel_data *d;
180  int rom_offset=0x3c0000, rom_length=DEV_TURBOCHANNEL_LEN, rom_skip=0;
181  char *name2;
182  size_t nlen;
183 
184  if (device_name == NULL)
185  return;
186 
187  if (strlen(device_name) > 8) {
188  fprintf(stderr, "dev_turbochannel_init(): bad device_name\n");
189  exit(1);
190  }
191 
192  CHECK_ALLOCATION(d = (struct turbochannel_data *) malloc(sizeof(struct turbochannel_data)));
193  memset(d, 0, sizeof(struct turbochannel_data));
194 
195  d->slot_nr = slot_nr;
196  d->baseaddr = baseaddr;
197  d->endaddr = endaddr;
198 
199  strlcpy(d->device_name, device_name, DEVICE_MAX_NAMELEN);
200 
201  strncpy(d->card_firmware_version, "V5.3a ", CARD_NAME_BUFLEN);
202  strncpy(d->card_vendor_name, "DEC ", CARD_NAME_BUFLEN);
203  strncpy(d->card_firmware_type, "TCF0", CARD_FIRMWARE_BUFLEN);
204 
205  memset(d->card_module_name, ' ', 8);
206  memcpy(d->card_module_name, device_name, strlen(device_name));
207 
208  /*
209  * According to NetBSD/pmax:
210  *
211  * PMAD-AA: le1 at tc0 slot 2 offset 0x0: address 00:00:00:00:00:00
212  * PMAG-AA: mfb0 at tc0 slot 2 offset 0x0: 1280x1024x8
213  * PMAG-BA: cfb0 at tc0 slot 2 offset 0x0cfb0: 1024x864x8
214  * PMAG-CA: px0 at tc0 slot 2 offset 0x0: 2D, 4x1 stamp, 8 plane
215  * (PMAG-DA,EA,FA,FB are also pixelstamps)
216  * PMAG-DV: xcfb0 at tc0 slot 2 offset 0x0: 1024x768x8
217  * PMAG-JA: "truecolor" in Ultrix
218  * PMAGB-BA: sfb0 at tc0 slot 0 offset 0x0: 0x0x8
219  * PMAGB-VA: sfb0 at tc0 slot 2 offset 0x0: 0x0x8
220  * PMAZ-AA: asc0 at tc0 slot 2 offset 0x0: NCR53C94, 25MHz, SCSI ID 7
221  *
222  * PMAF-FA: fta0 at tc0 slot 0 (fddi network, "DEC", "V1.0b")
223  */
224 
225  if (strcmp(device_name, "PMAD-AA")==0) {
226  /* le in NetBSD, Lance ethernet */
227  dev_le_init(machine, mem, baseaddr, 0, 0,
228  irq_path, DEV_LE_LENGTH);
229  /* One ROM at 0x1c03e0, and one at 0x3c0000. */
230  rom_skip = 0x300;
231  rom_offset = 0x1c0000;
232  rom_length = 0x201000;
233  } else if (strcmp(device_name, "PMAZ-AA")==0) {
234  /* asc in NetBSD, SCSI */
235  dev_asc_init(machine, mem, baseaddr, irq_path, d,
236  DEV_ASC_DEC, NULL, NULL);
237  rom_offset = 0xc0000;
238  /* There is a copy at 0x0, at least that's where Linux
239  looks for the rom signature */
240  } else if (strcmp(device_name, "PMAG-AA")==0) {
241  /* mfb in NetBSD */
242  fb = dev_fb_init(machine, mem, baseaddr + VFB_MFB_VRAM,
243  VFB_GENERIC, 1280, 1024, 2048, 1024, 8, device_name);
244  /* bt455 = palette, bt431 = cursor */
245  dev_bt455_init(mem, baseaddr + VFB_MFB_BT455, fb);
246  dev_bt431_init(mem, baseaddr + VFB_MFB_BT431, fb, 8);
247  rom_offset = 0;
248  } else if (strcmp(device_name, "PMAG-BA")==0) {
249  /* cfb in NetBSD */
250  fb = dev_fb_init(machine, mem, baseaddr, VFB_GENERIC,
251  1024,864, 1024,1024,8, device_name);
252  dev_bt459_init(machine, mem, baseaddr + VFB_CFB_BT459,
253  baseaddr + 0x300000, fb, 8, irq_path, BT459_BA);
254  /* ROM at both 0x380000 and 0x3c0000? */
255  rom_offset = 0x380000;
256  rom_length = 0x080000;
257  } else if (strcmp(device_name, "PMAGB-BA")==0) {
258  /* sfb in NetBSD */
259  /* TODO: This is not working with Ultrix yet. */
260  fb = dev_fb_init(machine, mem, baseaddr + SFB_OFFSET_VRAM,
261  VFB_GENERIC, 1280,1024, 1280,1024,8, device_name);
262  dev_sfb_init(machine, mem, baseaddr + SFB_ASIC_OFFSET, fb);
263  /* TODO: the CLEAR doesn't get through, as the address
264  range is already in use by the asic */
265  dev_bt459_init(machine, mem, baseaddr + SFB_OFFSET_BT459,
266  baseaddr + SFB_CLEAR, fb, 8, irq_path, BT459_BBA);
267  rom_offset = 0x0; /* ? TODO */
268  } else if (strcmp(device_name, "PMAG-CA")==0) {
269  /* px in NetBSD */
270  dev_px_init(machine, mem, baseaddr, DEV_PX_TYPE_PX, irq_path);
271  rom_offset = 0x3c0000;
272  } else if (strcmp(device_name, "PMAG-DA")==0) {
273  /* pxg in NetBSD */
274  dev_px_init(machine, mem, baseaddr, DEV_PX_TYPE_PXG, irq_path);
275  rom_offset = 0x3c0000;
276  } else if (strcmp(device_name, "PMAG-EA")==0) {
277  /* pxg+ in NetBSD: TODO (not supported by the kernel
278  I've tried) */
279  fatal("TODO (see dev_turbochannel.c)\n");
280  rom_offset = 0x3c0000;
281  } else if (strcmp(device_name, "PMAG-FA")==0) {
282  /* "pxg+ Turbo" in NetBSD */
283  dev_px_init(machine, mem, baseaddr,
284  DEV_PX_TYPE_PXGPLUSTURBO, irq_path);
285  rom_offset = 0x3c0000;
286  } else if (strcmp(device_name, "PMAG-DV")==0) {
287  /* xcfb in NetBSD: TODO */
288  fb = dev_fb_init(machine, mem, baseaddr + 0x2000000,
289  VFB_DEC_MAXINE, 0, 0, 0, 0, 0, "PMAG-DV");
290  /* TODO: not yet usable, needs a IMS332 vdac */
291  rom_offset = 0x3c0000;
292  } else if (strcmp(device_name, "PMAG-JA")==0) {
293  /* "Truecolor", mixed 8- and 24-bit */
294  dev_pmagja_init(machine, mem, baseaddr, irq_path);
295  rom_offset = 0; /* NOTE: 0, not 0x3c0000 */
296  } else if (strcmp(device_name, "PMAG-RO")==0) {
297  /* This works at least B/W in Ultrix, so far. */
298  fb = dev_fb_init(machine, mem, baseaddr + 0x200000,
299  VFB_GENERIC, 1280,1024, 1280,1024, 8, "PMAG-RO");
300  /* TODO: bt463 at offset 0x040000, not bt459 */
301  dev_bt459_init(machine, mem, baseaddr + 0x40000, 0,
302  fb, 8, irq_path, 0); /* TODO: type */
303  dev_bt431_init(mem, baseaddr + 0x40010, fb, 8); /* cursor */
304  rom_offset = 0x3c0000;
305  } else if (device_name[0] == '\0') {
306  /* If this slot is empty, then occupy the entire
307  4MB slot address range: */
308  rom_offset = 0;
309  rom_length = 4*1048576;
310  } else {
311  fatal("warning: unknown TURBOchannel device name \"%s\"\n",
312  device_name);
313  }
314 
315  d->rom_skip = rom_skip;
316 
317  nlen = strlen(device_name) + 30;
318  CHECK_ALLOCATION(name2 = (char *) malloc(nlen));
319 
320  if (*device_name)
321  snprintf(name2, nlen, "turbochannel [%s]", device_name);
322  else
323  snprintf(name2, nlen, "turbochannel");
324 
325  memory_device_register(mem, name2, baseaddr + rom_offset + rom_skip,
326  rom_length-rom_skip, dev_turbochannel_access, d, DM_DEFAULT, NULL);
327 }
328 
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
void fatal(const char *fmt,...)
Definition: main.cc:152
#define DM_DEFAULT
Definition: memory.h:130
void dev_asc_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, const char *irq_path, void *turbochannel, int mode, size_t(*dma_controller)(void *dma_controller_data, unsigned char *data, size_t len, int writeflag), void *dma_controller_data)
Definition: dev_asc.cc:1226
#define SFB_OFFSET_VRAM
Definition: sfbreg.h:43
#define CARD_FIRMWARE_BUFLEN
#define CARD_NAME_BUFLEN
void dev_px_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, int px_type, const char *irq_path)
Definition: dev_px.cc:752
struct vfb_data * dev_fb_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, int vfb_type, int visible_xsize, int visible_ysize, int xsize, int ysize, int bit_depth, const char *name)
Definition: dev_fb.cc:834
#define VFB_MFB_BT431
Definition: devices.h:235
#define VFB_GENERIC
Definition: devices.h:190
void dev_pmagja_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, const char *irq_path)
Definition: dev_pmagja.cc:196
#define MEM_READ
Definition: memory.h:116
char card_firmware_type[CARD_FIRMWARE_BUFLEN]
#define SFB_OFFSET_BT459
Definition: sfbreg.h:44
void dev_bt431_init(struct memory *mem, uint64_t baseaddr, struct vfb_data *vfb_data, int planes)
Definition: dev_bt431.cc:196
void dev_le_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, uint64_t buf_start, uint64_t buf_end, const char *irq_path, int len)
Definition: dev_le.cc:759
void dev_turbochannel_init(struct machine *machine, struct memory *mem, int slot_nr, uint64_t baseaddr, uint64_t endaddr, const char *device_name, const char *irq_path)
#define VFB_DEC_MAXINE
Definition: devices.h:194
#define DEV_TURBOCHANNEL_LEN
Definition: devices.h:465
void dev_sfb_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, struct vfb_data *fb)
Definition: dev_sfb.cc:94
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
#define BT459_BBA
Definition: devices.h:149
u_short data
Definition: siireg.h:79
void dev_bt459_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, uint64_t baseaddr_irq, struct vfb_data *vfb_data, int planes, const char *irq_path, int type)
Definition: dev_bt459.cc:522
#define DEV_PX_TYPE_PX
Definition: devices.h:353
#define MEM_WRITE
Definition: memory.h:117
#define VFB_MFB_VRAM
Definition: devices.h:236
#define BT459_BA
Definition: devices.h:148
DEVICE_ACCESS(turbochannel)
#define VFB_CFB_BT459
Definition: devices.h:237
int dev_turbochannel_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
#define DEV_PX_TYPE_PXG
Definition: devices.h:354
#define debug
Definition: dev_adb.cc:57
void dev_bt455_init(struct memory *mem, uint64_t baseaddr, struct vfb_data *vfb_data)
Definition: dev_bt455.cc:167
char device_name[DEVICE_MAX_NAMELEN]
Definition: cpu.h:326
char card_module_name[CARD_NAME_BUFLEN]
#define VFB_MFB_BT455
Definition: devices.h:234
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
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
#define DEV_LE_LENGTH
Definition: devices.h:292
#define DEVICE_MAX_NAMELEN
#define DEV_ASC_DEC
Definition: devices.h:116
#define SFB_CLEAR
Definition: sfbreg.h:68
char card_vendor_name[CARD_NAME_BUFLEN]
Definition: memory.h:75
#define DEV_PX_TYPE_PXGPLUSTURBO
Definition: devices.h:356
char card_firmware_version[CARD_NAME_BUFLEN]
#define SFB_ASIC_OFFSET
Definition: sfbreg.h:45

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13