linux-mips
[Top] [All Lists]

TurboChannel Bsus sysfs port.

To: linux-mips@linux-mips.org
Subject: TurboChannel Bsus sysfs port.
From: James Simmons <jsimmons@www.infradead.org>
Date: Sat, 22 Jan 2005 00:25:28 +0000 (GMT)
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
Experimenting with sysfs to figure out how it works. So I'm attempting to 
port the TurboChannel bus code to sysfs. Its a test of concept and a 
learning experience. Comments welcomed.

diff -urN -X /home/jsimmons/dontdiff linus-2.6/drivers/tc/Makefile 
fbdev-2.6/drivers/tc/Makefile
--- linus-2.6/drivers/tc/Makefile       2005-01-21 10:23:32.000000000 -0800
+++ fbdev-2.6/drivers/tc/Makefile       2005-01-20 14:14:54.000000000 -0800
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-$(CONFIG_TC) += tc.o
+obj-$(CONFIG_TC) += tc.o tc-driver.o
 obj-$(CONFIG_ZS) += zs.o
 obj-$(CONFIG_VT) += lk201.o lk201-map.o lk201-remap.o
 
diff -urN -X /home/jsimmons/dontdiff linus-2.6/drivers/tc/tc-driver.c 
fbdev-2.6/drivers/tc/tc-driver.c
--- linus-2.6/drivers/tc/tc-driver.c    1969-12-31 16:00:00.000000000 -0800
+++ fbdev-2.6/drivers/tc/tc-driver.c    2005-01-21 10:22:29.000000000 -0800
@@ -0,0 +1,92 @@
+/*
+ *  TURBO Channel Driver Services
+ *
+ *  Copyright (C) 2005 James Simmons 
+ *
+ *  Loosely based on drivers/tc/dio-driver.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/tc.h>
+
+       /**
+        *  tc_register_driver - register a new TC driver
+        *  @drv: the driver structure to register
+        *
+        *  Adds the driver structure to the list of registered drivers
+        *  Returns the number of TC devices which were claimed by the driver
+        *  during registration.  The driver remains registered even if the
+        *  return value is zero.
+        */
+
+int tc_register_driver(struct tc_driver *drv)
+{
+       int count = 0;
+
+       /* initialize common driver fields */
+       drv->driver.name = drv->name;
+       drv->driver.bus = &tc_bus_type;
+
+       /* register with core */
+       count = driver_register(&drv->driver);
+       return count ? count : 1;
+}
+
+       /**
+        *  tc_unregister_driver - unregister a TC driver
+        *  @drv: the driver structure to unregister
+        *
+        *  Deletes the driver structure from the list of registered TC drivers,
+        *  gives it a chance to clean up by calling its remove() function for
+        *  each device it was responsible for, and marks those devices as
+        *  driverless.
+        */
+
+void tc_unregister_driver(struct tc_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+
+
+       /**
+        *  tc_bus_match - Tell if a TC device structure has a matching TC
+        *                  device id structure
+        *  @ids: array of TC device id structures to search in
+        *  @dev: the TC device structure to match against
+        *
+        *  Used by a driver to check whether a TC device present in the
+        *  system is in its list of supported devices. Returns the matching
+        *  tc_device_id structure or %NULL if there is no match.
+        */
+
+static int tc_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct tc_driver *tc_drv = to_tc_driver(drv);
+       struct tc_dev *tdev = to_tc_dev(dev);
+
+       return (strncmp(tdev->name, drv->name, 9) == 0);
+}
+
+struct bus_type tc_bus_type = {
+       .name   = "tc",
+       .match  = tc_bus_match
+};
+
+
+static int __init tc_driver_init(void)
+{
+       return bus_register(&tc_bus_type);
+}
+
+postcore_initcall(tc_driver_init);
+
+EXPORT_SYMBOL(tc_match_device);
+EXPORT_SYMBOL(tc_register_driver);
+EXPORT_SYMBOL(tc_unregister_driver);
+EXPORT_SYMBOL(tc_dev_driver);
+EXPORT_SYMBOL(tc_bus_type);
diff -urN -X /home/jsimmons/dontdiff linus-2.6/drivers/tc/tc.c 
fbdev-2.6/drivers/tc/tc.c
--- linus-2.6/drivers/tc/tc.c   2005-01-21 10:23:32.000000000 -0800
+++ fbdev-2.6/drivers/tc/tc.c   2005-01-21 10:28:15.000000000 -0800
@@ -26,9 +26,6 @@
 #define TC_DEBUG
 
 MODULE_LICENSE("GPL");
