TurboChannel Bsus sysfs port.

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

 



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
-
-



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux