patch-2.1.79 linux/drivers/sbus/char/mach64.c
Next file: linux/drivers/sbus/char/mach64.h
Previous file: linux/drivers/sbus/char/flash.c
Back to the patch index
Back to the overall index
- Lines: 206
- Date:
Mon Jan 12 15:15:45 1998
- Orig file:
v2.1.78/linux/drivers/sbus/char/mach64.c
- Orig date:
Thu Sep 4 17:07:31 1997
diff -u --recursive --new-file v2.1.78/linux/drivers/sbus/char/mach64.c linux/drivers/sbus/char/mach64.c
@@ -1,4 +1,4 @@
-/* $Id: mach64.c,v 1.8 1997/08/25 07:50:34 jj Exp $
+/* $Id: mach64.c,v 1.11 1997/10/17 04:13:35 davem Exp $
* mach64.c: Ultra/PCI Mach64 console driver.
*
* Just about all of this is from the PPC/mac driver, see that for
@@ -22,13 +22,18 @@
#include <asm/pbm.h>
#include <asm/fbio.h>
#include <asm/sbus.h>
+#include <asm/pgtable.h>
#include "pcicons.h"
#include "mach64.h"
#include "fb.h"
+static unsigned int mach64_pci_membase;
+static unsigned int mach64_pci_iobase;
+
+#define MACH64_LE_FBOFF 0x000000
#define MACH64_REGOFF 0x7ffc00
-#define MACH64_FBOFF 0x800000
+#define MACH64_BE_FBOFF 0x800000
static inline void mach64_waitq(int entries)
{
@@ -69,7 +74,35 @@
mach64_mmap(struct inode *inode, struct file *file, struct vm_area_struct *vma,
long base, fbinfo_t *fb)
{
- return -ENOSYS;
+ unsigned long addr, size;
+
+ size = vma->vm_end - vma->vm_start;
+ if (vma->vm_offset & ~PAGE_MASK)
+ return -ENXIO;
+
+ if (vma->vm_offset == mach64_pci_iobase) {
+ addr = __pa(pcivga_iobase);
+ size = PAGE_SIZE;
+ } else if (vma->vm_offset >= (mach64_pci_membase + 0x800000)) {
+ addr = __pa(pcivga_membase) - mach64_pci_membase
+ + vma->vm_offset;
+ pgprot_val(vma->vm_page_prot) |= _PAGE_IE;
+ } else if (vma->vm_offset >= mach64_pci_membase) {
+ addr = __pa(pcivga_membase) - mach64_pci_membase
+ + vma->vm_offset;
+ } else {
+ return -EINVAL;
+ }
+
+ pgprot_val(vma->vm_page_prot) &= ~(_PAGE_CACHE);
+ pgprot_val(vma->vm_page_prot) |= _PAGE_E;
+ vma->vm_flags |= (VM_SHM | VM_LOCKED);
+
+ if (remap_page_range(vma->vm_start, addr, size, vma->vm_page_prot))
+ return -EAGAIN;
+
+ vma->vm_dentry = dget(file->f_dentry);
+ return 0;
}
static void
@@ -113,11 +146,29 @@
static struct mach64_info mach64;
+void mach64_test(fbinfo_t *fb)
+{
+ unsigned int x;
+ int i;
+
+ for (i = 0; i < mach64.total_vram; i += 4)
+ writel(i, pcivga_membase + i);
+
+ for (i = 0; i < mach64.total_vram; i += 4)
+ if ((x = readl(pcivga_membase + i)) != i) {
+ printk("vga mem read error @ %08x: exp %x, rd %x\n",
+ i, i, x);
+ i = (i & ~(0xffff)) + 0x10000;
+ }
+}
+
int mach64_init(fbinfo_t *fb)
{
struct pci_dev *pdev;
struct pcidev_cookie *cookie;
+ struct linux_pbm_info *pbm;
unsigned long addr;
+ unsigned int tmp;
memset(&mach64, 0, sizeof(mach64));
for(pdev = pci_devices; pdev; pdev = pdev->next) {
@@ -148,48 +199,85 @@
prom_halt();
}
+ pcibios_read_config_dword(pdev->bus->number, pdev->devfn,
+ PCI_BASE_ADDRESS_0, &mach64_pci_membase);
+ mach64_pci_membase &= PCI_BASE_ADDRESS_MEM_MASK;
+
+ pcibios_read_config_dword(pdev->bus->number, pdev->devfn,
+ PCI_BASE_ADDRESS_1, &mach64_pci_iobase);
+ mach64_pci_iobase &= PCI_BASE_ADDRESS_IO_MASK;
+
printk("mach64_init: IOBASE[%016lx] MEMBASE[%016lx]\n",
pcivga_iobase, pcivga_membase);
- cookie = (struct pcidev_cookie *)pdev->sysdata;
+ cookie = pdev->sysdata;
+ pbm = cookie->pbm;
+
fb->prom_node = cookie->prom_node;
- fb->proc_entry.node = cookie->pbm->prom_node;
+ fb->proc_entry.node = pbm->prom_node;
fb->type.fb_type = FBTYPE_PCI_MACH64;
fb->type.fb_cmsize = 256;
fb->info.private = (void *)&mach64;
- fb->base = pcivga_membase + MACH64_FBOFF;
-
- switch(pcivga_readl(MACH64_REGOFF + MEM_CNTL) & MEM_SIZE_ALIAS) {
- case MEM_SIZE_512K:
- mach64.total_vram = 0x80000;
- break;
- case MEM_SIZE_1M:
- mach64.total_vram = 0x100000;
- break;
- case MEM_SIZE_2M:
- mach64.total_vram = 0x200000;
- break;
- case MEM_SIZE_4M:
- mach64.total_vram = 0x400000;
- break;
- case MEM_SIZE_6M:
- mach64.total_vram = 0x600000;
- break;
- case MEM_SIZE_8M:
- mach64.total_vram = 0x800000;
- break;
- default:
- mach64.total_vram = 0x80000;
- break;
- }
+ fb->base = pcivga_membase + MACH64_BE_FBOFF;
if ((pcivga_readl(MACH64_REGOFF + CONFIG_CHIP_ID)
& CFG_CHIP_TYPE) == MACH64_VT_ID)
mach64.flags |= MACH64_MASK_VT;
+ /*
+ * Fix the PROM's idea of MEM_CNTL settings...
+ */
+ tmp = pcivga_readl(MACH64_REGOFF + MEM_CNTL);
+ switch (tmp & 0xf) {
+ case 3:
+ tmp = (tmp & ~(0xf)) | 2;
+ break;
+ case 7:
+ tmp = (tmp & ~(0xf)) | 3;
+ break;
+ case 9:
+ tmp = (tmp & ~(0xf)) | 4;
+ break;
+ case 11:
+ tmp = (tmp & ~(0xf)) | 5;
+ break;
+ default:
+ break;
+ }
+ tmp &= ~(0x00f00000);
+ pcivga_writel(tmp, MACH64_REGOFF + MEM_CNTL);
+
+ switch(tmp & MEM_SIZE_ALIAS) {
+ case MEM_SIZE_512K:
+ mach64.total_vram = 0x80000;
+ break;
+ case MEM_SIZE_1M:
+ mach64.total_vram = 0x100000;
+ break;
+ case MEM_SIZE_2M:
+ mach64.total_vram = 0x200000;
+ break;
+ case MEM_SIZE_4M:
+ mach64.total_vram = 0x400000;
+ break;
+ case MEM_SIZE_6M:
+ mach64.total_vram = 0x600000;
+ break;
+ case MEM_SIZE_8M:
+ mach64.total_vram = 0x800000;
+ break;
+ default:
+ mach64.total_vram = 0x80000;
+ break;
+ }
+
printk("mach64_init: total_vram[%08x] is_vt_chip[%d]\n",
mach64.total_vram, mach64.flags & MACH64_MASK_VT ? 1 : 0);
+
+#if 0
+ mach64_test(fb);
+#endif
fb->mmap = mach64_mmap;
fb->loadcmap = mach64_loadcmap;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov