#include "types.h" #include "link.h" #include #include #include #include "pci.h" #include "agp.h" #include "syscall.h" agp_t *bridge; int __stdcall srv_agp(ioctl_t *io); u32_t __stdcall drvEntry(int action) { u32_t retval; int i; if(action != 1) return 0; if(!dbg_open("/sys/drivers/agp.log")) { printf("Can't open /sys/drivers/agp.log\nExit\n"); return 0; } if( FindPciDevice() == 0) { dbgprintf("Device not found\n"); return 0; }; return 0; // retval = RegService("AGP", srv_2d); // dbgprintf("reg service %s as: %x\n", "HDRAW", retval); // return retval; }; #include "pci.inc" #include "isoch.inc" static void intel_8xx_tlbflush(void *mem) { u32_t temp; temp = pciReadLong(bridge->PciTag, INTEL_AGPCTRL); pciWriteLong(bridge->PciTag, INTEL_AGPCTRL, temp & ~(1 << 7)); temp = pciReadLong(bridge->PciTag, INTEL_AGPCTRL); pciWriteLong(bridge->PciTag, INTEL_AGPCTRL, temp | (1 << 7)); } static aper_size_t intel_8xx_sizes[7] = { { 256, 65536, 64, 0 }, { 128, 32768, 32, 32 }, { 64, 16384, 16, 48 }, { 32, 8192, 8, 56 }, { 16, 4096, 4, 60 }, { 8, 2048, 2, 62 }, { 4, 1024, 1, 63 } }; static int intel_845_configure() { u32_t temp; u8_t temp2; aper_size_t *current_size; current_size = bridge->current_size; /* aperture size */ pciWriteByte(bridge->PciTag, INTEL_APSIZE, current_size->size_value); dbgprintf("INTEL_APSIZE %d\n", current_size->size_value ); if (bridge->apbase_config != 0) { pciWriteLong(bridge->PciTag, AGP_APBASE, bridge->apbase_config); } else { /* address to map to */ temp = pciReadLong(bridge->PciTag, AGP_APBASE); bridge->gart_addr = (temp & PCI_MAP_MEMORY_ADDRESS_MASK); bridge->apbase_config = temp; } dbgprintf("AGP_APBASE %x\n", temp ); /* attbase - aperture base */ pciWriteLong(bridge->PciTag, INTEL_ATTBASE, bridge->gatt_dma); /* agpctrl */ pciWriteLong(bridge->PciTag, INTEL_AGPCTRL, 0x0000); /* agpm */ temp2 = pciReadByte(bridge->PciTag, INTEL_I845_AGPM); pciWriteByte(bridge->PciTag, INTEL_I845_AGPM, temp2 | (1 << 1)); /* clear any possible error conditions */ pciWriteWord(bridge->PciTag, INTEL_I845_ERRSTS, 0x001c); return 0; } int agp_generic_create_gatt_table() { count_t pages; pages = bridge->current_size->pages_count; if( bridge->gatt_dma = AllocPages(pages)) { if(bridge->gatt_table = (u32_t*)MapIoMem((void*)bridge->gatt_dma, pages<<12, PG_SW+PG_NOCACHE)) { dbgprintf("gatt map %x at %x %d pages\n",bridge->gatt_dma , bridge->gatt_table, pages); /* AK: bogus, should encode addresses > 4GB */ u32_t volatile *table = bridge->gatt_table; count_t count = bridge->current_size->num_entries; while(count--) { /* FIXME memset */ addr_t tmp; *table = 0; table++; } return 1; }; }; dbgprintf("unable to get memory for " "graphics translation table.\n"); return 0; } static int __intel_8xx_fetch_size(u8_t temp) { int i; aper_size_t *values; values = bridge->aperture_sizes; values = intel_8xx_sizes; for (i = 0; i < 7; i++) { if (temp == values[i].size_value) { bridge->previous_size = bridge->current_size = (void *) (values + i); bridge->aperture_size_idx = i; return values[i].size; } } return 0; } static int intel_8xx_fetch_size(void) { u8_t temp; temp = pciReadByte(bridge->PciTag, INTEL_APSIZE); return __intel_8xx_fetch_size(temp); } int agp_bind_memory(addr_t agp_addr, addr_t dma_addr, size_t size) { int ret_val; count_t count; // if (curr == NULL) // return -EINVAL; // if (curr->is_bound == TRUE) { // printk(KERN_INFO PFX "memory %p is already bound!\n", curr); // return -EINVAL; // } // if (curr->is_flushed == FALSE) { // curr->bridge->driver->cache_flush(); // curr->is_flushed = TRUE; // } // ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type); u32_t volatile *table = &bridge->gatt_table[agp_addr>>12]; count = size >> 12; dma_addr |= 0x00000017; while(count--) { *table = dma_addr; table++; dma_addr+=4096; } bridge->tlb_flush(NULL); // if (ret_val != 0) // return ret_val; // curr->is_bound = TRUE; // curr->pg_start = pg_start; return 0; } void get_agp_version(agp_t *bridge) { u32_t ncapid; /* Exit early if already set by errata workarounds. */ if (bridge->major_version != 0) return; ncapid = pciReadLong(bridge->PciTag, bridge->capndx); bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf; } static void agp_v2_parse_one(u32_t *requested_mode, u32_t *bridge_agpstat, u32_t *vga_agpstat) { u32_t tmp; if (*requested_mode & AGP2_RESERVED_MASK) { dbgprintf("reserved bits set (%x) in mode 0x%x. Fixed.\n", *requested_mode & AGP2_RESERVED_MASK, *requested_mode); *requested_mode &= ~AGP2_RESERVED_MASK; } /* Check the speed bits make sense. Only one should be set. */ tmp = *requested_mode & 7; switch (tmp) { case 0: dbgprintf("Setting to x1 mode.\n"); *requested_mode |= AGPSTAT2_1X; break; case 1: case 2: break; case 3: *requested_mode &= ~(AGPSTAT2_1X); /* rate=2 */ break; case 4: break; case 5: case 6: case 7: *requested_mode &= ~(AGPSTAT2_1X|AGPSTAT2_2X); /* rate=4*/ break; } /* disable SBA if it's not supported */ if (!((*bridge_agpstat & AGPSTAT_SBA) && (*vga_agpstat & AGPSTAT_SBA) && (*requested_mode & AGPSTAT_SBA))) *bridge_agpstat &= ~AGPSTAT_SBA; /* Set rate */ if (!((*bridge_agpstat & AGPSTAT2_4X) && (*vga_agpstat & AGPSTAT2_4X) && (*requested_mode & AGPSTAT2_4X))) *bridge_agpstat &= ~AGPSTAT2_4X; if (!((*bridge_agpstat & AGPSTAT2_2X) && (*vga_agpstat & AGPSTAT2_2X) && (*requested_mode & AGPSTAT2_2X))) *bridge_agpstat &= ~AGPSTAT2_2X; if (!((*bridge_agpstat & AGPSTAT2_1X) && (*vga_agpstat & AGPSTAT2_1X) && (*requested_mode & AGPSTAT2_1X))) *bridge_agpstat &= ~AGPSTAT2_1X; /* Now we know what mode it should be, clear out the unwanted bits. */ if (*bridge_agpstat & AGPSTAT2_4X) *bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */ if (*bridge_agpstat & AGPSTAT2_2X) *bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */ if (*bridge_agpstat & AGPSTAT2_1X) *bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1X */ /* Apply any errata. */ if (bridge->flags & AGP_ERRATA_FASTWRITES) *bridge_agpstat &= ~AGPSTAT_FW; if (bridge->flags & AGP_ERRATA_SBA) *bridge_agpstat &= ~AGPSTAT_SBA; if (bridge->flags & AGP_ERRATA_1X) { *bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X); *bridge_agpstat |= AGPSTAT2_1X; } /* If we've dropped down to 1X, disable fast writes. */ if (*bridge_agpstat & AGPSTAT2_1X) *bridge_agpstat &= ~AGPSTAT_FW; } static void agp_v3_parse_one(u32_t *requested_mode, u32_t *bridge_agpstat, u32_t *vga_agpstat) { u32_t origbridge = *bridge_agpstat, origvga = *vga_agpstat; u32_t tmp; if (*requested_mode & AGP3_RESERVED_MASK) { dbgprintf("reserved bits set (%x) in mode 0x%x. Fixed.\n", *requested_mode & AGP3_RESERVED_MASK, *requested_mode); *requested_mode &= ~AGP3_RESERVED_MASK; } /* Check the speed bits make sense. */ tmp = *requested_mode & 7; if (tmp == 0) { dbgprintf("Setting to AGP3 x4 mode.\n"); *requested_mode |= AGPSTAT3_4X; } if (tmp >= 3) { dbgprintf("Setting to AGP3 x8 mode.\n"); *requested_mode = (*requested_mode & ~7) | AGPSTAT3_8X; } /* ARQSZ - Set the value to the maximum one. * Don't allow the mode register to override values. */ *bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_ARQSZ) | max_t(u32_t,(*bridge_agpstat & AGPSTAT_ARQSZ),(*vga_agpstat & AGPSTAT_ARQSZ))); /* Calibration cycle. * Don't allow the mode register to override values. */ *bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_CAL_MASK) | min_t(u32_t,(*bridge_agpstat & AGPSTAT_CAL_MASK),(*vga_agpstat & AGPSTAT_CAL_MASK))); /* SBA *must* be supported for AGP v3 */ *bridge_agpstat |= AGPSTAT_SBA; /* * Set speed. * Check for invalid speeds. This can happen when applications * written before the AGP 3.0 standard pass AGP2.x modes to AGP3 hardware */ if (*requested_mode & AGPSTAT_MODE_3_0) { /* * Caller hasn't a clue what it is doing. Bridge is in 3.0 mode, * have been passed a 3.0 mode, but with 2.x speed bits set. * AGP2.x 4x -> AGP3.0 4x. */ if (*requested_mode & AGPSTAT2_4X) { dbgprintf("broken AGP3 flags (%x). Fixed.\n", *requested_mode); *requested_mode &= ~AGPSTAT2_4X; *requested_mode |= AGPSTAT3_4X; } } else { /* * The caller doesn't know what they are doing. We are in 3.0 mode, * but have been passed an AGP 2.x mode. * Convert AGP 1x,2x,4x -> AGP 3.0 4x. */ dbgprintf("broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",*requested_mode); *requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X); *requested_mode |= AGPSTAT3_4X; } if (*requested_mode & AGPSTAT3_8X) { if (!(*bridge_agpstat & AGPSTAT3_8X)) { *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); *bridge_agpstat |= AGPSTAT3_4X; dbgprintf("requested AGPx8 but bridge not capable.\n"); return; } if (!(*vga_agpstat & AGPSTAT3_8X)) { *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); *bridge_agpstat |= AGPSTAT3_4X; dbgprintf("requested AGPx8 but graphic card not capable.\n"); return; } /* All set, bridge & device can do AGP x8*/ *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); goto done; } else { /* * If we didn't specify AGPx8, we can only do x4. * If the hardware can't do x4, we're up shit creek, and never * should have got this far. */ *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X)) *bridge_agpstat |= AGPSTAT3_4X; else { dbgprintf("Badness. Don't know which AGP mode to set. " "[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n", origbridge, origvga, *bridge_agpstat, *vga_agpstat); if (!(*bridge_agpstat & AGPSTAT3_4X)) dbgprintf("Bridge couldn't do AGP x4.\n"); if (!(*vga_agpstat & AGPSTAT3_4X)) dbgprintf("Graphic card couldn't do AGP x4.\n"); return; } } done: /* Apply any errata. */ if (bridge->flags & AGP_ERRATA_FASTWRITES) *bridge_agpstat &= ~AGPSTAT_FW; if (bridge->flags & AGP_ERRATA_SBA) *bridge_agpstat &= ~AGPSTAT_SBA; if (bridge->flags & AGP_ERRATA_1X) { *bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X); *bridge_agpstat |= AGPSTAT2_1X; } } u32_t agp_collect_device_status(agp_t *bridge, u32_t requested_mode, u32_t bridge_agpstat) { PCITAG vgaTag; u32_t vga_agpstat; int cap_ptr; for (;;) { vgaTag = pci_find_class(PCI_CLASS_DISPLAY_VGA); if (vgaTag == -1) { dbgprintf("Couldn't find an AGP VGA controller.\n"); return 0; } cap_ptr = pci_find_capability(vgaTag, PCI_CAP_ID_AGP); if (cap_ptr) break; } /* * Ok, here we have a AGP device. Disable impossible * settings, and adjust the readqueue to the minimum. */ vga_agpstat = pciReadLong(vgaTag, cap_ptr+PCI_AGP_STATUS); /* adjust RQ depth */ bridge_agpstat = ((bridge_agpstat & ~AGPSTAT_RQ_DEPTH) | min_t(u32_t, (requested_mode & AGPSTAT_RQ_DEPTH), min_t(u32_t, (bridge_agpstat & AGPSTAT_RQ_DEPTH), (vga_agpstat & AGPSTAT_RQ_DEPTH)))); /* disable FW if it's not supported */ if (!((bridge_agpstat & AGPSTAT_FW) && (vga_agpstat & AGPSTAT_FW) && (requested_mode & AGPSTAT_FW))) bridge_agpstat &= ~AGPSTAT_FW; /* Check to see if we are operating in 3.0 mode */ if (bridge->mode & AGPSTAT_MODE_3_0) agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); else agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); return bridge_agpstat; } void agp_device_command(u32_t bridge_agpstat, int agp_v3) { PCITAG device = 0; int mode; mode = bridge_agpstat & 0x7; if (agp_v3) mode *= 4; for_each_pci_dev(device) { int agp = pci_find_capability(device, PCI_CAP_ID_AGP); if (!agp) continue; dbgprintf("Putting AGP V%d device at into %dx mode\n", agp_v3 ? 3 : 2, mode); pciWriteLong(device, agp + PCI_AGP_COMMAND, bridge_agpstat); } } void agp_generic_enable(u32_t requested_mode) { u32_t bridge_agpstat, temp; get_agp_version(bridge); dbgprintf("Found an AGP %d.%d compliant device.\n", bridge->major_version, bridge->minor_version); bridge_agpstat = pciReadLong(bridge->PciTag, bridge->capndx + PCI_AGP_STATUS); bridge_agpstat = agp_collect_device_status(bridge, requested_mode, bridge_agpstat); if (bridge_agpstat == 0) /* Something bad happened. FIXME: Return error code? */ return; bridge_agpstat |= AGPSTAT_AGP_ENABLE; /* Do AGP version specific frobbing. */ if (bridge->major_version >= 3) { if (bridge->mode & AGPSTAT_MODE_3_0) { /* If we have 3.5, we can do the isoch stuff. */ if (bridge->minor_version >= 5) agp_3_5_enable(bridge); agp_device_command(bridge_agpstat, TRUE); return; } else { /* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/ bridge_agpstat &= ~(7<<10) ; temp = pciReadLong(bridge->PciTag, bridge->capndx+AGPCTRL); temp |= (1<<9); pciWriteLong(bridge->PciTag, bridge->capndx+AGPCTRL, temp); dbgprintf("Device is in legacy mode," " falling back to 2.x\n"); } } /* AGP v<3 */ agp_device_command(bridge_agpstat, FALSE); } static agp_t intel_845_driver = { .aperture_sizes = intel_8xx_sizes, // .size_type = U8_APER_SIZE, // .num_aperture_sizes = 7, .configure = intel_845_configure, .fetch_size = intel_8xx_fetch_size, // .cleanup = intel_8xx_cleanup, .tlb_flush = intel_8xx_tlbflush, // .mask_memory = agp_generic_mask_memory, // .masks = intel_generic_masks, // .agp_enable = agp_generic_enable, // .cache_flush = global_cache_flush, .create_gatt_table = agp_generic_create_gatt_table, // .free_gatt_table = agp_generic_free_gatt_table, // .insert_memory = agp_generic_insert_memory, // .remove_memory = agp_generic_remove_memory, // .alloc_by_type = agp_generic_alloc_by_type, // .free_by_type = agp_generic_free_by_type, // .agp_alloc_page = agp_generic_alloc_page, // .agp_destroy_page = agp_generic_destroy_page, }; int init_bridge(PCITAG pciTag) { size_t size_value; bridge = &intel_845_driver; bridge->PciTag = pciTag; bridge->capndx = pci_find_capability(pciTag, PCI_CAP_ID_AGP); size_value = bridge->fetch_size(); if (size_value == 0) { dbgprintf("unable to determine aperture size.\n"); return 0; }; dbgprintf("fetch size = %x\n", size_value); if( bridge->create_gatt_table() ) { bridge->configure(); return 1; } return 0; } #include "detect.inc"