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 <[EMAIL PROTECTED]>

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 <[EMAIL PROTECTED]>
+
+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 <[EMAIL PROTECTED]>
+
+   Somewhat based on i2c-parport-light.c driver
+   Copyright (C) 2003-2007 Jean Delvare <[EMAIL PROTECTED]>
+
+   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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+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 <[EMAIL PROTECTED]>");
+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
i2c@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/i2c

Reply via email to