fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 507 lines 11 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/devices/pci.c * 7 * Created: 2004-06-05 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2004-2009 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include <stdio.h> 24#include <stdlib.h> 25 26#include "memory.h" 27#include "pci.h" 28 29 30void pci_dev_init (pci_dev_t *dev) 31{ 32 unsigned i; 33 34 dev->index = 0; 35 36 for (i = 0; i < PCI_REG_MAX; i++) { 37 dev->reg[i] = NULL; 38 } 39 40 for (i = 0; i < PCI_MEM_MAX; i++) { 41 dev->mem[i] = NULL; 42 } 43 44 for (i = 0; i < 256; i++) { 45 dev->config[i] = 0; 46 dev->wrmask[i] = 0; 47 } 48 49 dev->config[0] = 0xff; 50 dev->config[1] = 0xff; 51 52 dev->cfg_ext = NULL; 53 dev->get_cfg8 = NULL; 54 dev->get_cfg16 = NULL; 55 dev->get_cfg32 = NULL; 56 dev->set_cfg8 = NULL; 57 dev->get_cfg16 = NULL; 58 dev->set_cfg32 = NULL; 59 60 for (i = 0; i < 4; i++) { 61 dev->intr[i] = NULL; 62 dev->intr_ext[i] = NULL; 63 dev->intr_val[i] = 0; 64 } 65 66 dev->ext = NULL; 67} 68 69void pci_dev_free (pci_dev_t *dev) 70{ 71} 72 73void pci_dev_set_intr_fct (pci_dev_t *dev, unsigned intr, void *ext, void *fct) 74{ 75 if (intr < 4) { 76 dev->intr[intr] = fct; 77 dev->intr_ext[intr] = ext; 78 dev->intr_val[intr] = 0; 79 } 80} 81 82void pci_dev_set_intr (pci_dev_t *dev, unsigned intr, unsigned char val) 83{ 84 if (intr >= 4) { 85 return; 86 } 87 88 val = (val != 0); 89 90 if (val != dev->intr_val[intr]) { 91 dev->intr_val[intr] = val; 92 93 if (dev->intr[intr] != NULL) { 94 dev->intr[intr] (dev->intr_ext[intr], val); 95 } 96 97 if (dev->pci != NULL) { 98 pci_set_intr (dev->pci, dev->index, intr, val); 99 } 100 } 101} 102 103void pci_dev_set_inta (pci_dev_t *dev, unsigned char val) 104{ 105 pci_dev_set_intr (dev, 0, val); 106} 107 108void pci_dev_set_intb (pci_dev_t *dev, unsigned char val) 109{ 110 pci_dev_set_intr (dev, 1, val); 111} 112 113void pci_dev_set_intc (pci_dev_t *dev, unsigned char val) 114{ 115 pci_dev_set_intr (dev, 2, val); 116} 117 118void pci_dev_set_intd (pci_dev_t *dev, unsigned char val) 119{ 120 pci_dev_set_intr (dev, 3, val); 121} 122 123void pci_dev_set_device_id (pci_dev_t *dev, unsigned vendor, unsigned id) 124{ 125 buf_set_uint16_le (dev->config, 0x00, vendor); 126 buf_set_uint16_le (dev->config, 0x02, id); 127} 128 129void pci_dev_set_cfg_mask (pci_dev_t *dev, unsigned i, unsigned n, int val) 130{ 131 unsigned k, m; 132 133 while (n > 0) { 134 k = i >> 3; 135 m = 1 << (i & 7); 136 137 if (k > 255) { 138 return; 139 } 140 141 if (val) { 142 dev->wrmask[k] |= m; 143 } 144 else { 145 dev->wrmask[k] &= ~m; 146 } 147 148 i += 1; 149 n -= 1; 150 } 151} 152 153unsigned char pci_dev_get_cfg8 (pci_dev_t *dev, unsigned long addr) 154{ 155 if (addr <= 255) { 156 return (dev->config[addr]); 157 } 158 159 return (0); 160} 161 162unsigned short pci_dev_get_cfg16 (pci_dev_t *dev, unsigned long addr) 163{ 164 unsigned short val; 165 166 val = pci_dev_get_cfg8 (dev, addr + 1); 167 val = (val << 8) | pci_dev_get_cfg8 (dev, addr); 168 169 return (val); 170} 171 172unsigned long pci_dev_get_cfg32 (pci_dev_t *dev, unsigned long addr) 173{ 174 unsigned long val; 175 176 val = pci_dev_get_cfg8 (dev, addr + 3); 177 val = (val << 8) | pci_dev_get_cfg8 (dev, addr + 2); 178 val = (val << 8) | pci_dev_get_cfg8 (dev, addr + 1); 179 val = (val << 8) | pci_dev_get_cfg8 (dev, addr); 180 181 return (val); 182} 183 184void pci_dev_set_cfg8 (pci_dev_t *dev, unsigned long addr, unsigned char val) 185{ 186 if (addr <= 255) { 187 val = (val & dev->wrmask[addr]) | (dev->config[addr] & ~dev->wrmask[addr]); 188 dev->config[addr] = val; 189 } 190} 191 192void pci_dev_set_cfg16 (pci_dev_t *dev, unsigned long addr, unsigned short val) 193{ 194 pci_dev_set_cfg8 (dev, addr, val & 0xff); 195 pci_dev_set_cfg8 (dev, addr + 1, (val >> 8) & 0xff); 196} 197 198void pci_dev_set_cfg32 (pci_dev_t *dev, unsigned long addr, unsigned long val) 199{ 200 pci_dev_set_cfg8 (dev, addr, val & 0xff); 201 pci_dev_set_cfg8 (dev, addr + 1, (val >> 8) & 0xff); 202 pci_dev_set_cfg8 (dev, addr + 2, (val >> 16) & 0xff); 203 pci_dev_set_cfg8 (dev, addr + 3, (val >> 24) & 0xff); 204} 205 206 207void pci_init (pci_bus_t *pci) 208{ 209 unsigned i, j; 210 211 for (i = 0; i < 32; i++) { 212 pci->dev[i] = NULL; 213 } 214 215 pci->asio = NULL; 216 pci->asmem = NULL; 217 218 for (i = 0; i < 32; i++) { 219 for (j = 0; j < 4; j++) { 220 pci->irq[i][j] = NULL; 221 pci->irq_ext[i][j] = NULL; 222 pci->irq_val[i][j] = 0; 223 } 224 } 225 226 pci->cfgaddr = 0; 227 pci->cfgdata = 0; 228} 229 230void pci_free (pci_bus_t *pci) 231{ 232} 233 234void pci_set_device (pci_bus_t *pci, pci_dev_t *dev, unsigned i) 235{ 236 unsigned j; 237 pci_dev_t *old; 238 239 i &= 0x1f; 240 241 old = pci->dev[i]; 242 243 if (old != NULL) { 244 if (pci->asio != NULL) { 245 for (j = 0; j < PCI_REG_MAX; j++) { 246 if (dev->reg[j] != NULL) { 247 mem_rmv_blk (pci->asio, dev->reg[j]); 248 } 249 } 250 } 251 252 if (pci->asmem != NULL) { 253 for (j = 0; j < PCI_MEM_MAX; j++) { 254 if (dev->mem[j] != NULL) { 255 mem_rmv_blk (pci->asmem, dev->mem[j]); 256 } 257 } 258 } 259 } 260 261 dev->index = i; 262 dev->pci = pci; 263 264 pci->dev[i] = dev; 265 266 if (dev != NULL) { 267 if (pci->asio != NULL) { 268 for (j = 0; j < PCI_REG_MAX; j++) { 269 if (dev->reg[j] != NULL) { 270 mem_add_blk (pci->asio, dev->reg[j], 0); 271 } 272 } 273 } 274 275 if (pci->asmem != NULL) { 276 for (j = 0; j < PCI_MEM_MAX; j++) { 277 if (dev->mem[j] != NULL) { 278 mem_add_blk (pci->asmem, dev->mem[j], 0); 279 } 280 } 281 } 282 } 283} 284 285void pci_set_asio (pci_bus_t *pci, memory_t *as) 286{ 287 pci->asio = as; 288} 289 290void pci_set_asmem (pci_bus_t *pci, memory_t *as) 291{ 292 pci->asmem = as; 293} 294 295void pci_set_irq_fct (pci_bus_t *pci, unsigned dev, unsigned intr, void *ext, void *fct) 296{ 297 if ((dev < 32) && (intr < 4)) { 298 pci->irq[dev][intr] = fct; 299 pci->irq_ext[dev][intr] = ext; 300 pci->irq_val[dev][intr] = 0; 301 } 302} 303 304void pci_set_cfg8 (pci_bus_t *pci, unsigned dev, unsigned long addr, unsigned char val) 305{ 306 pci_dev_t *pdev = pci->dev[dev & 0x1f]; 307 308 if ((pdev != NULL) && (pdev->set_cfg8 != NULL)) { 309 pdev->set_cfg8 (pdev->cfg_ext, addr, val); 310 } 311} 312 313void pci_set_cfg16 (pci_bus_t *pci, unsigned dev, unsigned long addr, unsigned short val) 314{ 315 pci_dev_t *pdev = pci->dev[dev & 0x1f]; 316 317 if ((pdev != NULL) && (pdev->set_cfg16 != NULL)) { 318 pdev->set_cfg16 (pdev->cfg_ext, addr, val); 319 } 320} 321 322void pci_set_cfg32 (pci_bus_t *pci, unsigned dev, unsigned long addr, unsigned long val) 323{ 324 pci_dev_t *pdev = pci->dev[dev & 0x1f]; 325 326 if ((pdev != NULL) && (pdev->set_cfg32 != NULL)) { 327 pdev->set_cfg32 (pdev->cfg_ext, addr, val); 328 } 329} 330 331unsigned char pci_get_cfg8 (pci_bus_t *pci, unsigned dev, unsigned long addr) 332{ 333 pci_dev_t *pdev = pci->dev[dev & 0x1f]; 334 335 if ((pdev != NULL) && (pdev->get_cfg8 != NULL)) { 336 return (pdev->get_cfg8 (pdev->cfg_ext, addr)); 337 } 338 339 return (0xff); 340} 341 342unsigned short pci_get_cfg16 (pci_bus_t *pci, unsigned dev, unsigned long addr) 343{ 344 pci_dev_t *pdev = pci->dev[dev & 0x1f]; 345 346 if ((pdev != NULL) && (pdev->get_cfg16 != NULL)) { 347 return (pdev->get_cfg16 (pdev->cfg_ext, addr)); 348 } 349 350 return (0xffffU); 351} 352 353unsigned long pci_get_cfg32 (pci_bus_t *pci, unsigned dev, unsigned long addr) 354{ 355 pci_dev_t *pdev = pci->dev[dev & 0x1f]; 356 357 if ((pdev != NULL) && (pdev->get_cfg32 != NULL)) { 358 return (pdev->get_cfg32 (pdev->cfg_ext, addr)); 359 } 360 361 return (0xffffffffUL); 362} 363 364static 365void pci_set_irq (pci_bus_t *pci, unsigned dev, unsigned intr, unsigned char val) 366{ 367 val = (val != 0); 368 369 dev &= 0x1f; 370 intr &= 0x03; 371 372 if (val != pci->irq_val[dev][intr]) { 373 pci->irq_val[dev][intr] = val; 374 375 if (pci->irq[dev][intr] != NULL) { 376 pci->irq[dev][intr] (pci->irq_ext[dev][intr], val); 377 } 378 } 379} 380 381void pci_set_intr (pci_bus_t *pci, unsigned dev, unsigned intr, unsigned char val) 382{ 383 pci_set_irq (pci, dev, intr, val); 384} 385 386void pci_set_inta (pci_bus_t *pci, unsigned dev, unsigned char val) 387{ 388 pci_set_intr (pci, 0, dev, val); 389} 390 391void pci_set_intb (pci_bus_t *pci, unsigned dev, unsigned char val) 392{ 393 pci_set_intr (pci, 1, dev, val); 394} 395 396void pci_set_intc (pci_bus_t *pci, unsigned dev, unsigned char val) 397{ 398 pci_set_intr (pci, 2, dev, val); 399} 400 401void pci_set_intd (pci_bus_t *pci, unsigned dev, unsigned char val) 402{ 403 pci_set_intr (pci, 3, dev, val); 404} 405 406 407unsigned long pci_get_config_addr (pci_bus_t *pci) 408{ 409 return (pci->cfgaddr); 410} 411 412unsigned char pci_get_config_data8 (pci_bus_t *pci, unsigned addr) 413{ 414 unsigned dev; 415 pci_dev_t *pdev; 416 417 addr &= 0x03; 418 419 dev = (pci->cfgaddr >> 11) & 0x1f; 420 pdev = pci->dev[dev]; 421 422 if ((pdev != NULL) && (pdev->get_cfg8 != NULL)) { 423 return (pdev->get_cfg8 (pdev->cfg_ext, (pci->cfgaddr & 0x03fcU) + addr)); 424 } 425 426 return (0); 427} 428 429unsigned short pci_get_config_data16 (pci_bus_t *pci, unsigned addr) 430{ 431 unsigned dev; 432 pci_dev_t *pdev; 433 434 addr &= 0x03; 435 436 dev = (pci->cfgaddr >> 11) & 0x1f; 437 pdev = pci->dev[dev]; 438 439 if ((pdev != NULL) && (pdev->get_cfg16 != NULL)) { 440 return (pdev->get_cfg16 (pdev->cfg_ext, (pci->cfgaddr & 0x03fcU) + addr)); 441 } 442 443 return (0); 444} 445 446unsigned long pci_get_config_data32 (pci_bus_t *pci) 447{ 448 unsigned dev; 449 pci_dev_t *pdev; 450 451 dev = (pci->cfgaddr >> 11) & 0x1f; 452 pdev = pci->dev[dev]; 453 454 if ((pdev != NULL) && (pdev->get_cfg32 != NULL)) { 455 return (pdev->get_cfg32 (pdev->cfg_ext, pci->cfgaddr & 0x03fcU)); 456 } 457 458 return (0); 459} 460 461void pci_set_config_addr (pci_bus_t *pci, unsigned long val) 462{ 463 pci->cfgaddr = val; 464} 465 466void pci_set_config_data8 (pci_bus_t *pci, unsigned addr, unsigned char val) 467{ 468 unsigned dev; 469 pci_dev_t *pdev; 470 471 addr &= 0x03; 472 473 dev = (pci->cfgaddr >> 11) & 0x1f; 474 pdev = pci->dev[dev]; 475 476 if ((pdev != NULL) && (pdev->set_cfg8 != NULL)) { 477 pdev->set_cfg8 (pdev->cfg_ext, (pci->cfgaddr & 0x03fcU) + addr, val); 478 } 479} 480 481void pci_set_config_data16 (pci_bus_t *pci, unsigned addr, unsigned short val) 482{ 483 unsigned dev; 484 pci_dev_t *pdev; 485 486 addr &= 0x03; 487 488 dev = (pci->cfgaddr >> 11) & 0x1f; 489 pdev = pci->dev[dev]; 490 491 if ((pdev != NULL) && (pdev->set_cfg16 != NULL)) { 492 pdev->set_cfg16 (pdev->cfg_ext, (pci->cfgaddr & 0x03fcU) + addr, val); 493 } 494} 495 496void pci_set_config_data32 (pci_bus_t *pci, unsigned long val) 497{ 498 unsigned dev; 499 pci_dev_t *pdev; 500 501 dev = (pci->cfgaddr >> 11) & 0x1f; 502 pdev = pci->dev[dev]; 503 504 if ((pdev != NULL) && (pdev->set_cfg32 != NULL)) { 505 pdev->set_cfg32 (pdev->cfg_ext, pci->cfgaddr & 0x03fcU, val); 506 } 507}