[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: USB mouse



> >XFree86 4.01 debs won't be out for a while, and they probably won't
> >include the experimental PPC stuff. No idea on the Pismo, but the Lombard

[The Pismo doesn't have the braindead OF overlap mapping, so no problem
there ...]
 
> If someone wants to make XF4.0.1 debs for PPC, I beleive they should be
> done from Franz Sirl source base (devel.linuxppc.org/users/fsirl/xf4/
> SRPMS). This archive contains the latest fixes, patches, etc... for PPC

The latest changes from Ani Joshi's rsync server? That would save me
cleaning up my mess of 16 bit Mach64 hacks ...

> BTW Michael, can you send me the PCI patch ?

Attached. The first part is experimental code to make atyfb handle 16 bit
565 color which needs a bit more work, including bastardizing a reserved
field in the fb var struct to pass the actual depth as opposed to bpp. The
way it's #if'ed out it shouldn't hurt, it was just too much of a hassle to
take out again.

The other stuff (patch to atyfb_of_init) is the PCI overlap related one,
I've changed it to either remap the MMIO region into the LE aperture, or
right past the BE framebuffer aperture depending on whether there's enough
space. I'm sure it can be done in less than 100 lines of code and it's too
verbose for release purpose but it happens to work (please note that
mapping MMIO right adjacent to the IO aperture, i.e. 0x80882000, would
cause a hard crash. Apparently ATY decodes MMIO at both 0x81fff000 and
0x80fff000 regardless of what the PCI bridge is configured to, and setting
up a PCI mapping at 0x80882000 leaves both MMIO apertures unmapped. Was
that what PCI resource mapping was about, a new and improved way to shoot
yourself in the foot??)

	Michael
--- drivers/video/atyfb.c.org	Mon Apr  3 20:20:24 2000
+++ drivers/video/atyfb.c	Thu Jul 27 21:25:42 2000
@@ -1061,6 +1061,7 @@
     u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
     u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
     u32 pix_width, dp_pix_width, dp_chain_mask;
+    u32 depth;
 
     /* input */
     xres = var->xres;
@@ -1070,6 +1071,7 @@
     xoffset = var->xoffset;
     yoffset = var->yoffset;
     bpp = var->bits_per_pixel;
+    depth = var->red.length + var->green.length + var->blue.length + var->transp.length;
     left = var->left_margin;
     right = var->right_margin;
     upper = var->upper_margin;
@@ -1118,6 +1120,9 @@
 
     c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
 
+    if (depth > bpp+1)
+        depth = bpp;
+
     if (bpp <= 8) {
 	bpp = 8;
 	pix_width = CRTC_PIX_WIDTH_8BPP;
@@ -1125,10 +1130,24 @@
 	dp_chain_mask = 0x8080;
     } else if (bpp <= 16) {
 	bpp = 16;
+#if 1
 	pix_width = CRTC_PIX_WIDTH_15BPP;
 	dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
 		       BYTE_ORDER_LSB_TO_MSB;
 	dp_chain_mask = 0x4210;
+#else
+	if (depth == 15) {
+	    pix_width = CRTC_PIX_WIDTH_15BPP;
+	    dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
+		           BYTE_ORDER_LSB_TO_MSB;
+	    dp_chain_mask = 0x4210;
+	} else {
+	    pix_width = CRTC_PIX_WIDTH_16BPP;
+	    dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |
+		           BYTE_ORDER_LSB_TO_MSB;
+	    dp_chain_mask = 0x8410;
+	}
+#endif
     } else if ((bpp <= 24) && (Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
 	bpp = 24;
 	pix_width = CRTC_PIX_WIDTH_24BPP;
@@ -1285,7 +1304,7 @@
 	    var->transp.offset = 0;
 	    var->transp.length = 0;
 	    break;
-#if 0
+#if 1
 	case CRTC_PIX_WIDTH_16BPP:	/* RGB 565 */
 	    bpp = 16;
 	    var->red.offset = 11;
@@ -3176,7 +3195,7 @@
     u8 bus, devfn;
     u16 cmd;
     struct fb_info_aty *info;
-    int i;
+    int i, i_frame, i_regs, i_io, naddr;
 
     if (device_is_compatible(dp, "ATY,264LTPro")) {
 	/* XXX kludge for now */
@@ -3204,6 +3223,13 @@
 	    return;
     }
 
+    printk("atyfb: of_init got %d OF adresses for ATY:\n", dp->n_addrs);
+    for (i = 0; i < dp->n_addrs; i++)
+	printk(" %08x-%08x", dp->addrs[i].address,
+	       dp->addrs[i].address+dp->addrs[i].size-1);
+    if (dp->n_addrs)
+	printk("\n");
+
     info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
     if (!info) {
 	printk("atyfb_of_init: can't alloc fb_info_aty\n");
@@ -3215,6 +3241,8 @@
     info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys,
 						   0x1000);
 
+    printk("atyfb: regbase phys 0x%lx virt 0x%lx\n", info->ati_regbase_phys, info->ati_regbase);
+
     if(! info->ati_regbase) {
 	    printk("atyfb_init: ioremap() returned NULL\n");
 	    kfree(info);
@@ -3226,6 +3254,53 @@
 
     /* enable memory-space accesses using config-space command register */
     if (pci_device_loc(dp, &bus, &devfn) == 0) {
+
+	for (i = 0; i < dp->n_addrs + 2; i++) {
+	    int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
+	    unsigned long base;
+	    u32 size, pbase;
+
+	    base = dp->addrs[i].address;
+
+	    pcibios_read_config_dword(bus, devfn, breg, &pbase);
+	    pcibios_write_config_dword(bus, devfn, breg, 0xffffffff);
+	    pcibios_read_config_dword(bus, devfn, breg, &size);
+	    pcibios_write_config_dword(bus, devfn, breg, pbase);
+
+	    io = (pbase & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO;
+
+	    if (io) {
+		size &= ~1;
+		i_io = i;
+	    }
+
+	    size = ~(size) + 1;
+	    
+	    if (size == 0) 
+	    	break;
+
+	    printk("atyfb: chunk %d ofbase 0x%lx breg %d io %d pbase 0x%lx size 0x%lx \n",
+		i, base, breg, io, pbase, size);
+
+	    if (!base) {
+		printk("atyfb: chunk %d assigning ofbase 0x%lx \n", i, pbase);
+		dp->addrs[i].address = pbase;
+		dp->addrs[i].size = size;
+	    }
+	    if (pbase == addr) {
+		printk("atyfb: chunk %d assigned as VRAM aperture! \n", i);
+		i_frame = i;
+	    }
+	    if (size == 0x1000) {
+		printk("atyfb: chunk %d assigned as MMIO aperture! \n", i);
+		i_regs = i;
+	    }
+
+	}
+
+	naddr = i;
+	printk("atyfb: found %d PCI addresses total. \n", i);
+
 	pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
 	if (cmd != 0xffff) {
 	    cmd |= PCI_COMMAND_MEMORY;
@@ -3242,12 +3317,88 @@
     info->frame_buffer_phys = addr;
     info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
 
+    printk("atyfb: framebuffer phys 0x%lx virt 0x%lx\n", info->frame_buffer_phys, info->frame_buffer);
+
     if(! info->frame_buffer) {
 	    printk("atyfb_init: ioremap() returned NULL\n");
 	    kfree(info);
 	    return;
     }
 
+    /* 
+     * Fix MMIO mapping if MMIO and VRAM overlap 
+     * Note that we can't move the VRAM base address to the BE aperture (this would move the whole
+     * VRAM region, not resize it) so it's easier to remap MMIO someplace else.
+     */
+    if ( (dp->addrs[i_frame].address < dp->addrs[i_regs].address+dp->addrs[i_regs].size 
+	 && dp->addrs[i_frame].address+dp->addrs[i_frame].size >= dp->addrs[i_regs].address)
+    	 || (dp->addrs[i_regs].address < dp->addrs[i_frame].address+dp->addrs[i_frame].size
+    	    && dp->addrs[i_regs].address+dp->addrs[i_regs].size >= dp->addrs[i_frame].address) ) {
+
+	    struct pci_dev *pdev = pci_find_slot(bus, devfn);
+	    int io, breg = PCI_BASE_ADDRESS_0 + (i_regs << 2);
+	    int flags;
+	    unsigned long base;
+	    u32 size, pbase, new;
+
+	    base = dp->addrs[i_regs].address;
+
+	    pcibios_read_config_dword(bus, devfn, breg, &pbase);
+	    pcibios_write_config_dword(bus, devfn, breg, 0xffffffff);
+	    pcibios_read_config_dword(bus, devfn, breg, &size);
+	    pcibios_write_config_dword(bus, devfn, breg, pbase);
+
+	    io = (pbase & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO;
+	    flags = (pbase & PCI_BASE_ADDRESS_MEM_MASK);
+
+	    if (io)
+		size &= ~1;
+	    size = ~(size) + 1;
+	    
+	    printk("atyfb: chunk %d ofbase 0x%lx breg %d io %d pbase 0x%lx size 0x%lx needs reassigning! \n",
+		i_regs, base, breg, io, pbase, size);
+
+#if 0
+	    /* move MMIO past frame buffer for now. Need to walk PCI resources to find safe place */
+	    new = (dp->addrs[i_frame].address+dp->addrs[i_frame].size) | (flags & 0x0f);
+#else
+	    /* move MMIO before frame buffer and past I/O for now. Need to walk PCI resources to find safe place */
+	    if (dp->addrs[i_io].address+dp->addrs[i_io].size+dp->addrs[i_regs].size < dp->addrs[i_frame].address)
+	    	new = (dp->addrs[i_io].address&0xff000000) | (dp->addrs[i_regs].address&0x00ffffff) | (flags & 0x0f);
+	    else
+		new = (dp->addrs[i_frame].address+dp->addrs[i_frame].size) | (flags & 0x0f);
+#endif
+
+	    pcibios_write_config_dword(bus, devfn, breg, new);
+
+	    pcibios_read_config_dword(bus, devfn, breg, &pbase);
+	    pcibios_write_config_dword(bus, devfn, breg, 0xffffffff);
+	    pcibios_read_config_dword(bus, devfn, breg, &size);
+	    pcibios_write_config_dword(bus, devfn, breg, pbase);
+
+	    if (new != pbase) 
+	    	printk("atyfb: failed to remap MMIO region! \n");
+
+	    /* update PCI struct */
+	    if (!pdev) 
+	    	printk("atyfb: no pci_dev registered for device!\n");
+	    else
+	    	pdev->base_address[i_regs] = pbase;
+
+	    io = (pbase & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO;
+	    flags = (pbase & ~PCI_BASE_ADDRESS_MEM_MASK);
+
+	    if (io)
+		size &= ~1;
+	    size = ~(size) + 1;
+	    
+	    printk("atyfb: chunk %d ofbase 0x%lx breg %d io %d reassigned to pbase 0x%lx size 0x%lx ! \n",
+		i_regs, base, breg, io, pbase, size);
+
+	    /* update OF device tree */
+	    dp->addrs[i_regs].address = dp->addrs[i_frame].address+dp->addrs[i_frame].size;
+    }
+
     if (!aty_init(info, dp->full_name)) {
 	kfree(info);
 	return;

Reply to: