Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: Herbert Poetzl <herbert-dBHVzrDq9nF4Lj/PQRBjDg <at> public.gmane.org>
Subject: [PATCH] i2c: Floppy controller bus driver (V0.6.1)
Newsgroups: gmane.linux.drivers.i2c
Date: Wednesday 1st October 2008 17:08:27 UTC (over 8 years ago)
here is the latest version of the I2C floppy 
controller bus driver, which is now completely
configurable and can handle 'single floppy' type
controllers (where the second motor control is
missing).

please consider for (mainline) inclusion!

TIA,
Herbert

Signed-off-by: Herbert Poetzl


diff -NurpP --minimal linux-2.6.27-rc8/Documentation/i2c/busses/i2c-floppy
linux-2.6.27-rc8-fi2c-v0.6.1/Documentation/i2c/busses/i2c-floppy
--- linux-2.6.27-rc8/Documentation/i2c/busses/i2c-floppy	1970-01-01
01:00:00.000000000 +0100
+++
linux-2.6.27-rc8-fi2c-v0.6.1/Documentation/i2c/busses/i2c-floppy	2008-09-30
22:56:14.000000000 +0200
@@ -0,0 +1,151 @@
+Kernel driver i2c-floppy
+
+Author: Herbert Poetzl 
+
+This driver is for a simple do-it-yourself floppy controller
+to I2C adapter which uses direct I/O access and the sense
+command to control the output lines and query the input lines.
+
+Potential output lines are (for now):
+
+ Motor Enable A  [/MOTEA,  10]
+ Drive Select B  [/DRVSB,  12]
+ Drive Select A  [/DRVSA,  14]
+ Motor Enable B  [/MOTEB,  16]
+ Head Select     [/SIDE1,  32]
+
+Potential input lines are (for now):
+
+ Track 0         [/TRK00,  26]
+ Write Protect   [/WPT,    28]
+ Disk Change     [/DSKCHG, 34]
+
+Not all possible combinations are useable, as for example
+the Drive Select lines depend on the respective Motor Enable
+line. Nevertheless, the possible combinations can be selected
+from the following table:
+
+ Mode             ENA             SDA          SCL
+-------------------------------------------------------
+   1               -          /MOTEA [10]  /MOTEB [16]
+   2          /SIDE1 [32]     /MOTEA [10]  /MOTEB [16]
+  -----------------------------------------------------
+   3               -          /MOTEA [10]  /DRVSB [12]
+   4          /MOTEB [16]     /MOTEA [10]  /DRVSB [12]
+   5          /SIDE1 [32]     /MOTEA [10]  /DRVSB [12]
+  -----------------------------------------------------
+   6               -          /MOTEA [10]  /SIDE1 [32]
+   7          /MOTEB [16]     /MOTEA [10]  /SIDE1 [32]
+   8          /DRVSB [12]     /MOTEA [10]  /SIDE1 [32]
+  -----------------------------------------------------
+   9               -          /MOTEB [16]  /DRVSA [14]
+  10 [0a]     /MOTEA [10]     /MOTEB [16]  /DRVSA [14]
+  11 [0b]     /SIDE1 [32]     /MOTEB [16]  /DRVSA [14]
+  -----------------------------------------------------
+  12 [0c]          -          /MOTEB [16]  /SIDE1 [32]
+  13 [0d]     /MOTEA [10]     /MOTEB [16]  /SIDE1 [32]
+  14 [0e]     /DRVSA [14]     /MOTEB [16]  /SIDE1 [32]
+  -----------------------------------------------------
+  15 [0f]          -          /SIDE1 [32]  /DRVSA [14]
+  16 [10]     /MOTEA [10]     /SIDE1 [32]  /DRVSA [14]
+  17 [11]     /MOTEB [16]     /SIDE1 [32]  /DRVSA [14]
+  18 [12]     /DRVSB [12]     /SIDE1 [32]  /DRVSA [14]
+  -----------------------------------------------------
+  19 [13]          -          /SIDE1 [32]  /DRVSB [12]
+  20 [14]     /MOTEA [10]     /SIDE1 [32]  /DRVSB [12]
+  21 [15]     /MOTEB [16]     /SIDE1 [32]  /DRVSB [12]
+  22 [16]     /DRVSA [14]     /SIDE1 [32]  /DRVSB [12]
+-------------------------------------------------------
+
+The following modifiers can be added to the selection:
+
+  32 0x0020      Swap SCL and SDA
+  64 0x0040      Invert SDA Output
+ 128 0x0080      Invert SCL Output
+ 256 0x0100      Invert ENA Output
+
+
+The input can be selected in a similar way, although it is
+probably easier to use the autodetect feature there.
+Nevertheless here is the table:
+
+ Mode            ENA            SDA           SCL
+-------------------------------------------------------
+   0         auto detect    auto detect   auto detect
+  -----------------------------------------------------
+   1              -         /DSKCHG [34]       -
+   2              -         /TRK00  [26]       -
+   3              -         /WPT    [28]       -
+  -----------------------------------------------------
+   4              -         /DSKCHG [34]  /TRK00  [26]
+   5              -         /TRK00  [26]  /WPT    [28]
+   6              -         /WPT    [28]  /DSKCHG [34]
+  -----------------------------------------------------
+   7         /DSKCHG [34]   /TRK00  [26]       -
+   8         /DSKCHG [34]   /WPT    [28]       -
+   9         /DSKCHG [34]   /TRK00  [26]  /WPT    [28]
+  -----------------------------------------------------
+  10 [0a]    /TRK00  [26]   /DSKCHG [34]       -
+  11 [0b]    /TRK00  [26]   /WPT    [28]       -
+  12 [0c]    /TRK00  [26]   /WPT    [28]  /DSKCHG [34]
+  -----------------------------------------------------
+  13 [0d]    /WPT    [28]   /DSKCHG [34]       -
+  14 [0e]    /WPT    [28]   /TRK00  [26]       -
+  15 [0f]    /WPT    [28]   /DSKCHG [34]  /TRK00  [26]
+-------------------------------------------------------
+
+In addition, the same modifiers can be applied as for the
+output.
+
+
+The following (minimal) circuit is not suited to be used
+together with a Floppy drive (which would need some logic
+to work properly) but as replacement.
+
+ +---+
+ | F |  Motor Enable A [/MOTEA,10] -------------- SCL
+ | L |
+ | O |  Motor Enable B [/MOTEB,16] ------+------- SDA
+ | P |                                   |
+ | P |                                   |
+ | Y |  Disk Change   [/DSKCHG,34] ------+    +-- GND
+ +-+-+                                        |
+   |                                          |
+  GND	                                     GND
+
+The Motor Enable output of floppy disk controllers is an open
+drain output (48mA), usually pulled up to +5V via 1k or higher,
+and the Disk Change is a Schmitt Trigger (0.8V/2.2V) input with
+max 150uA input current (data taken from the WD/FDC 37C6xx
+Floppy Disk Subsystem Controller datasheets, which basically
+combine all the necessary parts of the PC floppy circuit).
+
+So it should be fine to connect it to all 5V I2C devices, and
+most 3.3V devices (which are usually capable of handling 5V
+I2C bus voltages).
+
+Power for those devices can be drawn from either the Floppy
+power connector (+5V/+12V) or from the SATA 3.3V lines
+(or if you prefer from some external source).
+
+
+Here is a slightly more advanced circuit, which works on
+controllers with reduced functionality (i.e. without control
+lines for a second drive), while allowing for SCL readback
+(and thus clock stretching):
+
+
+ +---+
+ |   |  Motor Enable A [/MOTEA,10] -------------- ENA
+ | F |
+ | L |  Drive Select A [/DRVSA,14] ------+------- SDA
+ | O |                                   |
+ | P |  Write Protect  [/WPT,28] --------+
+ | P |
+ | Y |  Head Select    [/SIDE1,32] ------+------- SCL
+ |   |                                   |
+ |   |  Disk Change    [/DSKCHG,34] -----+    +-- GND
+ +-+-+                                        |
+   |                                          |
+  GND	                                     GND
+
diff -NurpP --minimal linux-2.6.27-rc8/drivers/i2c/busses/i2c-floppy.c
linux-2.6.27-rc8-fi2c-v0.6.1/drivers/i2c/busses/i2c-floppy.c
--- linux-2.6.27-rc8/drivers/i2c/busses/i2c-floppy.c	1970-01-01
01:00:00.000000000 +0100
+++ linux-2.6.27-rc8-fi2c-v0.6.1/drivers/i2c/busses/i2c-floppy.c	2008-10-01
18:34:32.000000000 +0200
@@ -0,0 +1,626 @@
+/*
------------------------------------------------------------------------ *
+ * i2c-floppy.c I2C bus over floppy controller                            
 *
+ *
------------------------------------------------------------------------ *
+   Copyright (C) 2008 Herbert Poetzl

+
+   Somewhat based on i2c-parport-light.c driver
+   Copyright (C) 2003-2007 Jean Delvare

+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
------------------------------------------------------------------------ */
+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static struct platform_device *pdev;
+static unsigned char dor;
+
+static u16 base;
+module_param(base, ushort, 0);
+MODULE_PARM_DESC(base, "Base I/O address");
+
+static u16 delay;
+module_param(delay, ushort, 0);
+MODULE_PARM_DESC(base, "Signal delay");
+
+
+#define DEFAULT_BASE	0x3F0		/* for PC style hardware */
+#define DRVNAME		"i2c-floppy"
+
+
+#define FOFF_DOR	0x02
+#define FOFF_MSR	0x04
+#define FOFF_DATA	0x05
+#define FOFF_CCR	0x07
+#define FOFF_DIR	0x07
+
+
+#define	FDOR_MOA	0x10
+#define	FDOR_MOB	0x20
+#define	FDOR_DS0	0x01
+#define	FDOR_DS1	0x02
+
+#define	FDOR_RESET	0x04
+
+#define	FDIR_CHG	0x80
+
+#define	FMSR_RQM	0x80
+#define	FMSR_DIO	0x40
+#define	FMSR_CMD	0x10
+
+#define	FCMD_SENSE	0x04
+#define	FCMS_HDS	0x04
+
+#define	FST3_T0		0x10
+#define	FST3_WP		0x40
+
+
+/* ----- Low-level floppy access
------------------------------------------ */
+
+static inline void port_dor_out(unsigned char d)
+{
+	outb(d, base + FOFF_DOR);
+}
+
+static inline unsigned char port_dir_in(void)
+{
+	return inb(base + FOFF_DIR);
+}
+
+static inline unsigned char port_msr_in(void)
+{
+	return inb(base + FOFF_MSR);
+}
+
+static inline void port_data_out(unsigned char d)
+{
+	outb(d, base + FOFF_DATA);
+}
+
+static inline unsigned char port_data_in(void)
+{
+	return inb(base + FOFF_DATA);
+}
+
+
+/* ----- Floppy controller sense
------------------------------------------ */
+
+
+static inline unsigned char msr_wait(
+	unsigned mask, unsigned val, int timeout)
+{
+	unsigned char st;
+
+	/* wait for controller */
+	while (((st = port_msr_in()) & mask) != val)
+		if (!--timeout)
+			break;
+
+	if (timeout)
+		return st;
+
+	pr_err(DRVNAME ": timeout reached ... %02x/%02x\n", dor, st);
+	return 0;
+}
+
+unsigned char cmd_sense(unsigned char head)
+{
+	unsigned char st;
+
+	/* wait for controller */
+	msr_wait(FMSR_RQM|FMSR_CMD, FMSR_RQM, 5000);
+
+	port_data_out(FCMD_SENSE);
+	st = msr_wait(FMSR_RQM, FMSR_RQM, 5000);
+
+	if (!(st & FMSR_CMD))
+		return 0;
+
+	port_data_out(head ? FCMS_HDS : 0);
+	st = msr_wait(FMSR_RQM, FMSR_RQM, 5000);
+
+	if (!(st & FMSR_CMD))
+		return 0;
+
+	return port_data_in();
+}
+
+
+/* ----- Output and input lines
------------------------------------------- */
+
+#define	LINE_OFF	0x00
+
+	/* output lines */
+
+#define	LINE_MOA	FDOR_MOA
+#define	LINE_MOB	FDOR_MOB
+#define	LINE_DS0	FDOR_DS0
+#define	LINE_DS1	FDOR_DS1
+
+#define	LINE_MASK_DOR	(LINE_MOA | LINE_MOB | LINE_DS0 | LINE_DS1)
+
+#define	LINE_HDS	0x08
+
+struct i2c_floppy_lines {
+	unsigned ena:8;
+	unsigned sda:8;
+	unsigned scl:8;
+};
+
+static struct i2c_floppy_lines i2c_floppy_lines_out[] = {
+	{ LINE_OFF, LINE_OFF, LINE_OFF },	/*  0 */
+
+	{ LINE_OFF, LINE_MOA, LINE_MOB },	/*  1 */
+	{ LINE_HDS, LINE_MOA, LINE_MOB },	/*  2 */
+
+	{ LINE_OFF, LINE_MOA, LINE_DS1 },	/*  3 */
+	{ LINE_MOB, LINE_MOA, LINE_DS1 },	/*  4 */
+	{ LINE_HDS, LINE_MOA, LINE_DS1 },	/*  5 */
+
+	{ LINE_OFF, LINE_MOA, LINE_HDS },	/*  6 */
+	{ LINE_MOB, LINE_MOA, LINE_HDS },	/*  7 */
+	{ LINE_DS1, LINE_MOA, LINE_HDS },	/*  8 */
+
+	{ LINE_OFF, LINE_MOB, LINE_DS0 },	/*  9 */
+	{ LINE_MOA, LINE_MOB, LINE_DS0 },	/* 10 */
+	{ LINE_HDS, LINE_MOB, LINE_DS0 },	/* 11 */
+
+	{ LINE_OFF, LINE_MOB, LINE_HDS },	/* 12 */
+	{ LINE_MOA, LINE_MOB, LINE_HDS },	/* 13 */
+	{ LINE_DS0, LINE_MOB, LINE_HDS },	/* 14 */
+
+	{ LINE_OFF, LINE_HDS, LINE_DS0 },	/* 15 */
+	{ LINE_MOA, LINE_HDS, LINE_DS0 },	/* 16 */
+	{ LINE_MOB, LINE_HDS, LINE_DS0 },	/* 17 */
+	{ LINE_DS1, LINE_HDS, LINE_DS0 },	/* 18 */
+
+	{ LINE_OFF, LINE_HDS, LINE_DS1 },	/* 19 */
+	{ LINE_MOA, LINE_HDS, LINE_DS1 },	/* 20 */
+	{ LINE_MOB, LINE_HDS, LINE_DS1 },	/* 21 */
+	{ LINE_DS0, LINE_HDS, LINE_DS1 },	/* 22 */
+};
+
+	/* input lines */
+
+#define	LINE_T0		FST3_T0
+#define	LINE_WP		FST3_WP
+
+#define	LINE_MASK_ST3	(LINE_T0 | LINE_WP)
+
+#define LINE_CHG	FDIR_CHG
+
+static struct i2c_floppy_lines i2c_floppy_lines_in[] = {
+	{ LINE_OFF, LINE_OFF, LINE_OFF },	/*  0 - auto*/
+
+	{ LINE_OFF, LINE_CHG, LINE_OFF },	/*  1 */
+	{ LINE_OFF, LINE_T0,  LINE_OFF },	/*  2 */
+	{ LINE_OFF, LINE_WP,  LINE_OFF },	/*  3 */
+
+	{ LINE_OFF, LINE_CHG, LINE_T0  },	/*  4 */
+	{ LINE_OFF, LINE_T0,  LINE_WP  },	/*  5 */
+	{ LINE_OFF, LINE_WP,  LINE_CHG },	/*  6 */
+
+	{ LINE_CHG, LINE_T0,  LINE_OFF },	/*  7 */
+	{ LINE_CHG, LINE_WP,  LINE_OFF },	/*  8 */
+	{ LINE_CHG, LINE_T0,  LINE_WP  },	/*  9 */
+
+	{ LINE_T0,  LINE_CHG, LINE_OFF },	/* 10 */
+	{ LINE_T0,  LINE_WP,  LINE_OFF },	/* 11 */
+	{ LINE_T0,  LINE_WP,  LINE_CHG },	/* 12 */
+
+	{ LINE_WP,  LINE_CHG, LINE_OFF },       /* 13 */
+	{ LINE_WP,  LINE_T0,  LINE_OFF },       /* 14 */
+	{ LINE_WP,  LINE_CHG, LINE_T0  },       /* 15 */
+};
+
+	/* parameters */
+
+#define	LM_SWAP		0x0020
+#define	LM_INV_SDA	0x0040
+#define	LM_INV_SCL	0x0080
+#define	LM_INV_ENA	0x0100
+
+
+static unsigned int line_mode = 0xe1;
+module_param(line_mode, uint, 0);
+MODULE_PARM_DESC(line_mode, "Output line mode");
+
+static unsigned int line_mode_in = 0x00;
+module_param(line_mode_in, uint, 0);
+MODULE_PARM_DESC(line_mode_in, "Input line mode");
+
+
+	/* calculated */
+
+static unsigned char lo_inv;
+static unsigned char lo_mask;
+
+static unsigned char li_inv;
+static unsigned char li_mask;
+
+static struct i2c_floppy_lines lines;
+static struct i2c_floppy_lines lines_in;
+
+
+/* ----- Output and input helpers
----------------------------------------- */
+
+static unsigned char i2c_lo;
+
+static void update_lo(unsigned char lo)
+{
+	static unsigned char lo_prev;
+	unsigned char chg = lo ^ lo_prev;
+
+	if (!chg)
+		return;
+
+	lo_prev = lo;
+
+	if (chg & LINE_MASK_DOR) {
+		dor &= ~LINE_MASK_DOR;
+		dor |= (lo ^ lo_inv) & LINE_MASK_DOR;
+		port_dor_out(dor);
+	}
+
+	if (chg & LINE_HDS)
+		cmd_sense((lo ^ lo_inv) & LINE_HDS);
+}
+
+
+static unsigned char i2c_li;
+
+static unsigned char update_li(void)
+{
+	unsigned char li = 0;
+
+	/* conditionally retrieve st3 flags */
+	if (li_mask & LINE_MASK_ST3)
+		li |= cmd_sense((i2c_lo ^ lo_inv) & LINE_HDS)
+			& LINE_MASK_ST3;
+
+	/* conditionally map in disk change */
+	if (li_mask & LINE_CHG)
+		li |= port_dir_in() & FDIR_CHG;
+
+	i2c_li = li;
+	return li;
+}
+
+
+/* ----- I2C algorithm call-back functions and structures
----------------- */
+
+static void floppy_setena(void *data, int state)
+{
+	if (state)
+		i2c_lo |= lines.ena;
+	else
+		i2c_lo &= ~lines.ena;
+
+	update_lo(i2c_lo);
+}
+
+static void floppy_setscl(void *data, int state)
+{
+	if (state)
+		i2c_lo |= lines.scl;
+	else
+		i2c_lo &= ~lines.scl;
+
+	update_lo(i2c_lo);
+}
+
+static void floppy_setsda(void *data, int state)
+{
+	if (state)
+		i2c_lo |= lines.sda;
+	else
+		i2c_lo &= ~lines.sda;
+
+	update_lo(i2c_lo);
+}
+
+
+static int floppy_getena(void *data)
+{
+	return (update_li() ^ li_inv) & lines_in.ena;
+}
+
+static int floppy_getscl(void *data)
+{
+	return (update_li() ^ li_inv) & lines_in.scl;
+}
+
+static int floppy_getsda(void *data)
+{
+	return (update_li() ^ li_inv) & lines_in.sda;
+}
+
+
+static struct i2c_algo_bit_data floppy_algo_data = {
+	.setsda		= floppy_setsda,
+	.setscl		= floppy_setscl,
+	.getsda		= floppy_getsda,
+	.getscl		= floppy_getscl,
+	.udelay		= 50,
+	.timeout	= HZ,
+};
+
+
+/* ----- Driver setup
----------------------------------------------------- */
+
+static void swap_sda_scl(struct i2c_floppy_lines *lines)
+{
+	unsigned char tmp = lines->sda;
+
+	lines->sda = lines->scl;
+	lines->scl = tmp;
+}
+
+
+static void setup_lo(void)
+{
+	/* avoid undefined line modes */
+	if ((line_mode & 0x1F) > 22)
+		line_mode &= ~0x1F;
+
+	lines = i2c_floppy_lines_out[line_mode & 0x1F];
+
+	/* swap scl and sda */
+	if (line_mode & LM_SWAP)
+		swap_sda_scl(&lines);
+
+	if (line_mode & LM_INV_SDA)
+		lo_inv ^= lines.sda;
+	if (line_mode & LM_INV_SCL)
+		lo_inv ^= lines.scl;
+	if (line_mode & LM_INV_ENA)
+		lo_inv ^= lines.ena;
+
+	/* calculate line mask */
+	lo_mask = lines.ena | lines.sda | lines.scl;
+
+	pr_info(DRVNAME ": line output config: "
+		"%02x/%02x/%02x [%02x/%02x]\n",
+		lines.ena, lines.scl, lines.sda, lo_mask, lo_inv);
+}
+
+
+static unsigned char lo_state(int ena, int sda, int scl)
+{
+	floppy_setena(NULL, ena);
+	floppy_setsda(NULL, sda);
+	floppy_setscl(NULL, scl);
+	return update_li();
+}
+
+static void auto_setup_li(void)
+{
+	unsigned char a, b, m;
+
+	li_mask = ~0;
+	li_inv = 0;
+
+	/* reset controller */
+	dor = 0;
+	port_dor_out(dor);
+
+	/* enable controller */
+	dor |= FDOR_RESET;
+	port_dor_out(dor);
+
+	udelay(100);
+
+	a = lo_state(0, 1, 1);
+	b = lo_state(1, 1, 1);
+	m = a ^ b;	/* maybe only one bit? */
+
+	/* calculate enable input */
+	lines_in.ena = m;
+	li_inv |= a & m;
+
+	a = b;
+	b = lo_state(1, 1, 0);
+	m = a ^ b;	/* maybe only one bit? */
+
+	/* calculate scl input */
+	lines_in.scl = m;
+	li_inv |= b & m;
+
+	a = b;
+	b = lo_state(1, 0, 0);
+	m = a ^ b;	/* maybe only one bit? */
+
+	/* calculate sda input */
+	lines_in.sda = m;
+	li_inv |= b & m;
+}
+
+static void setup_li(void)
+{
+	/* automatic setup if selected */
+	if (!line_mode_in) {
+		auto_setup_li();
+		goto calc_mask;
+	}
+
+	lines_in = i2c_floppy_lines_in[line_mode_in & 0x0F];
+
+	/* swap scl and sda */
+	if (line_mode_in & LM_SWAP)
+		swap_sda_scl(&lines_in);
+
+	if (line_mode_in & LM_INV_SDA)
+		li_inv ^= lines_in.sda;
+	if (line_mode_in & LM_INV_SCL)
+		li_inv ^= lines_in.scl;
+	if (line_mode_in & LM_INV_ENA)
+		li_inv ^= lines_in.ena;
+
+calc_mask:
+	/* calculate line mask */
+	li_mask = lines_in.ena | lines_in.sda | lines_in.scl;
+
+	pr_info(DRVNAME ": line input config:  "
+		"%02x/%02x/%02x [%02x/%02x]\n",
+		lines_in.ena, lines_in.scl, lines_in.sda,
+		li_mask, li_inv);
+}
+
+
+/* ----- Driver registration
---------------------------------------------- */
+
+static struct i2c_adapter floppy_adapter = {
+	.owner		= THIS_MODULE,
+	.class		= I2C_CLASS_HWMON,
+	.algo_data	= &floppy_algo_data,
+	.name		= "Floppy controller adapter",
+};
+
+static int __devinit i2c_floppy_probe(struct platform_device *pdev)
+{
+	int err;
+
+	floppy_adapter.dev.parent = &pdev->dev;
+	err = i2c_bit_add_bus(&floppy_adapter);
+	if (err)
+		dev_err(&pdev->dev, "Unable to register with I2C\n");
+	return err;
+}
+
+static int __devexit i2c_floppy_remove(struct platform_device *pdev)
+{
+	i2c_del_adapter(&floppy_adapter);
+	return 0;
+}
+
+static struct platform_driver i2c_floppy_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+	},
+	.probe		= i2c_floppy_probe,
+	.remove		= __devexit_p(i2c_floppy_remove),
+};
+
+static int __init i2c_floppy_device_add(u16 address)
+{
+	int err;
+
+	pdev = platform_device_alloc(DRVNAME, -1);
+	if (!pdev) {
+		err = -ENOMEM;
+		pr_err(DRVNAME ": Device allocation failed\n");
+		goto exit;
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		pr_err(DRVNAME ": Device addition failed (%d)\n",
+		       err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(pdev);
+exit:
+	return err;
+}
+
+static int __init i2c_floppy_init(void)
+{
+	int err;
+
+	if (base == 0) {
+		pr_info(DRVNAME ": using default base 0x%x\n",
+			DEFAULT_BASE);
+		base = DEFAULT_BASE;
+	}
+
+	err = -EBUSY;
+	if (!request_region(base, 5, DRVNAME))
+		goto exit;
+
+	if (!request_region(base + 7, 1, DRVNAME))
+		goto exit_rel0;
+
+	/* Sets global pdev as a side effect */
+	err = i2c_floppy_device_add(base);
+	if (err)
+		goto exit_rel7;
+
+	err = platform_driver_register(&i2c_floppy_driver);
+	if (err)
+		goto exit_device;
+
+	setup_lo();
+	setup_li();
+
+	dor &= ~FDOR_RESET;
+	/* do we need the controller active? */
+	if ((li_mask & LINE_MASK_ST3) ||
+		(lo_mask & LINE_HDS))
+		dor |= FDOR_RESET;
+	port_dor_out(dor);
+
+	lo_state(1, 1, 1);
+	pr_info(DRVNAME ": input line check %02x/%02x/%02x\n",
+		floppy_getena(NULL),
+		floppy_getscl(NULL),
+		floppy_getsda(NULL));
+
+	/* disable getscl if no mapping */
+	if (!lines_in.scl)
+		floppy_algo_data.getscl = NULL;
+
+	/* update udelay with param */
+	floppy_algo_data.udelay = delay;
+
+	return 0;
+
+exit_device:
+	platform_device_unregister(pdev);
+exit_rel7:
+	release_region(base + 7, 1);
+exit_rel0:
+	release_region(base, 5);
+exit:
+	return err;
+}
+
+static void __exit i2c_floppy_exit(void)
+{
+	platform_driver_unregister(&i2c_floppy_driver);
+	platform_device_unregister(pdev);
+	release_region(base + 7, 1);
+	release_region(base, 5);
+}
+
+
+MODULE_AUTHOR("Herbert Poetzl
");
+MODULE_DESCRIPTION("I2C bus over floppy controller");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_floppy_init);
+module_exit(i2c_floppy_exit);
diff -NurpP --minimal linux-2.6.27-rc8/drivers/i2c/busses/Kconfig
linux-2.6.27-rc8-fi2c-v0.6.1/drivers/i2c/busses/Kconfig
--- linux-2.6.27-rc8/drivers/i2c/busses/Kconfig	2008-09-30
22:53:59.000000000 +0200
+++ linux-2.6.27-rc8-fi2c-v0.6.1/drivers/i2c/busses/Kconfig	2008-09-30
22:57:12.000000000 +0200
@@ -490,6 +490,21 @@ config I2C_VERSATILE
 
 comment "External I2C/SMBus adapter drivers"
 
+config I2C_FLOPPY
+	tristate "Floppy controller adapter"
+	select I2C_ALGOBIT
+	help
+	  This supports a simple do-it-yourself floppy controller to
+	  I2C adapters using the motor control lines for SDA and SCL,
+	  and the drive change input for SDA readback.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-floppy.
+
+	  If you do not have such a device, and do not plan to build one,
+	  it's safe to say N here. Do not say Y here and to the floppy
+	  driver unless you know exactly what you are doing.
+
 config I2C_PARPORT
 	tristate "Parallel port adapter"
 	depends on PARPORT
diff -NurpP --minimal linux-2.6.27-rc8/drivers/i2c/busses/Makefile
linux-2.6.27-rc8-fi2c-v0.6.1/drivers/i2c/busses/Makefile
--- linux-2.6.27-rc8/drivers/i2c/busses/Makefile	2008-09-30
22:53:59.000000000 +0200
+++ linux-2.6.27-rc8-fi2c-v0.6.1/drivers/i2c/busses/Makefile	2008-09-30
22:56:14.000000000 +0200
@@ -48,6 +48,7 @@ obj-$(CONFIG_I2C_SIMTEC)	+= i2c-simtec.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 
 # External I2C/SMBus adapter drivers
+obj-$(CONFIG_I2C_FLOPPY)	+= i2c-floppy.o
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
 obj-$(CONFIG_I2C_TAOS_EVM)	+= i2c-taos-evm.o
diff -NurpP --minimal linux-2.6.27-rc8/Makefile
linux-2.6.27-rc8-fi2c-v0.6.1/Makefile
--- linux-2.6.27-rc8/Makefile	2008-09-30 22:53:29.000000000 +0200
+++ linux-2.6.27-rc8-fi2c-v0.6.1/Makefile	2008-10-01 18:43:54.000000000
+0200
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 27
-EXTRAVERSION = -rc8
+EXTRAVERSION = -rc8linux-2.6.27-rc8-fi2c-v0.6.1
 NAME = Rotary Wombat
 
 # *DOCUMENTATION*

_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
 
CD: 21ms