-slot_info tc_bus[MAX_SLOT];
-static int max_tcslot;
-static tcinfo *info;
 
 unsigned long system_base;
 
@@ -40,54 +37,14 @@
  * Interface to the world. Read comment in include/asm-mips/tc.h.
  */
 
-int search_tc_card(char *name)
-{
-       int slot;
-       slot_info *sip;
-
-       for (slot = 0; slot <= max_tcslot; slot++) {
-               sip = &tc_bus[slot];
-               if ((sip->flags & FREE) && (strncmp(sip->name, name, 
strlen(name)) == 0)) {
-                       return slot;
-               }
-       }
-
-       return -ENODEV;
-}
-
-void claim_tc_card(int slot)
-{
-       if (tc_bus[slot].flags & IN_USE) {
-               printk("claim_tc_card: attempting to claim a card already in 
use\n");
-               return;
-       }
-       tc_bus[slot].flags &= ~FREE;
-       tc_bus[slot].flags |= IN_USE;
-}
-
-void release_tc_card(int slot)
-{
-       if (tc_bus[slot].flags & FREE) {
-               printk("release_tc_card: attempting to release a card already 
free\n");
-               return;
-       }
-       tc_bus[slot].flags &= ~IN_USE;
-       tc_bus[slot].flags |= FREE;
-}
-
-unsigned long get_tc_base_addr(int slot)
-{
-       return tc_bus[slot].base_addr;
-}
-
 unsigned long get_tc_irq_nr(int slot)
 {
-       return tc_bus[slot].interrupt;
+       return tc_devices[slot].interrupt;
 }
 
 unsigned long get_tc_speed(void)
 {
-       return 100000 * (10000 / (unsigned long)info->clk_period);
+       return 100000 * (10000 / (unsigned long)tc_bus.info->clk_period);
 }
 
 /*
@@ -98,138 +55,144 @@
        regs->cp0_epc += 4;
 }
 
-static void __init tc_probe(unsigned long startaddr, unsigned long size, int 
max_slot)
+static void __init tc_bus_add_devices(struct tc_bus *bus, unsigned long 
startaddr)
 {
-       int i, slot;
-       long offset;
-       unsigned char *module;
+       unsigned long size = bus->info->slot_size << 20;
        void (*old_be_handler)(struct pt_regs *regs);
+       unsigned char *module;
+       struct tc_device *dev;  
+       long offset;
+       int i, slot;
 
+       switch (mips_machtype) {
+       case MACH_DS5000_200:
+               bus->max_tcslot = 6;
+               break;
+       case MACH_DS5000_1XX:
+       case MACH_DS5000_2X0:
+               bus->max_tcslot = 2;
+               break;
+       case MACH_DS5000_XX:
+       default:
+               bus->max_tcslot = 1;
+               break;
+       }
+       
        /* Install our exception handler temporarily */
-
        old_be_handler = dbe_board_handler;
        dbe_board_handler = my_dbe_handler;
-       for (slot = 0; slot <= max_slot; slot++) {
+       
+       for (slot = 0; slot <= bus->max_slot; slot++) {
                module = (char *)(startaddr + slot * size);
                offset = -1;
-               if (module[OLDCARD + TC_PATTERN0] == 0x55 && module[OLDCARD + 
TC_PATTERN1] == 0x00
-                 && module[OLDCARD + TC_PATTERN2] == 0xaa && module[OLDCARD + 
TC_PATTERN3] == 0xff)
+               if (module[OLDCARD + TC_PATTERN0] == 0x55 &&
+                   module[OLDCARD + TC_PATTERN1] == 0x00 &&
+                   module[OLDCARD + TC_PATTERN2] == 0xaa &&
+                   module[OLDCARD + TC_PATTERN3] == 0xff)
                        offset = OLDCARD;
-               if (module[TC_PATTERN0] == 0x55 && module[TC_PATTERN1] == 0x00
-                 && module[TC_PATTERN2] == 0xaa && module[TC_PATTERN3] == 0xff)
+               if (module[TC_PATTERN0] == 0x55 && module[TC_PATTERN1] == 0x00 
&& 
+                   module[TC_PATTERN2] == 0xaa && module[TC_PATTERN3] == 0xff)
                        offset = 0;
 
                if (offset != -1) {
-                       tc_bus[slot].base_addr = (unsigned long)module;
+                       /* Found a board, allocate it an entry in the list */
+                       dev = kmalloc(sizeof(struct tc_dev), GFP_KERNEL);
+                       if (!dev)
+                               return 0;
+                       memset(dev, 0, sizeof(struct tc_dev));
+                       dev->bus = &tc_bus;
+                       dev->dev.parent = &tc_bus.dev;
+                       dev->dev.bus = &tc_bus_type;
+                       dev->slot = slot;               
+                       
+                       dev->base_addr = (unsigned long)module;
                        for(i = 0; i < 8; i++) {
-                               tc_bus[slot].firmware[i] = module[TC_FIRM_VER + 
offset + 4 * i];
-                               tc_bus[slot].vendor[i] = module[TC_VENDOR + 
offset + 4 * i];
-                               tc_bus[slot].name[i] = module[TC_MODULE + 
offset + 4 * i];
+                               dev->firmware[i] = module[TC_FIRM_VER + offset 
+ 4 * i];
+                               dev->vendor[i] = module[TC_VENDOR + offset + 4 
* i];
+                               dev->name[i] = module[TC_MODULE + offset + 4 * 
i];
                        }
-                       tc_bus[slot].firmware[8] = 0;
-                       tc_bus[slot].vendor[8] = 0;
-                       tc_bus[slot].name[8] = 0;
+                       dev->firmware[8] = 0;
+                       dev->vendor[8] = 0;
+                       dev->name[8] = 0;
+
                        /*
                         * Looks unneccesary, but we may change
                         * TC? in the future
                         */
                        switch (slot) {
                        case 0:
-                               tc_bus[slot].interrupt = TC0;
+                               dev->interrupt = TC0;
                                break;
                        case 1:
-                               tc_bus[slot].interrupt = TC1;
+                               dev->interrupt = TC1;
                                break;
                        case 2:
-                               tc_bus[slot].interrupt = TC2;
+                               dev->interrupt = TC2;
                                break;
                        /*
                         * Yuck! DS5000/200 onboard devices
                         */
                        case 5:
-                               tc_bus[slot].interrupt = SCSI_INT;
+                               dev->interrupt = SCSI_INT;
                                break;
                        case 6:
-                               tc_bus[slot].interrupt = ETHER;
+                               dev->interrupt = ETHER;
                                break;
                        default:
-                               tc_bus[slot].interrupt = -1;
+                               dev->interrupt = -1;
                                break;
-                       }       
+                       }
                }
        }
-
        dbe_board_handler = old_be_handler;
+
+       /*
+        * All TURBOchannel DECstations have the onboard devices
+        * where the (max_tcslot + 1 or 2 on DS5k/xx) Option Module
+        * would be.
+        */
+       if (mips_machtype == MACH_DS5000_XX)
+               i = 2;
+       else
+               i = 1;
+        system_base = startaddr + size * (bus->max_tcslot + i);
 }
 
 /*
  * the main entry
  */
-void __init tc_init(void)
+static int __init tc_init(void)
 {
-       int tc_clock;
-       int i;
        unsigned long slot0addr;
        unsigned long slot_size;
-
+       int tc_clock;
+       int i;
+       
        if (!TURBOCHANNEL)
                return;
 
-       for (i = 0; i < MAX_SLOT; i++) {
-               tc_bus[i].base_addr = 0;
-               tc_bus[i].name[0] = 0;
-               tc_bus[i].vendor[0] = 0;
-               tc_bus[i].firmware[0] = 0;
-               tc_bus[i].interrupt = -1;
-               tc_bus[i].flags = FREE;
-       }
+       /* Initialize the Turbo Channel bus */
+       INIT_LIST_HEAD(&tc_bus.devices);
+       strcpy(tc_bus.dev.bus_id, "TURBO Channel");
+       device_register(&tc_bus.dev);
 
-       info = (tcinfo *) rex_gettcinfo();
+       tc_bus.info = (tcinfo *) rex_gettcinfo();
        slot0addr = (unsigned long)KSEG1ADDR(rex_slot_address(0));
 
-       switch (mips_machtype) {
-       case MACH_DS5000_200:
-               max_tcslot = 6;
-               break;
-       case MACH_DS5000_1XX:
-       case MACH_DS5000_2X0:
-               max_tcslot = 2;
-               break;
-       case MACH_DS5000_XX:
-       default:
-               max_tcslot = 1;
-               break;
-       }
-
-       tc_clock = 10000 / info->clk_period;
+       tc_clock = 10000 / tc_bus.info->clk_period;
 
-       if (TURBOCHANNEL && info->slot_size && slot0addr) {
-               printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision,
+       if (tc_bus.info->slot_size && slot0addr) {
+               printk("TURBOchannel rev. %1d at %2d.%1d MHz", 
tc_bus.info->revision,
                        tc_clock / 10, tc_clock % 10);
-               printk("(with%s parity)\n", info->parity ? "" : "out");
-
-               slot_size = info->slot_size << 20;
-
-               tc_probe(slot0addr, slot_size, max_tcslot);
-
-               /*
-                * All TURBOchannel DECstations have the onboard devices
-                * where the (max_tcslot + 1 or 2 on DS5k/xx) Option Module
-                * would be.
-                */
-               if(mips_machtype == MACH_DS5000_XX)
-                       i = 2;
-               else
-                       i = 1;
-               
-               system_base = slot0addr + slot_size * (max_tcslot + i);
+               printk("(with%s parity)\n", tc_bus.info->parity ? "" : "out");
 
+               tc_bus_add_devices(&tc_bus, slot0addr);
 #ifdef TC_DEBUG
-               for (i = 0; i <= max_tcslot; i++)
-                       if (tc_bus[i].base_addr) {
+               for (i = 0; i <= tc_bus.max_tcslot; i++)
+                       if (tc_devices[i].base_addr) {
                                printk("    slot %d: ", i);
-                               printk("%s %s %s\n", tc_bus[i].vendor,
-                                       tc_bus[i].name, tc_bus[i].firmware);
+                               printk("%s %s %s\n", tc_devices[i].vendor,
+                                       tc_devices[i].name, 
tc_devices[i].firmware);
                        }
 #endif
                ioport_resource.end = KSEG2 - 1;
@@ -238,9 +201,6 @@
 
 subsys_initcall(tc_init);
 
-EXPORT_SYMBOL(search_tc_card);
-EXPORT_SYMBOL(claim_tc_card);
-EXPORT_SYMBOL(release_tc_card);
 EXPORT_SYMBOL(get_tc_base_addr);
 EXPORT_SYMBOL(get_tc_irq_nr);
 EXPORT_SYMBOL(get_tc_speed);
diff -urN -X /home/jsimmons/dontdiff linus-2.6/drivers/video/pmag-ba-fb.c 
fbdev-2.6/drivers/video/pmag-ba-fb.c
--- linus-2.6/drivers/video/pmag-ba-fb.c        2005-01-21 10:23:49.000000000 
-0800
+++ fbdev-2.6/drivers/video/pmag-ba-fb.c        2005-01-21 10:26:48.000000000 
-0800
@@ -118,12 +118,12 @@
        .fb_cursor      = soft_cursor,
 };
 
-int __init pmagbafb_init_one(int slot)
+static int __devinit pmagbafb_probe(struct tc_dev *dev)
 {
-       unsigned long base_addr = get_tc_base_addr(slot);
-       struct fb_info *info = &pmagba_fb_info[slot]; 
+       struct fb_info *info = &pmagba_fb_info[dev->slot]; 
+       unsigned long base_addr = dev->base_addr;
 
-       printk("PMAG-BA framebuffer in slot %d\n", slot);
+       printk("PMAG-BA framebuffer in slot %d\n", dev->slot);
        /*
         * Framebuffer display memory base address and friends
         */
@@ -155,24 +155,28 @@
  * Initialise the framebuffer
  */
 
+static struct tc_device_id pmagbafb_tc_tbl[] = {
+       { "PMAG-BA" },
+       { 0 }
+};
+
+
+static struct tc_driver pmagbafb_driver = {
+       .name      = "PMAG-BA",
+       .id_table  = pmagbafb_tc_tbl,
+       .probe     = pmagbafb_probe,
+};
+
 int __init pmagbafb_init(void)
 {
-       int sid;
-       int found = 0;
-
        if (fb_get_options("pmagbafb", NULL))
                return -ENODEV;
+       return tc_register_driver(&pmagbafb_driver);
+}
 
-       if (TURBOCHANNEL) {
-               while ((sid = search_tc_card("PMAG-BA")) >= 0) {
-                       found = 1;
-                       claim_tc_card(sid);
-                       pmagbafb_init_one(sid);
-               }
-               return found ? 0 : -ENODEV;
-       } else {
-               return -ENODEV;
-       }
+void __exit pmagbafb_exit(void)
+{
+       tc_unregister_driver(&pmagbafb_driver);
 }
 
 module_init(pmagbafb_init);
diff -urN -X /home/jsimmons/dontdiff linus-2.6/include/asm-mips/dec/tc.h 
fbdev-2.6/include/asm-mips/dec/tc.h
--- linus-2.6/include/asm-mips/dec/tc.h 2005-01-21 10:25:17.000000000 -0800
+++ fbdev-2.6/include/asm-mips/dec/tc.h 2005-01-20 21:23:47.000000000 -0800
@@ -10,6 +10,47 @@
 #ifndef ASM_TC_H
 #define ASM_TC_H
 
+#include <linux/device.h>
+
+/*
+ * TURBOchannel Bus
+ */
+
+struct tc_bus {
+       struct list_head devices;       /* list of devices on this bus */
+       unsigned int num_resources;     /* number of resources */
+       struct resource resources[2];   /* address space routed to this bus */
+       
+       struct device dev;
+       char name[10];
+       int max_tcslot;
+       tcinfo *info;
+};
+
+#define MAX_SLOT 7
+
+struct tc_dev {
+       struct tc_driver *driver;
+       struct tc_bus *bus;
+       struct device *dev;
+       unsigned long base_addr;
+       unsigned char name[9];
+       unsigned char vendor[9];
+       unsigned char firmware[9];
+       int interrupt;
+       int flags;
+       int slot;
+};
+
+/*
+ *  * Values for flags
+ *   */
+#define FREE    1<<0
+#define IN_USE  1<<1
+
+typedef char* tc_device_id;
+
+
 extern unsigned long system_base;
 
 /*
diff -urN -X /home/jsimmons/dontdiff linus-2.6/include/asm-mips/dec/tcinfo.h 
fbdev-2.6/include/asm-mips/dec/tcinfo.h
--- linus-2.6/include/asm-mips/dec/tcinfo.h     2005-01-21 10:25:17.000000000 
-0800
+++ fbdev-2.6/include/asm-mips/dec/tcinfo.h     2005-01-20 20:34:25.000000000 
-0800
@@ -27,21 +27,3 @@
        int reserved[4];
 } tcinfo;
 
-#define MAX_SLOT 7
-
-typedef struct {
-       unsigned long base_addr;
-       unsigned char name[9];
-       unsigned char vendor[9];
-       unsigned char firmware[9];
-       int interrupt;
-       int flags;
-} slot_info;
-
-/*
- * Values for flags
- */
-#define FREE   1<<0
-#define IN_USE 1<<1
-
-


<Prev in Thread] Current Thread [Next in Thread>