1/* 2 * Copyright 2007, François Revol <revol@free.fr>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6#include "pci_atari.h" 7 8#include <stdlib.h> 9#include <string.h> 10 11#include <KernelExport.h> 12#include <PCI.h> 13 14#include "pci_controller.h" 15 16/* 17 * Here we fake a PCI bus that maps the physical memory 18 * (which is also I/O on 68k), and fake some system devices. 19 * Some other devices are faked as ISA because they need DMA 20 * notification. 21 * 22 * TODO: anything to be done to support VME cards ? 23 * I don't think they are PnP at all anyway. 24 * 25 * TODO: On Hades/Milan clones a real PCI bus is accessible 26 * through PAE-like extra bits in page descriptors. This one 27 * should be handled in a separate file. 28 */ 29 30//XXX:find one and put in shared priv header! 31// 0x68xx is free according to pci.ids 32// 68fx (f=fake) x = 0:amiga, 1:apple, 2:atari 33#define FAKEV 0x68f2 34 35// bus number 36#define BN 0 37 38// default line size 39#define DLL 1 40// default latency 41#define DL 0 42// default bist 43#define DB 0 44 45#define PEI 0 46 47#define INVV 0xffff //0x0000 ?? 48#define INVD 0xffff 49 50struct fake_pci_device { 51 pci_info info; 52 53}; 54 55static struct fake_pci_device gFakePCIDevices[] = { 56{ {FAKEV, 0x0000, BN, 0, 0, 0, 0xff, PCI_host, PCI_bridge, DLL, DL, DB, 0, PEI }}, /* cpu */ 57{ {FAKEV, 0x0001, BN, 1, 0, 0, 0xff, 0x68/*fake*/, PCI_processor, DLL, DL, DB, 0, PEI }}, /* cpu */ 58{ {FAKEV, 0x0002, BN, 2, 0, 0, 0xff, PCI_display_other, PCI_display, DLL, DL, DB, 0, 0xFFFF8200, PEI }}, /* gfx */ 59{ {FAKEV, 0x0003, BN, 3, 0, 0, 0xff, PCI_ide, PCI_mass_storage, DLL, DL, DB, 0, 0xFFF00000, PEI }}, /* ide */ 60{ {FAKEV, 0x0004, BN, 4, 0, 0, 0xff, PCI_scsi, PCI_mass_storage, DLL, DL, DB, 0, PEI }}, /* scsi */ 61{ {FAKEV, 0x0005, BN, 5, 0, 0, 0xff, 0x0/*CHANGEME*/, PCI_multimedia, DLL, DL, DB, 0x00, 0, 0xFFFF8900, PEI }}, /* snd */ 62//UART ? 63//centronics? 64{ {INVV, INVD} } 65}; 66#define FAKE_DEVICES_COUNT (sizeof(gFakePCIDevices)/sizeof(struct fake_pci_device)-1) 67 68struct m68k_atari_fake_host_bridge { 69 uint32 bus; 70}; 71 72 73#define out8rb(address, value) m68k_out8((vuint8*)(address), value) 74#define out16rb(address, value) m68k_out16_reverse((vuint16*)(address), value) 75#define out32rb(address, value) m68k_out32_reverse((vuint32*)(address), value) 76#define in8rb(address) m68k_in8((const vuint8*)(address)) 77#define in16rb(address) m68k_in16_reverse((const vuint16*)(address)) 78#define in32rb(address) m68k_in32_reverse((const vuint32*)(address)) 79 80 81static int m68k_atari_enable_config(struct m68k_atari_fake_host_bridge *bridge, 82 uint8 bus, uint8 slot, uint8 function, uint8 offset); 83 84static status_t m68k_atari_read_pci_config(void *cookie, uint8 bus, uint8 device, 85 uint8 function, uint8 offset, uint8 size, uint32 *value); 86static status_t m68k_atari_write_pci_config(void *cookie, uint8 bus, 87 uint8 device, uint8 function, uint8 offset, uint8 size, 88 uint32 value); 89static status_t m68k_atari_get_max_bus_devices(void *cookie, int32 *count); 90static status_t m68k_atari_read_pci_irq(void *cookie, uint8 bus, uint8 device, 91 uint8 function, uint8 pin, uint8 *irq); 92static status_t m68k_atari_write_pci_irq(void *cookie, uint8 bus, uint8 device, 93 uint8 function, uint8 pin, uint8 irq); 94 95static pci_controller sM68kAtariPCIController = { 96 m68k_atari_read_pci_config, 97 m68k_atari_write_pci_config, 98 m68k_atari_get_max_bus_devices, 99 m68k_atari_read_pci_irq, 100 m68k_atari_write_pci_irq, 101}; 102 103 104static status_t 105m68k_atari_read_pci_config(void *cookie, uint8 bus, uint8 device, uint8 function, 106 uint8 offset, uint8 size, uint32 *value) 107{ 108 struct fake_pci_device *devices = (struct fake_pci_device *)cookie; 109 struct fake_pci_device *dev; 110 111 if (bus != 0) 112 return EINVAL; 113 if (device >= FAKE_DEVICES_COUNT) 114 return EINVAL; 115 if (function != 0) 116 return EINVAL; 117 dev = &devices[device]; 118 119#define O(pn,n,s) \ 120 case pn: \ 121 if (size != s) { \ 122 panic("invalid pci config size %d for offset %d", size, offset); \ 123 return EINVAL; \ 124 } \ 125 *value = dev->info.n; \ 126 return B_OK 127 128 if (1) { 129 switch (offset) { 130 O(PCI_vendor_id, vendor_id, 2); 131 O(PCI_device_id, device_id, 2); 132 O(PCI_revision, revision, 1); 133 O(PCI_class_api, class_api, 1); 134 O(PCI_class_sub, class_sub, 1); 135 O(PCI_class_base, class_base, 1); 136 O(PCI_line_size, line_size, 1); 137 O(PCI_latency, latency, 1); 138 O(PCI_header_type, header_type, 1); 139 O(PCI_bist, bist, 1); 140 } 141 } 142//#undef O 143#if 0 144#define PCI_command 0x04 /* (2 byte) command */ 145#define PCI_status 0x06 /* (2 byte) status */ 146#endif 147 148 if (dev->info.header_type == 0x00 || dev->info.header_type == 0x01) { 149 switch (offset) { 150 case PCI_base_registers: 151 return EINVAL; 152 O(PCI_interrupt_line, u.h0.interrupt_line, 1); 153 O(PCI_interrupt_pin, u.h0.interrupt_pin, 1); 154 default: 155 break; 156 } 157 } 158 159 if (dev->info.header_type == 0x00) { 160 switch (offset) { 161 default: 162 break; 163 } 164 } 165 166 if (dev->info.header_type == 0x01) { 167 switch (offset) { 168 O(PCI_primary_bus, u.h1.primary_bus, 1); 169 O(PCI_secondary_bus, u.h1.secondary_bus, 1); 170 O(PCI_subordinate_bus, u.h1.subordinate_bus, 1); 171 O(PCI_secondary_latency, u.h1.secondary_latency, 1); 172 default: 173 break; 174 } 175 } 176 177 *value = 0xffffffff; 178 panic("invalid pci config offset %d", offset); 179 return EINVAL; 180 //return B_OK; 181} 182 183 184static status_t 185m68k_atari_write_pci_config(void *cookie, uint8 bus, uint8 device, 186 uint8 function, uint8 offset, uint8 size, uint32 value) 187{ 188#if 0 189 if (m68k_atari_enable_config(bridge, bus, device, function, offset)) { 190 switch (size) { 191 case 1: 192 out8rb(caoff, (uint8)value); 193 (void)in8rb(caoff); 194 break; 195 case 2: 196 out16rb(caoff, (uint16)value); 197 (void)in16rb(caoff); 198 break; 199 case 4: 200 out32rb(caoff, value); 201 (void)in32rb(caoff); 202 break; 203 } 204 } 205 206#endif 207 panic("write pci config dev %d offset %d", device, offset); 208 return B_ERROR; 209 return B_OK; 210} 211 212 213static status_t 214m68k_atari_get_max_bus_devices(void *cookie, int32 *count) 215{ 216 *count = 32; 217 return B_OK; 218} 219 220 221static status_t 222m68k_atari_read_pci_irq(void *cookie, uint8 bus, uint8 device, 223 uint8 function, uint8 pin, uint8 *irq) 224{ 225#warning M68K: WRITEME 226 return B_ERROR; 227} 228 229 230static status_t 231m68k_atari_write_pci_irq(void *cookie, uint8 bus, uint8 device, 232 uint8 function, uint8 pin, uint8 irq) 233{ 234#warning M68K: WRITEME 235 return B_ERROR; 236} 237 238 239// #pragma mark - 240 241 242static int 243m68k_atari_enable_config(struct m68k_atari_fake_host_bridge *bridge, uint8 bus, 244 uint8 slot, uint8 function, uint8 offset) 245{ 246#warning M68K: WRITEME 247 return 0; 248} 249 250 251// #pragma mark - 252 253 254 255 256status_t 257m68k_atari_pci_controller_init(void) 258{ 259 struct m68k_atari_fake_host_bridge *bridge; 260 bridge = (struct m68k_atari_fake_host_bridge *) 261 malloc(sizeof(struct m68k_atari_fake_host_bridge)); 262 if (!bridge) 263 return B_NO_MEMORY; 264 265 bridge->bus = 0; 266 267 status_t error = pci_controller_add(&sM68kAtariPCIController, bridge); 268 269 if (error != B_OK) 270 free(bridge); 271 272 // TODO: probe Hades & Milan bridges 273 return error; 274} 275 276 277// #pragma mark - support functions 278 279 280