aboutsummaryrefslogtreecommitdiffstats
path: root/i2c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-12-07 15:54:12 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2005-12-07 15:54:12 -0800
commit4bd956d2e2f9072faecd767e9b27da06b89481f0 (patch)
treefe9ce13110e1673e019ba876768a549a01f80f1f /i2c
parentdc4d53eedb18d77f3782c1c8109ebca0424cf976 (diff)
downloadpatches-4bd956d2e2f9072faecd767e9b27da06b89481f0.tar.gz
w1 and usb patches
Diffstat (limited to 'i2c')
-rw-r--r--i2c/w1-add-the-ds2482-i2c-to-w1-bridge-driver.patch646
-rw-r--r--i2c/w1-change-the-type-unsigned-long-member-of-struct-w1_bus_master-to-void.patch279
-rw-r--r--i2c/w1-move-w1-bus-master-code-into-w1-masters-and-move-w1-slave-code-into-w1-slaves.patch4374
3 files changed, 5299 insertions, 0 deletions
diff --git a/i2c/w1-add-the-ds2482-i2c-to-w1-bridge-driver.patch b/i2c/w1-add-the-ds2482-i2c-to-w1-bridge-driver.patch
new file mode 100644
index 00000000000000..46d0abf0b347c0
--- /dev/null
+++ b/i2c/w1-add-the-ds2482-i2c-to-w1-bridge-driver.patch
@@ -0,0 +1,646 @@
+From johnpol@2ka.mipt.ru Tue Dec 6 02:32:28 2005
+From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Cc: Ben Gardner <gardner.ben@gmail.com>, Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Subject: W1: Add the DS2482 I2C-to-w1 bridge driver.
+Date: Tue, 6 Dec 2005 13:38:28 +0300
+Message-Id: <11338655082568@2ka.mipt.ru>
+To: GregKH <greg@kroah.com>
+
+
+Signed-off-by: Ben Gardner <bgardner@wabtec.com>
+Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ Documentation/w1/masters/ds2482 | 31 ++
+ drivers/w1/masters/Kconfig | 10
+ drivers/w1/masters/Makefile | 2
+ drivers/w1/masters/ds2482.c | 564 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 607 insertions(+)
+
+--- /dev/null
++++ gregkh-2.6/Documentation/w1/masters/ds2482
+@@ -0,0 +1,31 @@
++Kernel driver ds2482
++====================
++
++Supported chips:
++ * Maxim DS2482-100, Maxim DS2482-800
++ Prefix: 'ds2482'
++ Addresses scanned: None
++ Datasheets:
++ http://pdfserv.maxim-ic.com/en/ds/DS2482-100-DS2482S-100.pdf
++ http://pdfserv.maxim-ic.com/en/ds/DS2482-800-DS2482S-800.pdf
++
++Author: Ben Gardner <bgardner@wabtec.com>
++
++
++Description
++-----------
++
++The Maixm/Dallas Semiconductor DS2482 is a I2C device that provides
++one (DS2482-100) or eight (DS2482-800) 1-wire busses.
++
++
++General Remarks
++---------------
++
++Valid addresses are 0x18, 0x19, 0x1a, and 0x1b.
++However, the device cannot be detected without writing to the i2c bus, so no
++detection is done.
++You should force the device address.
++
++$ modprobe ds2482 force=0,0x18
++
+--- gregkh-2.6.orig/drivers/w1/masters/Kconfig
++++ gregkh-2.6/drivers/w1/masters/Kconfig
+@@ -34,5 +34,15 @@ config W1_MASTER_DS9490_BRIDGE
+ This support is also available as a module. If so, the module
+ will be called ds_w1_bridge.ko.
+
++config W1_MASTER_DS2482
++ tristate "Maxim DS2482 I2C to 1-Wire bridge"
++ depends on I2C && W1 && EXPERIMENTAL
++ help
++ If you say yes here you get support for the Maxim DS2482
++ I2C to 1-Wire bridge.
++
++ This driver can also be built as a module. If so, the module
++ will be called ds2482.
++
+ endmenu
+
+--- gregkh-2.6.orig/drivers/w1/masters/Makefile
++++ gregkh-2.6/drivers/w1/masters/Makefile
+@@ -9,3 +9,5 @@ ds9490r-objs := dscore.o
+
+ obj-$(CONFIG_W1_MASTER_DS9490_BRIDGE) += ds_w1_bridge.o
+
++obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o
++
+--- /dev/null
++++ gregkh-2.6/drivers/w1/masters/ds2482.c
+@@ -0,0 +1,564 @@
++/**
++ * ds2482.c - provides i2c to w1-master bridge(s)
++ * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
++ *
++ * The DS2482 is a sensor chip made by Dallas Semiconductor (Maxim).
++ * It is a I2C to 1-wire bridge.
++ * There are two variations: -100 and -800, which have 1 or 8 1-wire ports.
++ * The complete datasheet can be obtained from MAXIM's website at:
++ * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/4382
++ *
++ * 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; version 2 of the License.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <asm/delay.h>
++
++#include "../w1.h"
++#include "../w1_int.h"
++
++/**
++ * Address is selected using 2 pins, resulting in 4 possible addresses.
++ * 0x18, 0x19, 0x1a, 0x1b
++ * However, the chip cannot be detected without doing an i2c write,
++ * so use the force module parameter.
++ */
++static unsigned short normal_i2c[] = {I2C_CLIENT_END};
++
++/**
++ * Insmod parameters
++ */
++I2C_CLIENT_INSMOD_1(ds2482);
++
++/**
++ * The DS2482 registers - there are 3 registers that are addressed by a read
++ * pointer. The read pointer is set by the last command executed.
++ *
++ * To read the data, issue a register read for any address
++ */
++#define DS2482_CMD_RESET 0xF0 /* No param */
++#define DS2482_CMD_SET_READ_PTR 0xE1 /* Param: DS2482_PTR_CODE_xxx */
++#define DS2482_CMD_CHANNEL_SELECT 0xC3 /* Param: Channel byte - DS2482-800 only */
++#define DS2482_CMD_WRITE_CONFIG 0xD2 /* Param: Config byte */
++#define DS2482_CMD_1WIRE_RESET 0xB4 /* Param: None */
++#define DS2482_CMD_1WIRE_SINGLE_BIT 0x87 /* Param: Bit byte (bit7) */
++#define DS2482_CMD_1WIRE_WRITE_BYTE 0xA5 /* Param: Data byte */
++#define DS2482_CMD_1WIRE_READ_BYTE 0x96 /* Param: None */
++/* Note to read the byte, Set the ReadPtr to Data then read (any addr) */
++#define DS2482_CMD_1WIRE_TRIPLET 0x78 /* Param: Dir byte (bit7) */
++
++/* Values for DS2482_CMD_SET_READ_PTR */
++#define DS2482_PTR_CODE_STATUS 0xF0
++#define DS2482_PTR_CODE_DATA 0xE1
++#define DS2482_PTR_CODE_CHANNEL 0xD2 /* DS2482-800 only */
++#define DS2482_PTR_CODE_CONFIG 0xC3
++
++/**
++ * Configure Register bit definitions
++ * The top 4 bits always read 0.
++ * To write, the top nibble must be the 1's compl. of the low nibble.
++ */
++#define DS2482_REG_CFG_1WS 0x08
++#define DS2482_REG_CFG_SPU 0x04
++#define DS2482_REG_CFG_PPM 0x02
++#define DS2482_REG_CFG_APU 0x01
++
++
++/**
++ * Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only).
++ * To set the channel, write the value at the index of the channel.
++ * Read and compare against the corresponding value to verify the change.
++ */
++static const u8 ds2482_chan_wr[8] =
++ { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 };
++static const u8 ds2482_chan_rd[8] =
++ { 0xB8, 0xB1, 0xAA, 0xA3, 0x9C, 0x95, 0x8E, 0x87 };
++
++
++/**
++ * Status Register bit definitions (read only)
++ */
++#define DS2482_REG_STS_DIR 0x80
++#define DS2482_REG_STS_TSB 0x40
++#define DS2482_REG_STS_SBR 0x20
++#define DS2482_REG_STS_RST 0x10
++#define DS2482_REG_STS_LL 0x08
++#define DS2482_REG_STS_SD 0x04
++#define DS2482_REG_STS_PPD 0x02
++#define DS2482_REG_STS_1WB 0x01
++
++
++static int ds2482_attach_adapter(struct i2c_adapter *adapter);
++static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind);
++static int ds2482_detach_client(struct i2c_client *client);
++
++
++/**
++ * Driver data (common to all clients)
++ */
++static struct i2c_driver ds2482_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "ds2482",
++ },
++ .attach_adapter = ds2482_attach_adapter,
++ .detach_client = ds2482_detach_client,
++};
++
++/*
++ * Client data (each client gets its own)
++ */
++
++struct ds2482_data;
++
++struct ds2482_w1_chan {
++ struct ds2482_data *pdev;
++ u8 channel;
++ struct w1_bus_master w1_bm;
++};
++
++struct ds2482_data {
++ struct i2c_client client;
++ struct semaphore access_lock;
++
++ /* 1-wire interface(s) */
++ int w1_count; /* 1 or 8 */
++ struct ds2482_w1_chan w1_ch[8];
++
++ /* per-device values */
++ u8 channel;
++ u8 read_prt; /* see DS2482_PTR_CODE_xxx */
++ u8 reg_config;
++};
++
++
++/**
++ * Sets the read pointer.
++ * @param pdev The ds2482 client pointer
++ * @param read_ptr see DS2482_PTR_CODE_xxx above
++ * @return -1 on failure, 0 on success
++ */
++static inline int ds2482_select_register(struct ds2482_data *pdev, u8 read_ptr)
++{
++ if (pdev->read_prt != read_ptr) {
++ if (i2c_smbus_write_byte_data(&pdev->client,
++ DS2482_CMD_SET_READ_PTR,
++ read_ptr) < 0)
++ return -1;
++
++ pdev->read_prt = read_ptr;
++ }
++ return 0;
++}
++
++/**
++ * Sends a command without a parameter
++ * @param pdev The ds2482 client pointer
++ * @param cmd DS2482_CMD_RESET,
++ * DS2482_CMD_1WIRE_RESET,
++ * DS2482_CMD_1WIRE_READ_BYTE
++ * @return -1 on failure, 0 on success
++ */
++static inline int ds2482_send_cmd(struct ds2482_data *pdev, u8 cmd)
++{
++ if (i2c_smbus_write_byte(&pdev->client, cmd) < 0)
++ return -1;
++
++ pdev->read_prt = DS2482_PTR_CODE_STATUS;
++ return 0;
++}
++
++/**
++ * Sends a command with a parameter
++ * @param pdev The ds2482 client pointer
++ * @param cmd DS2482_CMD_WRITE_CONFIG,
++ * DS2482_CMD_1WIRE_SINGLE_BIT,
++ * DS2482_CMD_1WIRE_WRITE_BYTE,
++ * DS2482_CMD_1WIRE_TRIPLET
++ * @param byte The data to send
++ * @return -1 on failure, 0 on success
++ */
++static inline int ds2482_send_cmd_data(struct ds2482_data *pdev,
++ u8 cmd, u8 byte)
++{
++ if (i2c_smbus_write_byte_data(&pdev->client, cmd, byte) < 0)
++ return -1;
++
++ /* all cmds leave in STATUS, except CONFIG */
++ pdev->read_prt = (cmd != DS2482_CMD_WRITE_CONFIG) ?
++ DS2482_PTR_CODE_STATUS : DS2482_PTR_CODE_CONFIG;
++ return 0;
++}
++
++
++/*
++ * 1-Wire interface code
++ */
++
++#define DS2482_WAIT_IDLE_TIMEOUT 100
++
++/**
++ * Waits until the 1-wire interface is idle (not busy)
++ *
++ * @param pdev Pointer to the device structure
++ * @return the last value read from status or -1 (failure)
++ */
++static int ds2482_wait_1wire_idle(struct ds2482_data *pdev)
++{
++ int temp = -1;
++ int retries = 0;
++
++ if (!ds2482_select_register(pdev, DS2482_PTR_CODE_STATUS)) {
++ do {
++ temp = i2c_smbus_read_byte(&pdev->client);
++ } while ((temp >= 0) && (temp & DS2482_REG_STS_1WB) &&
++ (++retries > DS2482_WAIT_IDLE_TIMEOUT));
++ }
++
++ if (retries > DS2482_WAIT_IDLE_TIMEOUT)
++ printk(KERN_ERR "%s: timeout on channel %d\n",
++ __func__, pdev->channel);
++
++ return temp;
++}
++
++/**
++ * Selects a w1 channel.
++ * The 1-wire interface must be idle before calling this function.
++ *
++ * @param pdev The ds2482 client pointer
++ * @param channel 0-7
++ * @return -1 (failure) or 0 (success)
++ */
++static int ds2482_set_channel(struct ds2482_data *pdev, u8 channel)
++{
++ if (i2c_smbus_write_byte_data(&pdev->client, DS2482_CMD_CHANNEL_SELECT,
++ ds2482_chan_wr[channel]) < 0)
++ return -1;
++
++ pdev->read_prt = DS2482_PTR_CODE_CHANNEL;
++ pdev->channel = -1;
++ if (i2c_smbus_read_byte(&pdev->client) == ds2482_chan_rd[channel]) {
++ pdev->channel = channel;
++ return 0;
++ }
++ return -1;
++}
++
++
++/**
++ * Performs the touch-bit function, which writes a 0 or 1 and reads the level.
++ *
++ * @param data The ds2482 channel pointer
++ * @param bit The level to write: 0 or non-zero
++ * @return The level read: 0 or 1
++ */
++static u8 ds2482_w1_touch_bit(void *data, u8 bit)
++{
++ struct ds2482_w1_chan *pchan = data;
++ struct ds2482_data *pdev = pchan->pdev;
++ int status = -1;
++
++ down(&pdev->access_lock);
++
++ /* Select the channel */
++ ds2482_wait_1wire_idle(pdev);
++ if (pdev->w1_count > 1)
++ ds2482_set_channel(pdev, pchan->channel);
++
++ /* Send the touch command, wait until 1WB == 0, return the status */
++ if (!ds2482_send_cmd_data(pdev, DS2482_CMD_1WIRE_SINGLE_BIT,
++ bit ? 0xFF : 0))
++ status = ds2482_wait_1wire_idle(pdev);
++
++ up(&pdev->access_lock);
++
++ return (status & DS2482_REG_STS_SBR) ? 1 : 0;
++}
++
++/**
++ * Performs the triplet function, which reads two bits and writes a bit.
++ * The bit written is determined by the two reads:
++ * 00 => dbit, 01 => 0, 10 => 1
++ *
++ * @param data The ds2482 channel pointer
++ * @param dbit The direction to choose if both branches are valid
++ * @return b0=read1 b1=read2 b3=bit written
++ */
++static u8 ds2482_w1_triplet(void *data, u8 dbit)
++{
++ struct ds2482_w1_chan *pchan = data;
++ struct ds2482_data *pdev = pchan->pdev;
++ int status = (3 << 5);
++
++ down(&pdev->access_lock);
++
++ /* Select the channel */
++ ds2482_wait_1wire_idle(pdev);
++ if (pdev->w1_count > 1)
++ ds2482_set_channel(pdev, pchan->channel);
++
++ /* Send the triplet command, wait until 1WB == 0, return the status */
++ if (!ds2482_send_cmd_data(pdev, DS2482_CMD_1WIRE_TRIPLET,
++ dbit ? 0xFF : 0))
++ status = ds2482_wait_1wire_idle(pdev);
++
++ up(&pdev->access_lock);
++
++ /* Decode the status */
++ return (status >> 5);
++}
++
++/**
++ * Performs the write byte function.
++ *
++ * @param data The ds2482 channel pointer
++ * @param byte The value to write
++ */
++static void ds2482_w1_write_byte(void *data, u8 byte)
++{
++ struct ds2482_w1_chan *pchan = data;
++ struct ds2482_data *pdev = pchan->pdev;
++
++ down(&pdev->access_lock);
++
++ /* Select the channel */
++ ds2482_wait_1wire_idle(pdev);
++ if (pdev->w1_count > 1)
++ ds2482_set_channel(pdev, pchan->channel);
++
++ /* Send the write byte command */
++ ds2482_send_cmd_data(pdev, DS2482_CMD_1WIRE_WRITE_BYTE, byte);
++
++ up(&pdev->access_lock);
++}
++
++/**
++ * Performs the read byte function.
++ *
++ * @param data The ds2482 channel pointer
++ * @return The value read
++ */
++static u8 ds2482_w1_read_byte(void *data)
++{
++ struct ds2482_w1_chan *pchan = data;
++ struct ds2482_data *pdev = pchan->pdev;
++ int result;
++
++ down(&pdev->access_lock);
++
++ /* Select the channel */
++ ds2482_wait_1wire_idle(pdev);
++ if (pdev->w1_count > 1)
++ ds2482_set_channel(pdev, pchan->channel);
++
++ /* Send the read byte command */
++ ds2482_send_cmd(pdev, DS2482_CMD_1WIRE_READ_BYTE);
++
++ /* Wait until 1WB == 0 */
++ ds2482_wait_1wire_idle(pdev);
++
++ /* Select the data register */
++ ds2482_select_register(pdev, DS2482_PTR_CODE_DATA);
++
++ /* Read the data byte */
++ result = i2c_smbus_read_byte(&pdev->client);
++
++ up(&pdev->access_lock);
++
++ return result;
++}
++
++
++/**
++ * Sends a reset on the 1-wire interface
++ *
++ * @param data The ds2482 channel pointer
++ * @return 0=Device present, 1=No device present or error
++ */
++static u8 ds2482_w1_reset_bus(void *data)
++{
++ struct ds2482_w1_chan *pchan = data;
++ struct ds2482_data *pdev = pchan->pdev;
++ int err;
++ u8 retval = 1;
++
++ down(&pdev->access_lock);
++
++ /* Select the channel */
++ ds2482_wait_1wire_idle(pdev);
++ if (pdev->w1_count > 1)
++ ds2482_set_channel(pdev, pchan->channel);
++
++ /* Send the reset command */
++ err = ds2482_send_cmd(pdev, DS2482_CMD_1WIRE_RESET);
++ if (err >= 0) {
++ /* Wait until the reset is complete */
++ err = ds2482_wait_1wire_idle(pdev);
++ retval = !(err & DS2482_REG_STS_PPD);
++
++ /* If the chip did reset since detect, re-config it */
++ if (err & DS2482_REG_STS_RST)
++ ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG,
++ 0xF0);
++ }
++
++ up(&pdev->access_lock);
++
++ return retval;
++}
++
++
++/**
++ * Called to see if the device exists on an i2c bus.
++ */
++static int ds2482_attach_adapter(struct i2c_adapter *adapter)
++{
++ return i2c_probe(adapter, &addr_data, ds2482_detect);
++}
++
++
++/*
++ * The following function does more than just detection. If detection
++ * succeeds, it also registers the new chip.
++ */
++static int ds2482_detect(struct i2c_adapter *adapter, int address, int kind)
++{
++ struct ds2482_data *data;
++ struct i2c_client *new_client;
++ int err = 0;
++ int temp1;
++ int idx;
++
++ if (!i2c_check_functionality(adapter,
++ I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
++ I2C_FUNC_SMBUS_BYTE))
++ goto exit;
++
++ if (!(data = kzalloc(sizeof(struct ds2482_data), GFP_KERNEL))) {
++ err = -ENOMEM;
++ goto exit;
++ }
++
++ new_client = &data->client;
++ i2c_set_clientdata(new_client, data);
++ new_client->addr = address;
++ new_client->driver = &ds2482_driver;
++ new_client->adapter = adapter;
++
++ /* Reset the device (sets the read_ptr to status) */
++ if (ds2482_send_cmd(data, DS2482_CMD_RESET) < 0) {
++ dev_dbg(&adapter->dev, "DS2482 reset failed at 0x%02x.\n",
++ address);
++ goto exit_free;
++ }
++
++ /* Sleep at least 525ns to allow the reset to complete */
++ ndelay(525);
++
++ /* Read the status byte - only reset bit and line should be set */
++ temp1 = i2c_smbus_read_byte(new_client);
++ if (temp1 != (DS2482_REG_STS_LL | DS2482_REG_STS_RST)) {
++ dev_dbg(&adapter->dev, "DS2482 (0x%02x) reset status "
++ "0x%02X - not a DS2482\n", address, temp1);
++ goto exit_free;
++ }
++
++ /* Detect the 8-port version */
++ data->w1_count = 1;
++ if (ds2482_set_channel(data, 7) == 0)
++ data->w1_count = 8;
++
++ /* Set all config items to 0 (off) */
++ ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, 0xF0);
++
++ /* We can fill in the remaining client fields */
++ snprintf(new_client->name, sizeof(new_client->name), "ds2482-%d00",
++ data->w1_count);
++
++ init_MUTEX(&data->access_lock);
++
++ /* Tell the I2C layer a new client has arrived */
++ if ((err = i2c_attach_client(new_client)))
++ goto exit_free;
++
++ /* Register 1-wire interface(s) */
++ for (idx = 0; idx < data->w1_count; idx++) {
++ data->w1_ch[idx].pdev = data;
++ data->w1_ch[idx].channel = idx;
++
++ /* Populate all the w1 bus master stuff */
++ data->w1_ch[idx].w1_bm.data = &data->w1_ch[idx];
++ data->w1_ch[idx].w1_bm.read_byte = ds2482_w1_read_byte;
++ data->w1_ch[idx].w1_bm.write_byte = ds2482_w1_write_byte;
++ data->w1_ch[idx].w1_bm.touch_bit = ds2482_w1_touch_bit;
++ data->w1_ch[idx].w1_bm.triplet = ds2482_w1_triplet;
++ data->w1_ch[idx].w1_bm.reset_bus = ds2482_w1_reset_bus;
++
++ err = w1_add_master_device(&data->w1_ch[idx].w1_bm);
++ if (err) {
++ data->w1_ch[idx].pdev = NULL;
++ goto exit_w1_remove;
++ }
++ }
++
++ return 0;
++
++exit_w1_remove:
++ i2c_detach_client(new_client);
++
++ for (idx = 0; idx < data->w1_count; idx++) {
++ if (data->w1_ch[idx].pdev != NULL)
++ w1_remove_master_device(&data->w1_ch[idx].w1_bm);
++ }
++exit_free:
++ kfree(data);
++exit:
++ return err;
++}
++
++static int ds2482_detach_client(struct i2c_client *client)
++{
++ struct ds2482_data *data = i2c_get_clientdata(client);
++ int err, idx;
++
++ /* Unregister the 1-wire bridge(s) */
++ for (idx = 0; idx < data->w1_count; idx++) {
++ if (data->w1_ch[idx].pdev != NULL)
++ w1_remove_master_device(&data->w1_ch[idx].w1_bm);
++ }
++
++ /* Detach the i2c device */
++ if ((err = i2c_detach_client(client))) {
++ dev_err(&client->dev,
++ "Deregistration failed, client not detached.\n");
++ return err;
++ }
++
++ /* Free the memory */
++ kfree(data);
++ return 0;
++}
++
++static int __init sensors_ds2482_init(void)
++{
++ return i2c_add_driver(&ds2482_driver);
++}
++
++static void __exit sensors_ds2482_exit(void)
++{
++ i2c_del_driver(&ds2482_driver);
++}
++
++MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
++MODULE_DESCRIPTION("DS2482 driver");
++MODULE_LICENSE("GPL");
++
++module_init(sensors_ds2482_init);
++module_exit(sensors_ds2482_exit);
diff --git a/i2c/w1-change-the-type-unsigned-long-member-of-struct-w1_bus_master-to-void.patch b/i2c/w1-change-the-type-unsigned-long-member-of-struct-w1_bus_master-to-void.patch
new file mode 100644
index 00000000000000..f55d626d39dc96
--- /dev/null
+++ b/i2c/w1-change-the-type-unsigned-long-member-of-struct-w1_bus_master-to-void.patch
@@ -0,0 +1,279 @@
+From johnpol@2ka.mipt.ru Tue Dec 6 02:32:24 2005
+From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Cc: Ben Gardner <gardner.ben@gmail.com>, Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Subject: W1: Change the type 'unsigned long' member of 'struct w1_bus_master' to 'void *'.
+Date: Tue, 6 Dec 2005 13:38:27 +0300
+Message-Id: <11338655072468@2ka.mipt.ru>
+To: GregKH <greg@kroah.com>
+
+
+Signed-off-by: Ben Gardner <bgardner@wabtec.com>
+Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/w1/ds_w1_bridge.c | 34 +++++++++++++++++-----------------
+ drivers/w1/matrox_w1.c | 14 +++++++-------
+ drivers/w1/w1.c | 8 ++++----
+ drivers/w1/w1.h | 24 ++++++++++++------------
+ 4 files changed, 40 insertions(+), 40 deletions(-)
+
+--- gregkh-2.6.orig/drivers/w1/ds_w1_bridge.c
++++ gregkh-2.6/drivers/w1/ds_w1_bridge.c
+@@ -29,10 +29,10 @@
+ static struct ds_device *ds_dev;
+ static struct w1_bus_master *ds_bus_master;
+
+-static u8 ds9490r_touch_bit(unsigned long data, u8 bit)
++static u8 ds9490r_touch_bit(void *data, u8 bit)
+ {
+ u8 ret;
+- struct ds_device *dev = (struct ds_device *)data;
++ struct ds_device *dev = data;
+
+ if (ds_touch_bit(dev, bit, &ret))
+ return 0;
+@@ -40,23 +40,23 @@ static u8 ds9490r_touch_bit(unsigned lon
+ return ret;
+ }
+
+-static void ds9490r_write_bit(unsigned long data, u8 bit)
++static void ds9490r_write_bit(void *data, u8 bit)
+ {
+- struct ds_device *dev = (struct ds_device *)data;
++ struct ds_device *dev = data;
+
+ ds_write_bit(dev, bit);
+ }
+
+-static void ds9490r_write_byte(unsigned long data, u8 byte)
++static void ds9490r_write_byte(void *data, u8 byte)
+ {
+- struct ds_device *dev = (struct ds_device *)data;
++ struct ds_device *dev = data;
+
+ ds_write_byte(dev, byte);
+ }
+
+-static u8 ds9490r_read_bit(unsigned long data)
++static u8 ds9490r_read_bit(void *data)
+ {
+- struct ds_device *dev = (struct ds_device *)data;
++ struct ds_device *dev = data;
+ int err;
+ u8 bit = 0;
+
+@@ -70,9 +70,9 @@ static u8 ds9490r_read_bit(unsigned long
+ return bit & 1;
+ }
+
+-static u8 ds9490r_read_byte(unsigned long data)
++static u8 ds9490r_read_byte(void *data)
+ {
+- struct ds_device *dev = (struct ds_device *)data;
++ struct ds_device *dev = data;
+ int err;
+ u8 byte = 0;
+
+@@ -83,16 +83,16 @@ static u8 ds9490r_read_byte(unsigned lon
+ return byte;
+ }
+
+-static void ds9490r_write_block(unsigned long data, const u8 *buf, int len)
++static void ds9490r_write_block(void *data, const u8 *buf, int len)
+ {
+- struct ds_device *dev = (struct ds_device *)data;
++ struct ds_device *dev = data;
+
+ ds_write_block(dev, (u8 *)buf, len);
+ }
+
+-static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len)
++static u8 ds9490r_read_block(void *data, u8 *buf, int len)
+ {
+- struct ds_device *dev = (struct ds_device *)data;
++ struct ds_device *dev = data;
+ int err;
+
+ err = ds_read_block(dev, buf, len);
+@@ -102,9 +102,9 @@ static u8 ds9490r_read_block(unsigned lo
+ return len;
+ }
+
+-static u8 ds9490r_reset(unsigned long data)
++static u8 ds9490r_reset(void *data)
+ {
+- struct ds_device *dev = (struct ds_device *)data;
++ struct ds_device *dev = data;
+ struct ds_status st;
+ int err;
+
+@@ -136,7 +136,7 @@ static int __devinit ds_w1_init(void)
+
+ memset(ds_bus_master, 0, sizeof(*ds_bus_master));
+
+- ds_bus_master->data = (unsigned long)ds_dev;
++ ds_bus_master->data = ds_dev;
+ ds_bus_master->touch_bit = &ds9490r_touch_bit;
+ ds_bus_master->read_bit = &ds9490r_read_bit;
+ ds_bus_master->write_bit = &ds9490r_write_bit;
+--- gregkh-2.6.orig/drivers/w1/matrox_w1.c
++++ gregkh-2.6/drivers/w1/matrox_w1.c
+@@ -90,8 +90,8 @@ struct matrox_device
+ struct w1_bus_master *bus_master;
+ };
+
+-static u8 matrox_w1_read_ddc_bit(unsigned long);
+-static void matrox_w1_write_ddc_bit(unsigned long, u8);
++static u8 matrox_w1_read_ddc_bit(void *);
++static void matrox_w1_write_ddc_bit(void *, u8);
+
+ /*
+ * These functions read and write DDC Data bit.
+@@ -122,10 +122,10 @@ static __inline__ void matrox_w1_write_r
+ wmb();
+ }
+
+-static void matrox_w1_write_ddc_bit(unsigned long data, u8 bit)
++static void matrox_w1_write_ddc_bit(void *data, u8 bit)
+ {
+ u8 ret;
+- struct matrox_device *dev = (struct matrox_device *) data;
++ struct matrox_device *dev = data;
+
+ if (bit)
+ bit = 0;
+@@ -137,10 +137,10 @@ static void matrox_w1_write_ddc_bit(unsi
+ matrox_w1_write_reg(dev, MATROX_GET_DATA, 0x00);
+ }
+
+-static u8 matrox_w1_read_ddc_bit(unsigned long data)
++static u8 matrox_w1_read_ddc_bit(void *data)
+ {
+ u8 ret;
+- struct matrox_device *dev = (struct matrox_device *) data;
++ struct matrox_device *dev = data;
+
+ ret = matrox_w1_read_reg(dev, MATROX_GET_DATA);
+
+@@ -198,7 +198,7 @@ static int __devinit matrox_w1_probe(str
+
+ matrox_w1_hw_init(dev);
+
+- dev->bus_master->data = (unsigned long) dev;
++ dev->bus_master->data = dev;
+ dev->bus_master->read_bit = &matrox_w1_read_ddc_bit;
+ dev->bus_master->write_bit = &matrox_w1_write_ddc_bit;
+
+--- gregkh-2.6.orig/drivers/w1/w1.c
++++ gregkh-2.6/drivers/w1/w1.c
+@@ -552,7 +552,7 @@ static void w1_slave_detach(struct w1_sl
+ kfree(sl);
+ }
+
+-static struct w1_master *w1_search_master(unsigned long data)
++static struct w1_master *w1_search_master(void *data)
+ {
+ struct w1_master *dev;
+ int found = 0;
+@@ -583,7 +583,7 @@ void w1_reconnect_slaves(struct w1_famil
+ spin_unlock_bh(&w1_mlock);
+ }
+
+-static void w1_slave_found(unsigned long data, u64 rn)
++static void w1_slave_found(void *data, u64 rn)
+ {
+ int slave_count;
+ struct w1_slave *sl;
+@@ -595,8 +595,8 @@ static void w1_slave_found(unsigned long
+
+ dev = w1_search_master(data);
+ if (!dev) {
+- printk(KERN_ERR "Failed to find w1 master device for data %08lx, it is impossible.\n",
+- data);
++ printk(KERN_ERR "Failed to find w1 master device for data %p, "
++ "it is impossible.\n", data);
+ return;
+ }
+
+--- gregkh-2.6.orig/drivers/w1/w1.h
++++ gregkh-2.6/drivers/w1/w1.h
+@@ -80,7 +80,7 @@ struct w1_slave
+ struct completion released;
+ };
+
+-typedef void (* w1_slave_found_callback)(unsigned long, u64);
++typedef void (* w1_slave_found_callback)(void *, u64);
+
+
+ /**
+@@ -93,16 +93,16 @@ typedef void (* w1_slave_found_callback)
+ struct w1_bus_master
+ {
+ /** the first parameter in all the functions below */
+- unsigned long data;
++ void *data;
+
+ /**
+ * Sample the line level
+ * @return the level read (0 or 1)
+ */
+- u8 (*read_bit)(unsigned long);
++ u8 (*read_bit)(void *);
+
+ /** Sets the line level */
+- void (*write_bit)(unsigned long, u8);
++ void (*write_bit)(void *, u8);
+
+ /**
+ * touch_bit is the lowest-level function for devices that really
+@@ -111,42 +111,42 @@ struct w1_bus_master
+ * touch_bit(1) = write-1 / read cycle
+ * @return the bit read (0 or 1)
+ */
+- u8 (*touch_bit)(unsigned long, u8);
++ u8 (*touch_bit)(void *, u8);
+
+ /**
+ * Reads a bytes. Same as 8 touch_bit(1) calls.
+ * @return the byte read
+ */
+- u8 (*read_byte)(unsigned long);
++ u8 (*read_byte)(void *);
+
+ /**
+ * Writes a byte. Same as 8 touch_bit(x) calls.
+ */
+- void (*write_byte)(unsigned long, u8);
++ void (*write_byte)(void *, u8);
+
+ /**
+ * Same as a series of read_byte() calls
+ * @return the number of bytes read
+ */
+- u8 (*read_block)(unsigned long, u8 *, int);
++ u8 (*read_block)(void *, u8 *, int);
+
+ /** Same as a series of write_byte() calls */
+- void (*write_block)(unsigned long, const u8 *, int);
++ void (*write_block)(void *, const u8 *, int);
+
+ /**
+ * Combines two reads and a smart write for ROM searches
+ * @return bit0=Id bit1=comp_id bit2=dir_taken
+ */
+- u8 (*triplet)(unsigned long, u8);
++ u8 (*triplet)(void *, u8);
+
+ /**
+ * long write-0 with a read for the presence pulse detection
+ * @return -1=Error, 0=Device present, 1=No device present
+ */
+- u8 (*reset_bus)(unsigned long);
++ u8 (*reset_bus)(void *);
+
+ /** Really nice hardware can handles the ROM searches */
+- void (*search)(unsigned long, w1_slave_found_callback);
++ void (*search)(void *, w1_slave_found_callback);
+ };
+
+ #define W1_MASTER_NEED_EXIT 0
diff --git a/i2c/w1-move-w1-bus-master-code-into-w1-masters-and-move-w1-slave-code-into-w1-slaves.patch b/i2c/w1-move-w1-bus-master-code-into-w1-masters-and-move-w1-slave-code-into-w1-slaves.patch
new file mode 100644
index 00000000000000..3b93c3962637e2
--- /dev/null
+++ b/i2c/w1-move-w1-bus-master-code-into-w1-masters-and-move-w1-slave-code-into-w1-slaves.patch
@@ -0,0 +1,4374 @@
+From johnpol@2ka.mipt.ru Tue Dec 6 02:32:34 2005
+From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Subject: W1: Move w1 bus master code into 'w1/masters' and move w1 slave code into 'w1/slaves'
+Date: Tue, 6 Dec 2005 13:38:28 +0300
+Message-Id: <11338655084139@2ka.mipt.ru>
+To: GregKH <greg@kroah.com>
+Cc: Ben Gardner <gardner.ben@gmail.com>, Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+
+
+Signed-off-by: Ben Gardner <bgardner@wabtec.com>
+Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/w1/Kconfig | 60 --
+ drivers/w1/Makefile | 10
+ drivers/w1/ds_w1_bridge.c | 174 --------
+ drivers/w1/dscore.c | 796 --------------------------------------
+ drivers/w1/dscore.h | 166 -------
+ drivers/w1/masters/Kconfig | 38 +
+ drivers/w1/masters/Makefile | 11
+ drivers/w1/masters/ds_w1_bridge.c | 174 ++++++++
+ drivers/w1/masters/dscore.c | 795 +++++++++++++++++++++++++++++++++++++
+ drivers/w1/masters/dscore.h | 166 +++++++
+ drivers/w1/masters/matrox_w1.c | 247 +++++++++++
+ drivers/w1/matrox_w1.c | 247 -----------
+ drivers/w1/slaves/Kconfig | 38 +
+ drivers/w1/slaves/Makefile | 12
+ drivers/w1/slaves/w1_ds2433.c | 329 +++++++++++++++
+ drivers/w1/slaves/w1_smem.c | 71 +++
+ drivers/w1/slaves/w1_therm.c | 268 ++++++++++++
+ drivers/w1/w1_ds2433.c | 329 ---------------
+ drivers/w1/w1_smem.c | 71 ---
+ drivers/w1/w1_therm.c | 268 ------------
+ 20 files changed, 2152 insertions(+), 2118 deletions(-)
+
+--- gregkh-2.6.orig/drivers/w1/Kconfig
++++ gregkh-2.6/drivers/w1/Kconfig
+@@ -11,63 +11,7 @@ config W1
+ This W1 support can also be built as a module. If so, the module
+ will be called wire.ko.
+
+-config W1_MATROX
+- tristate "Matrox G400 transport layer for 1-wire"
+- depends on W1 && PCI
+- help
+- Say Y here if you want to communicate with your 1-wire devices
+- using Matrox's G400 GPIO pins.
+-
+- This support is also available as a module. If so, the module
+- will be called matrox_w1.ko.
+-
+-config W1_DS9490
+- tristate "DS9490R transport layer driver"
+- depends on W1 && USB
+- help
+- Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge.
+-
+- This support is also available as a module. If so, the module
+- will be called ds9490r.ko.
+-
+-config W1_DS9490_BRIDGE
+- tristate "DS9490R USB <-> W1 transport layer for 1-wire"
+- depends on W1_DS9490
+- help
+- Say Y here if you want to communicate with your 1-wire devices
+- using DS9490R USB bridge.
+-
+- This support is also available as a module. If so, the module
+- will be called ds_w1_bridge.ko.
+-
+-config W1_THERM
+- tristate "Thermal family implementation"
+- depends on W1
+- help
+- Say Y here if you want to connect 1-wire thermal sensors to you
+- wire.
+-
+-config W1_SMEM
+- tristate "Simple 64bit memory family implementation"
+- depends on W1
+- help
+- Say Y here if you want to connect 1-wire
+- simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
+-
+-config W1_DS2433
+- tristate "4kb EEPROM family support (DS2433)"
+- depends on W1
+- help
+- Say Y here if you want to use a 1-wire
+- 4kb EEPROM family device (DS2433).
+-
+-config W1_DS2433_CRC
+- bool "Protect DS2433 data with a CRC16"
+- depends on W1_DS2433
+- select CRC16
+- help
+- Say Y here to protect DS2433 data with a CRC16.
+- Each block has 30 bytes of data and a two byte CRC16.
+- Full block writes are only allowed if the CRC is valid.
++source drivers/w1/masters/Kconfig
++source drivers/w1/slaves/Kconfig
+
+ endmenu
+--- gregkh-2.6.orig/drivers/w1/Makefile
++++ gregkh-2.6/drivers/w1/Makefile
+@@ -13,13 +13,5 @@ endif
+ obj-$(CONFIG_W1) += wire.o
+ wire-objs := w1.o w1_int.o w1_family.o w1_netlink.o w1_io.o
+
+-obj-$(CONFIG_W1_MATROX) += matrox_w1.o
+-obj-$(CONFIG_W1_THERM) += w1_therm.o
+-obj-$(CONFIG_W1_SMEM) += w1_smem.o
++obj-y += masters/ slaves/
+
+-obj-$(CONFIG_W1_DS9490) += ds9490r.o
+-ds9490r-objs := dscore.o
+-
+-obj-$(CONFIG_W1_DS9490_BRIDGE) += ds_w1_bridge.o
+-
+-obj-$(CONFIG_W1_DS2433) += w1_ds2433.o
+--- gregkh-2.6.orig/drivers/w1/ds_w1_bridge.c
++++ /dev/null
+@@ -1,174 +0,0 @@
+-/*
+- * ds_w1_bridge.c
+- *
+- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+- *
+- *
+- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#include <linux/module.h>
+-#include <linux/types.h>
+-
+-#include "../w1/w1.h"
+-#include "../w1/w1_int.h"
+-#include "dscore.h"
+-
+-static struct ds_device *ds_dev;
+-static struct w1_bus_master *ds_bus_master;
+-
+-static u8 ds9490r_touch_bit(void *data, u8 bit)
+-{
+- u8 ret;
+- struct ds_device *dev = data;
+-
+- if (ds_touch_bit(dev, bit, &ret))
+- return 0;
+-
+- return ret;
+-}
+-
+-static void ds9490r_write_bit(void *data, u8 bit)
+-{
+- struct ds_device *dev = data;
+-
+- ds_write_bit(dev, bit);
+-}
+-
+-static void ds9490r_write_byte(void *data, u8 byte)
+-{
+- struct ds_device *dev = data;
+-
+- ds_write_byte(dev, byte);
+-}
+-
+-static u8 ds9490r_read_bit(void *data)
+-{
+- struct ds_device *dev = data;
+- int err;
+- u8 bit = 0;
+-
+- err = ds_touch_bit(dev, 1, &bit);
+- if (err)
+- return 0;
+- //err = ds_read_bit(dev, &bit);
+- //if (err)
+- // return 0;
+-
+- return bit & 1;
+-}
+-
+-static u8 ds9490r_read_byte(void *data)
+-{
+- struct ds_device *dev = data;
+- int err;
+- u8 byte = 0;
+-
+- err = ds_read_byte(dev, &byte);
+- if (err)
+- return 0;
+-
+- return byte;
+-}
+-
+-static void ds9490r_write_block(void *data, const u8 *buf, int len)
+-{
+- struct ds_device *dev = data;
+-
+- ds_write_block(dev, (u8 *)buf, len);
+-}
+-
+-static u8 ds9490r_read_block(void *data, u8 *buf, int len)
+-{
+- struct ds_device *dev = data;
+- int err;
+-
+- err = ds_read_block(dev, buf, len);
+- if (err < 0)
+- return 0;
+-
+- return len;
+-}
+-
+-static u8 ds9490r_reset(void *data)
+-{
+- struct ds_device *dev = data;
+- struct ds_status st;
+- int err;
+-
+- memset(&st, 0, sizeof(st));
+-
+- err = ds_reset(dev, &st);
+- if (err)
+- return 1;
+-
+- return 0;
+-}
+-
+-static int __devinit ds_w1_init(void)
+-{
+- int err;
+-
+- ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL);
+- if (!ds_bus_master) {
+- printk(KERN_ERR "Failed to allocate DS9490R USB<->W1 bus_master structure.\n");
+- return -ENOMEM;
+- }
+-
+- ds_dev = ds_get_device();
+- if (!ds_dev) {
+- printk(KERN_ERR "DS9490R is not registered.\n");
+- err = -ENODEV;
+- goto err_out_free_bus_master;
+- }
+-
+- memset(ds_bus_master, 0, sizeof(*ds_bus_master));
+-
+- ds_bus_master->data = ds_dev;
+- ds_bus_master->touch_bit = &ds9490r_touch_bit;
+- ds_bus_master->read_bit = &ds9490r_read_bit;
+- ds_bus_master->write_bit = &ds9490r_write_bit;
+- ds_bus_master->read_byte = &ds9490r_read_byte;
+- ds_bus_master->write_byte = &ds9490r_write_byte;
+- ds_bus_master->read_block = &ds9490r_read_block;
+- ds_bus_master->write_block = &ds9490r_write_block;
+- ds_bus_master->reset_bus = &ds9490r_reset;
+-
+- err = w1_add_master_device(ds_bus_master);
+- if (err)
+- goto err_out_put_device;
+-
+- return 0;
+-
+-err_out_put_device:
+- ds_put_device(ds_dev);
+-err_out_free_bus_master:
+- kfree(ds_bus_master);
+-
+- return err;
+-}
+-
+-static void __devexit ds_w1_fini(void)
+-{
+- w1_remove_master_device(ds_bus_master);
+- ds_put_device(ds_dev);
+- kfree(ds_bus_master);
+-}
+-
+-module_init(ds_w1_init);
+-module_exit(ds_w1_fini);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+--- gregkh-2.6.orig/drivers/w1/dscore.c
++++ /dev/null
+@@ -1,796 +0,0 @@
+-/*
+- * dscore.c
+- *
+- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+- *
+- *
+- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/mod_devicetable.h>
+-#include <linux/usb.h>
+-
+-#include "dscore.h"
+-
+-static struct usb_device_id ds_id_table [] = {
+- { USB_DEVICE(0x04fa, 0x2490) },
+- { },
+-};
+-MODULE_DEVICE_TABLE(usb, ds_id_table);
+-
+-static int ds_probe(struct usb_interface *, const struct usb_device_id *);
+-static void ds_disconnect(struct usb_interface *);
+-
+-int ds_touch_bit(struct ds_device *, u8, u8 *);
+-int ds_read_byte(struct ds_device *, u8 *);
+-int ds_read_bit(struct ds_device *, u8 *);
+-int ds_write_byte(struct ds_device *, u8);
+-int ds_write_bit(struct ds_device *, u8);
+-static int ds_start_pulse(struct ds_device *, int);
+-int ds_reset(struct ds_device *, struct ds_status *);
+-struct ds_device * ds_get_device(void);
+-void ds_put_device(struct ds_device *);
+-
+-static inline void ds_dump_status(unsigned char *, unsigned char *, int);
+-static int ds_send_control(struct ds_device *, u16, u16);
+-static int ds_send_control_mode(struct ds_device *, u16, u16);
+-static int ds_send_control_cmd(struct ds_device *, u16, u16);
+-
+-
+-static struct usb_driver ds_driver = {
+- .owner = THIS_MODULE,
+- .name = "DS9490R",
+- .probe = ds_probe,
+- .disconnect = ds_disconnect,
+- .id_table = ds_id_table,
+-};
+-
+-static struct ds_device *ds_dev;
+-
+-struct ds_device * ds_get_device(void)
+-{
+- if (ds_dev)
+- atomic_inc(&ds_dev->refcnt);
+- return ds_dev;
+-}
+-
+-void ds_put_device(struct ds_device *dev)
+-{
+- atomic_dec(&dev->refcnt);
+-}
+-
+-static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
+-{
+- int err;
+-
+- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+- CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
+- if (err < 0) {
+- printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
+- value, index, err);
+- return err;
+- }
+-
+- return err;
+-}
+-
+-static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
+-{
+- int err;
+-
+- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+- MODE_CMD, 0x40, value, index, NULL, 0, 1000);
+- if (err < 0) {
+- printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
+- value, index, err);
+- return err;
+- }
+-
+- return err;
+-}
+-
+-static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
+-{
+- int err;
+-
+- err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+- COMM_CMD, 0x40, value, index, NULL, 0, 1000);
+- if (err < 0) {
+- printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
+- value, index, err);
+- return err;
+- }
+-
+- return err;
+-}
+-
+-static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
+-{
+- printk("%45s: %8x\n", str, buf[off]);
+-}
+-
+-static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
+- unsigned char *buf, int size)
+-{
+- int count, err;
+-
+- memset(st, 0, sizeof(st));
+-
+- count = 0;
+- err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
+- if (err < 0) {
+- printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
+- return err;
+- }
+-
+- if (count >= sizeof(*st))
+- memcpy(st, buf, sizeof(*st));
+-
+- return count;
+-}
+-
+-static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
+-{
+- unsigned char buf[64];
+- int count, err = 0, i;
+-
+- memcpy(st, buf, sizeof(*st));
+-
+- count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+- if (count < 0)
+- return err;
+-
+- printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
+- for (i=0; i<count; ++i)
+- printk("%02x ", buf[i]);
+- printk("\n");
+-
+- if (count >= 16) {
+- ds_dump_status(buf, "enable flag", 0);
+- ds_dump_status(buf, "1-wire speed", 1);
+- ds_dump_status(buf, "strong pullup duration", 2);
+- ds_dump_status(buf, "programming pulse duration", 3);
+- ds_dump_status(buf, "pulldown slew rate control", 4);
+- ds_dump_status(buf, "write-1 low time", 5);
+- ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
+- ds_dump_status(buf, "reserved (test register)", 7);
+- ds_dump_status(buf, "device status flags", 8);
+- ds_dump_status(buf, "communication command byte 1", 9);
+- ds_dump_status(buf, "communication command byte 2", 10);
+- ds_dump_status(buf, "communication command buffer status", 11);
+- ds_dump_status(buf, "1-wire data output buffer status", 12);
+- ds_dump_status(buf, "1-wire data input buffer status", 13);
+- ds_dump_status(buf, "reserved", 14);
+- ds_dump_status(buf, "reserved", 15);
+- }
+-
+- memcpy(st, buf, sizeof(*st));
+-
+- if (st->status & ST_EPOF) {
+- printk(KERN_INFO "Resetting device after ST_EPOF.\n");
+- err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+- if (err)
+- return err;
+- count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+- if (count < 0)
+- return err;
+- }
+-#if 0
+- if (st->status & ST_IDLE) {
+- printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
+- err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+- if (err)
+- return err;
+- }
+-#endif
+-
+- return err;
+-}
+-
+-static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
+-{
+- int count, err;
+- struct ds_status st;
+-
+- count = 0;
+- err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
+- buf, size, &count, 1000);
+- if (err < 0) {
+- printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
+- usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
+- ds_recv_status(dev, &st);
+- return err;
+- }
+-
+-#if 0
+- {
+- int i;
+-
+- printk("%s: count=%d: ", __func__, count);
+- for (i=0; i<count; ++i)
+- printk("%02x ", buf[i]);
+- printk("\n");
+- }
+-#endif
+- return count;
+-}
+-
+-static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
+-{
+- int count, err;
+-
+- count = 0;
+- err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
+- if (err < 0) {
+- printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
+- return err;
+- }
+-
+- return err;
+-}
+-
+-#if 0
+-
+-int ds_stop_pulse(struct ds_device *dev, int limit)
+-{
+- struct ds_status st;
+- int count = 0, err = 0;
+- u8 buf[0x20];
+-
+- do {
+- err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
+- if (err)
+- break;
+- err = ds_send_control(dev, CTL_RESUME_EXE, 0);
+- if (err)
+- break;
+- err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
+- if (err)
+- break;
+-
+- if ((st.status & ST_SPUA) == 0) {
+- err = ds_send_control_mode(dev, MOD_PULSE_EN, 0);
+- if (err)
+- break;
+- }
+- } while(++count < limit);
+-
+- return err;
+-}
+-
+-int ds_detect(struct ds_device *dev, struct ds_status *st)
+-{
+- int err;
+-
+- err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+- if (err)
+- return err;
+-
+- err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
+- if (err)
+- return err;
+-
+- err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
+- if (err)
+- return err;
+-
+- err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
+- if (err)
+- return err;
+-
+- err = ds_recv_status(dev, st);
+-
+- return err;
+-}
+-
+-#endif /* 0 */
+-
+-static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
+-{
+- u8 buf[0x20];
+- int err, count = 0;
+-
+- do {
+- err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+-#if 0
+- if (err >= 0) {
+- int i;
+- printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
+- for (i=0; i<err; ++i)
+- printk("%02x ", buf[i]);
+- printk("\n");
+- }
+-#endif
+- } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
+-
+-
+- if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
+- ds_recv_status(dev, st);
+- return -1;
+- } else
+- return 0;
+-}
+-
+-int ds_reset(struct ds_device *dev, struct ds_status *st)
+-{
+- int err;
+-
+- //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
+- err = ds_send_control(dev, 0x43, SPEED_NORMAL);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, st);
+-#if 0
+- if (st->command_buffer_status) {
+- printk(KERN_INFO "Short circuit.\n");
+- return -EIO;
+- }
+-#endif
+-
+- return 0;
+-}
+-
+-#if 0
+-int ds_set_speed(struct ds_device *dev, int speed)
+-{
+- int err;
+-
+- if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE)
+- return -EINVAL;
+-
+- if (speed != SPEED_OVERDRIVE)
+- speed = SPEED_FLEXIBLE;
+-
+- speed &= 0xff;
+-
+- err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
+- if (err)
+- return err;
+-
+- return err;
+-}
+-#endif /* 0 */
+-
+-static int ds_start_pulse(struct ds_device *dev, int delay)
+-{
+- int err;
+- u8 del = 1 + (u8)(delay >> 4);
+- struct ds_status st;
+-
+-#if 0
+- err = ds_stop_pulse(dev, 10);
+- if (err)
+- return err;
+-
+- err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
+- if (err)
+- return err;
+-#endif
+- err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
+- if (err)
+- return err;
+-
+- err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
+- if (err)
+- return err;
+-
+- mdelay(delay);
+-
+- ds_wait_status(dev, &st);
+-
+- return err;
+-}
+-
+-int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
+-{
+- int err, count;
+- struct ds_status st;
+- u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
+- u16 cmd;
+-
+- err = ds_send_control(dev, value, 0);
+- if (err)
+- return err;
+-
+- count = 0;
+- do {
+- err = ds_wait_status(dev, &st);
+- if (err)
+- return err;
+-
+- cmd = st.command0 | (st.command1 << 8);
+- } while (cmd != value && ++count < 10);
+-
+- if (err < 0 || count >= 10) {
+- printk(KERN_ERR "Failed to obtain status.\n");
+- return -EINVAL;
+- }
+-
+- err = ds_recv_data(dev, tbit, sizeof(*tbit));
+- if (err < 0)
+- return err;
+-
+- return 0;
+-}
+-
+-int ds_write_bit(struct ds_device *dev, u8 bit)
+-{
+- int err;
+- struct ds_status st;
+-
+- err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- return 0;
+-}
+-
+-int ds_write_byte(struct ds_device *dev, u8 byte)
+-{
+- int err;
+- struct ds_status st;
+- u8 rbyte;
+-
+- err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
+- if (err)
+- return err;
+-
+- err = ds_wait_status(dev, &st);
+- if (err)
+- return err;
+-
+- err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
+- if (err < 0)
+- return err;
+-
+- ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+-
+- return !(byte == rbyte);
+-}
+-
+-int ds_read_bit(struct ds_device *dev, u8 *bit)
+-{
+- int err;
+-
+- err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
+- if (err)
+- return err;
+-
+- err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0);
+- if (err)
+- return err;
+-
+- err = ds_recv_data(dev, bit, sizeof(*bit));
+- if (err < 0)
+- return err;
+-
+- return 0;
+-}
+-
+-int ds_read_byte(struct ds_device *dev, u8 *byte)
+-{
+- int err;
+- struct ds_status st;
+-
+- err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- err = ds_recv_data(dev, byte, sizeof(*byte));
+- if (err < 0)
+- return err;
+-
+- return 0;
+-}
+-
+-int ds_read_block(struct ds_device *dev, u8 *buf, int len)
+-{
+- struct ds_status st;
+- int err;
+-
+- if (len > 64*1024)
+- return -E2BIG;
+-
+- memset(buf, 0xFF, len);
+-
+- err = ds_send_data(dev, buf, len);
+- if (err < 0)
+- return err;
+-
+- err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- memset(buf, 0x00, len);
+- err = ds_recv_data(dev, buf, len);
+-
+- return err;
+-}
+-
+-int ds_write_block(struct ds_device *dev, u8 *buf, int len)
+-{
+- int err;
+- struct ds_status st;
+-
+- err = ds_send_data(dev, buf, len);
+- if (err < 0)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- err = ds_recv_data(dev, buf, len);
+- if (err < 0)
+- return err;
+-
+- ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+-
+- return !(err == len);
+-}
+-
+-#if 0
+-
+-int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
+-{
+- int err;
+- u16 value, index;
+- struct ds_status st;
+-
+- memset(buf, 0, sizeof(buf));
+-
+- err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
+- if (err)
+- return err;
+-
+- ds_wait_status(ds_dev, &st);
+-
+- value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
+- index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
+- err = ds_send_control(ds_dev, value, index);
+- if (err)
+- return err;
+-
+- ds_wait_status(ds_dev, &st);
+-
+- err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
+- if (err < 0)
+- return err;
+-
+- return err/8;
+-}
+-
+-int ds_match_access(struct ds_device *dev, u64 init)
+-{
+- int err;
+- struct ds_status st;
+-
+- err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- return 0;
+-}
+-
+-int ds_set_path(struct ds_device *dev, u64 init)
+-{
+- int err;
+- struct ds_status st;
+- u8 buf[9];
+-
+- memcpy(buf, &init, 8);
+- buf[8] = BRANCH_MAIN;
+-
+- err = ds_send_data(dev, buf, sizeof(buf));
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
+- if (err)
+- return err;
+-
+- ds_wait_status(dev, &st);
+-
+- return 0;
+-}
+-
+-#endif /* 0 */
+-
+-static int ds_probe(struct usb_interface *intf,
+- const struct usb_device_id *udev_id)
+-{
+- struct usb_device *udev = interface_to_usbdev(intf);
+- struct usb_endpoint_descriptor *endpoint;
+- struct usb_host_interface *iface_desc;
+- int i, err;
+-
+- ds_dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
+- if (!ds_dev) {
+- printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
+- return -ENOMEM;
+- }
+-
+- ds_dev->udev = usb_get_dev(udev);
+- usb_set_intfdata(intf, ds_dev);
+-
+- err = usb_set_interface(ds_dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
+- if (err) {
+- printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
+- intf->altsetting[0].desc.bInterfaceNumber, err);
+- return err;
+- }
+-
+- err = usb_reset_configuration(ds_dev->udev);
+- if (err) {
+- printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
+- return err;
+- }
+-
+- iface_desc = &intf->altsetting[0];
+- if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
+- printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
+- return -ENODEV;
+- }
+-
+- atomic_set(&ds_dev->refcnt, 0);
+- memset(ds_dev->ep, 0, sizeof(ds_dev->ep));
+-
+- /*
+- * This loop doesn'd show control 0 endpoint,
+- * so we will fill only 1-3 endpoints entry.
+- */
+- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+- endpoint = &iface_desc->endpoint[i].desc;
+-
+- ds_dev->ep[i+1] = endpoint->bEndpointAddress;
+-
+- printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
+- i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
+- (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
+- endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+- }
+-
+-#if 0
+- {
+- int err, i;
+- u64 buf[3];
+- u64 init=0xb30000002078ee81ull;
+- struct ds_status st;
+-
+- ds_reset(ds_dev, &st);
+- err = ds_search(ds_dev, init, buf, 3, 0);
+- if (err < 0)
+- return err;
+- for (i=0; i<err; ++i)
+- printk("%d: %llx\n", i, buf[i]);
+-
+- printk("Resetting...\n");
+- ds_reset(ds_dev, &st);
+- printk("Setting path for %llx.\n", init);
+- err = ds_set_path(ds_dev, init);
+- if (err)
+- return err;
+- printk("Calling MATCH_ACCESS.\n");
+- err = ds_match_access(ds_dev, init);
+- if (err)
+- return err;
+-
+- printk("Searching the bus...\n");
+- err = ds_search(ds_dev, init, buf, 3, 0);
+-
+- printk("ds_search() returned %d\n", err);
+-
+- if (err < 0)
+- return err;
+- for (i=0; i<err; ++i)
+- printk("%d: %llx\n", i, buf[i]);
+-
+- return 0;
+- }
+-#endif
+-
+- return 0;
+-}
+-
+-static void ds_disconnect(struct usb_interface *intf)
+-{
+- struct ds_device *dev;
+-
+- dev = usb_get_intfdata(intf);
+- usb_set_intfdata(intf, NULL);
+-
+- while (atomic_read(&dev->refcnt)) {
+- printk(KERN_INFO "Waiting for DS to become free: refcnt=%d.\n",
+- atomic_read(&dev->refcnt));
+-
+- if (msleep_interruptible(1000))
+- flush_signals(current);
+- }
+-
+- usb_put_dev(dev->udev);
+- kfree(dev);
+- ds_dev = NULL;
+-}
+-
+-static int ds_init(void)
+-{
+- int err;
+-
+- err = usb_register(&ds_driver);
+- if (err) {
+- printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err);
+- return err;
+- }
+-
+- return 0;
+-}
+-
+-static void ds_fini(void)
+-{
+- usb_deregister(&ds_driver);
+-}
+-
+-module_init(ds_init);
+-module_exit(ds_fini);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+-
+-EXPORT_SYMBOL(ds_touch_bit);
+-EXPORT_SYMBOL(ds_read_byte);
+-EXPORT_SYMBOL(ds_read_bit);
+-EXPORT_SYMBOL(ds_read_block);
+-EXPORT_SYMBOL(ds_write_byte);
+-EXPORT_SYMBOL(ds_write_bit);
+-EXPORT_SYMBOL(ds_write_block);
+-EXPORT_SYMBOL(ds_reset);
+-EXPORT_SYMBOL(ds_get_device);
+-EXPORT_SYMBOL(ds_put_device);
+-
+-/*
+- * This functions can be used for EEPROM programming,
+- * when driver will be included into mainline this will
+- * require uncommenting.
+- */
+-#if 0
+-EXPORT_SYMBOL(ds_start_pulse);
+-EXPORT_SYMBOL(ds_set_speed);
+-EXPORT_SYMBOL(ds_detect);
+-EXPORT_SYMBOL(ds_stop_pulse);
+-EXPORT_SYMBOL(ds_search);
+-#endif
+--- gregkh-2.6.orig/drivers/w1/dscore.h
++++ /dev/null
+@@ -1,166 +0,0 @@
+-/*
+- * dscore.h
+- *
+- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+- *
+- *
+- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#ifndef __DSCORE_H
+-#define __DSCORE_H
+-
+-#include <linux/usb.h>
+-#include <asm/atomic.h>
+-
+-/* COMMAND TYPE CODES */
+-#define CONTROL_CMD 0x00
+-#define COMM_CMD 0x01
+-#define MODE_CMD 0x02
+-
+-/* CONTROL COMMAND CODES */
+-#define CTL_RESET_DEVICE 0x0000
+-#define CTL_START_EXE 0x0001
+-#define CTL_RESUME_EXE 0x0002
+-#define CTL_HALT_EXE_IDLE 0x0003
+-#define CTL_HALT_EXE_DONE 0x0004
+-#define CTL_FLUSH_COMM_CMDS 0x0007
+-#define CTL_FLUSH_RCV_BUFFER 0x0008
+-#define CTL_FLUSH_XMT_BUFFER 0x0009
+-#define CTL_GET_COMM_CMDS 0x000A
+-
+-/* MODE COMMAND CODES */
+-#define MOD_PULSE_EN 0x0000
+-#define MOD_SPEED_CHANGE_EN 0x0001
+-#define MOD_1WIRE_SPEED 0x0002
+-#define MOD_STRONG_PU_DURATION 0x0003
+-#define MOD_PULLDOWN_SLEWRATE 0x0004
+-#define MOD_PROG_PULSE_DURATION 0x0005
+-#define MOD_WRITE1_LOWTIME 0x0006
+-#define MOD_DSOW0_TREC 0x0007
+-
+-/* COMMUNICATION COMMAND CODES */
+-#define COMM_ERROR_ESCAPE 0x0601
+-#define COMM_SET_DURATION 0x0012
+-#define COMM_BIT_IO 0x0020
+-#define COMM_PULSE 0x0030
+-#define COMM_1_WIRE_RESET 0x0042
+-#define COMM_BYTE_IO 0x0052
+-#define COMM_MATCH_ACCESS 0x0064
+-#define COMM_BLOCK_IO 0x0074
+-#define COMM_READ_STRAIGHT 0x0080
+-#define COMM_DO_RELEASE 0x6092
+-#define COMM_SET_PATH 0x00A2
+-#define COMM_WRITE_SRAM_PAGE 0x00B2
+-#define COMM_WRITE_EPROM 0x00C4
+-#define COMM_READ_CRC_PROT_PAGE 0x00D4
+-#define COMM_READ_REDIRECT_PAGE_CRC 0x21E4
+-#define COMM_SEARCH_ACCESS 0x00F4
+-
+-/* Communication command bits */
+-#define COMM_TYPE 0x0008
+-#define COMM_SE 0x0008
+-#define COMM_D 0x0008
+-#define COMM_Z 0x0008
+-#define COMM_CH 0x0008
+-#define COMM_SM 0x0008
+-#define COMM_R 0x0008
+-#define COMM_IM 0x0001
+-
+-#define COMM_PS 0x4000
+-#define COMM_PST 0x4000
+-#define COMM_CIB 0x4000
+-#define COMM_RTS 0x4000
+-#define COMM_DT 0x2000
+-#define COMM_SPU 0x1000
+-#define COMM_F 0x0800
+-#define COMM_NTP 0x0400
+-#define COMM_ICP 0x0200
+-#define COMM_RST 0x0100
+-
+-#define PULSE_PROG 0x01
+-#define PULSE_SPUE 0x02
+-
+-#define BRANCH_MAIN 0xCC
+-#define BRANCH_AUX 0x33
+-
+-/*
+- * Duration of the strong pull-up pulse in milliseconds.
+- */
+-#define PULLUP_PULSE_DURATION 750
+-
+-/* Status flags */
+-#define ST_SPUA 0x01 /* Strong Pull-up is active */
+-#define ST_PRGA 0x02 /* 12V programming pulse is being generated */
+-#define ST_12VP 0x04 /* external 12V programming voltage is present */
+-#define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */
+-#define ST_HALT 0x10 /* DS2490 is currently halted */
+-#define ST_IDLE 0x20 /* DS2490 is currently idle */
+-#define ST_EPOF 0x80
+-
+-#define SPEED_NORMAL 0x00
+-#define SPEED_FLEXIBLE 0x01
+-#define SPEED_OVERDRIVE 0x02
+-
+-#define NUM_EP 4
+-#define EP_CONTROL 0
+-#define EP_STATUS 1
+-#define EP_DATA_OUT 2
+-#define EP_DATA_IN 3
+-
+-struct ds_device
+-{
+- struct usb_device *udev;
+- struct usb_interface *intf;
+-
+- int ep[NUM_EP];
+-
+- atomic_t refcnt;
+-};
+-
+-struct ds_status
+-{
+- u8 enable;
+- u8 speed;
+- u8 pullup_dur;
+- u8 ppuls_dur;
+- u8 pulldown_slew;
+- u8 write1_time;
+- u8 write0_time;
+- u8 reserved0;
+- u8 status;
+- u8 command0;
+- u8 command1;
+- u8 command_buffer_status;
+- u8 data_out_buffer_status;
+- u8 data_in_buffer_status;
+- u8 reserved1;
+- u8 reserved2;
+-
+-};
+-
+-int ds_touch_bit(struct ds_device *, u8, u8 *);
+-int ds_read_byte(struct ds_device *, u8 *);
+-int ds_read_bit(struct ds_device *, u8 *);
+-int ds_write_byte(struct ds_device *, u8);
+-int ds_write_bit(struct ds_device *, u8);
+-int ds_reset(struct ds_device *, struct ds_status *);
+-struct ds_device * ds_get_device(void);
+-void ds_put_device(struct ds_device *);
+-int ds_write_block(struct ds_device *, u8 *, int);
+-int ds_read_block(struct ds_device *, u8 *, int);
+-
+-#endif /* __DSCORE_H */
+-
+--- /dev/null
++++ gregkh-2.6/drivers/w1/masters/Kconfig
+@@ -0,0 +1,38 @@
++#
++# 1-wire bus master configuration
++#
++
++menu "1-wire Bus Masters"
++ depends on W1
++
++config W1_MASTER_MATROX
++ tristate "Matrox G400 transport layer for 1-wire"
++ depends on W1 && PCI
++ help
++ Say Y here if you want to communicate with your 1-wire devices
++ using Matrox's G400 GPIO pins.
++
++ This support is also available as a module. If so, the module
++ will be called matrox_w1.ko.
++
++config W1_MASTER_DS9490
++ tristate "DS9490R transport layer driver"
++ depends on W1 && USB
++ help
++ Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge.
++
++ This support is also available as a module. If so, the module
++ will be called ds9490r.ko.
++
++config W1_MASTER_DS9490_BRIDGE
++ tristate "DS9490R USB <-> W1 transport layer for 1-wire"
++ depends on W1_DS9490
++ help
++ Say Y here if you want to communicate with your 1-wire devices
++ using DS9490R USB bridge.
++
++ This support is also available as a module. If so, the module
++ will be called ds_w1_bridge.ko.
++
++endmenu
++
+--- /dev/null
++++ gregkh-2.6/drivers/w1/masters/Makefile
+@@ -0,0 +1,11 @@
++#
++# Makefile for 1-wire bus master drivers.
++#
++
++obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o
++
++obj-$(CONFIG_W1_MASTER_DS9490) += ds9490r.o
++ds9490r-objs := dscore.o
++
++obj-$(CONFIG_W1_MASTER_DS9490_BRIDGE) += ds_w1_bridge.o
++
+--- /dev/null
++++ gregkh-2.6/drivers/w1/masters/ds_w1_bridge.c
+@@ -0,0 +1,174 @@
++/*
++ * ds_w1_bridge.c
++ *
++ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
++ *
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++
++#include "../w1.h"
++#include "../w1_int.h"
++#include "dscore.h"
++
++static struct ds_device *ds_dev;
++static struct w1_bus_master *ds_bus_master;
++
++static u8 ds9490r_touch_bit(void *data, u8 bit)
++{
++ u8 ret;
++ struct ds_device *dev = data;
++
++ if (ds_touch_bit(dev, bit, &ret))
++ return 0;
++
++ return ret;
++}
++
++static void ds9490r_write_bit(void *data, u8 bit)
++{
++ struct ds_device *dev = data;
++
++ ds_write_bit(dev, bit);
++}
++
++static void ds9490r_write_byte(void *data, u8 byte)
++{
++ struct ds_device *dev = data;
++
++ ds_write_byte(dev, byte);
++}
++
++static u8 ds9490r_read_bit(void *data)
++{
++ struct ds_device *dev = data;
++ int err;
++ u8 bit = 0;
++
++ err = ds_touch_bit(dev, 1, &bit);
++ if (err)
++ return 0;
++ //err = ds_read_bit(dev, &bit);
++ //if (err)
++ // return 0;
++
++ return bit & 1;
++}
++
++static u8 ds9490r_read_byte(void *data)
++{
++ struct ds_device *dev = data;
++ int err;
++ u8 byte = 0;
++
++ err = ds_read_byte(dev, &byte);
++ if (err)
++ return 0;
++
++ return byte;
++}
++
++static void ds9490r_write_block(void *data, const u8 *buf, int len)
++{
++ struct ds_device *dev = data;
++
++ ds_write_block(dev, (u8 *)buf, len);
++}
++
++static u8 ds9490r_read_block(void *data, u8 *buf, int len)
++{
++ struct ds_device *dev = data;
++ int err;
++
++ err = ds_read_block(dev, buf, len);
++ if (err < 0)
++ return 0;
++
++ return len;
++}
++
++static u8 ds9490r_reset(void *data)
++{
++ struct ds_device *dev = data;
++ struct ds_status st;
++ int err;
++
++ memset(&st, 0, sizeof(st));
++
++ err = ds_reset(dev, &st);
++ if (err)
++ return 1;
++
++ return 0;
++}
++
++static int __devinit ds_w1_init(void)
++{
++ int err;
++
++ ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL);
++ if (!ds_bus_master) {
++ printk(KERN_ERR "Failed to allocate DS9490R USB<->W1 bus_master structure.\n");
++ return -ENOMEM;
++ }
++
++ ds_dev = ds_get_device();
++ if (!ds_dev) {
++ printk(KERN_ERR "DS9490R is not registered.\n");
++ err = -ENODEV;
++ goto err_out_free_bus_master;
++ }
++
++ memset(ds_bus_master, 0, sizeof(*ds_bus_master));
++
++ ds_bus_master->data = ds_dev;
++ ds_bus_master->touch_bit = &ds9490r_touch_bit;
++ ds_bus_master->read_bit = &ds9490r_read_bit;
++ ds_bus_master->write_bit = &ds9490r_write_bit;
++ ds_bus_master->read_byte = &ds9490r_read_byte;
++ ds_bus_master->write_byte = &ds9490r_write_byte;
++ ds_bus_master->read_block = &ds9490r_read_block;
++ ds_bus_master->write_block = &ds9490r_write_block;
++ ds_bus_master->reset_bus = &ds9490r_reset;
++
++ err = w1_add_master_device(ds_bus_master);
++ if (err)
++ goto err_out_put_device;
++
++ return 0;
++
++err_out_put_device:
++ ds_put_device(ds_dev);
++err_out_free_bus_master:
++ kfree(ds_bus_master);
++
++ return err;
++}
++
++static void __devexit ds_w1_fini(void)
++{
++ w1_remove_master_device(ds_bus_master);
++ ds_put_device(ds_dev);
++ kfree(ds_bus_master);
++}
++
++module_init(ds_w1_init);
++module_exit(ds_w1_fini);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+--- /dev/null
++++ gregkh-2.6/drivers/w1/masters/dscore.c
+@@ -0,0 +1,795 @@
++/*
++ * dscore.c
++ *
++ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
++ *
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/usb.h>
++
++#include "dscore.h"
++
++static struct usb_device_id ds_id_table [] = {
++ { USB_DEVICE(0x04fa, 0x2490) },
++ { },
++};
++MODULE_DEVICE_TABLE(usb, ds_id_table);
++
++static int ds_probe(struct usb_interface *, const struct usb_device_id *);
++static void ds_disconnect(struct usb_interface *);
++
++int ds_touch_bit(struct ds_device *, u8, u8 *);
++int ds_read_byte(struct ds_device *, u8 *);
++int ds_read_bit(struct ds_device *, u8 *);
++int ds_write_byte(struct ds_device *, u8);
++int ds_write_bit(struct ds_device *, u8);
++static int ds_start_pulse(struct ds_device *, int);
++int ds_reset(struct ds_device *, struct ds_status *);
++struct ds_device * ds_get_device(void);
++void ds_put_device(struct ds_device *);
++
++static inline void ds_dump_status(unsigned char *, unsigned char *, int);
++static int ds_send_control(struct ds_device *, u16, u16);
++static int ds_send_control_mode(struct ds_device *, u16, u16);
++static int ds_send_control_cmd(struct ds_device *, u16, u16);
++
++
++static struct usb_driver ds_driver = {
++ .name = "DS9490R",
++ .probe = ds_probe,
++ .disconnect = ds_disconnect,
++ .id_table = ds_id_table,
++};
++
++static struct ds_device *ds_dev;
++
++struct ds_device * ds_get_device(void)
++{
++ if (ds_dev)
++ atomic_inc(&ds_dev->refcnt);
++ return ds_dev;
++}
++
++void ds_put_device(struct ds_device *dev)
++{
++ atomic_dec(&dev->refcnt);
++}
++
++static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
++{
++ int err;
++
++ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
++ CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
++ value, index, err);
++ return err;
++ }
++
++ return err;
++}
++
++static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
++{
++ int err;
++
++ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
++ MODE_CMD, 0x40, value, index, NULL, 0, 1000);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
++ value, index, err);
++ return err;
++ }
++
++ return err;
++}
++
++static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
++{
++ int err;
++
++ err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
++ COMM_CMD, 0x40, value, index, NULL, 0, 1000);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
++ value, index, err);
++ return err;
++ }
++
++ return err;
++}
++
++static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
++{
++ printk("%45s: %8x\n", str, buf[off]);
++}
++
++static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
++ unsigned char *buf, int size)
++{
++ int count, err;
++
++ memset(st, 0, sizeof(st));
++
++ count = 0;
++ err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
++ return err;
++ }
++
++ if (count >= sizeof(*st))
++ memcpy(st, buf, sizeof(*st));
++
++ return count;
++}
++
++static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
++{
++ unsigned char buf[64];
++ int count, err = 0, i;
++
++ memcpy(st, buf, sizeof(*st));
++
++ count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
++ if (count < 0)
++ return err;
++
++ printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
++ for (i=0; i<count; ++i)
++ printk("%02x ", buf[i]);
++ printk("\n");
++
++ if (count >= 16) {
++ ds_dump_status(buf, "enable flag", 0);
++ ds_dump_status(buf, "1-wire speed", 1);
++ ds_dump_status(buf, "strong pullup duration", 2);
++ ds_dump_status(buf, "programming pulse duration", 3);
++ ds_dump_status(buf, "pulldown slew rate control", 4);
++ ds_dump_status(buf, "write-1 low time", 5);
++ ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
++ ds_dump_status(buf, "reserved (test register)", 7);
++ ds_dump_status(buf, "device status flags", 8);
++ ds_dump_status(buf, "communication command byte 1", 9);
++ ds_dump_status(buf, "communication command byte 2", 10);
++ ds_dump_status(buf, "communication command buffer status", 11);
++ ds_dump_status(buf, "1-wire data output buffer status", 12);
++ ds_dump_status(buf, "1-wire data input buffer status", 13);
++ ds_dump_status(buf, "reserved", 14);
++ ds_dump_status(buf, "reserved", 15);
++ }
++
++ memcpy(st, buf, sizeof(*st));
++
++ if (st->status & ST_EPOF) {
++ printk(KERN_INFO "Resetting device after ST_EPOF.\n");
++ err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
++ if (err)
++ return err;
++ count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
++ if (count < 0)
++ return err;
++ }
++#if 0
++ if (st->status & ST_IDLE) {
++ printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
++ err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
++ if (err)
++ return err;
++ }
++#endif
++
++ return err;
++}
++
++static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
++{
++ int count, err;
++ struct ds_status st;
++
++ count = 0;
++ err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
++ buf, size, &count, 1000);
++ if (err < 0) {
++ printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
++ usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
++ ds_recv_status(dev, &st);
++ return err;
++ }
++
++#if 0
++ {
++ int i;
++
++ printk("%s: count=%d: ", __func__, count);
++ for (i=0; i<count; ++i)
++ printk("%02x ", buf[i]);
++ printk("\n");
++ }
++#endif
++ return count;
++}
++
++static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
++{
++ int count, err;
++
++ count = 0;
++ err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
++ return err;
++ }
++
++ return err;
++}
++
++#if 0
++
++int ds_stop_pulse(struct ds_device *dev, int limit)
++{
++ struct ds_status st;
++ int count = 0, err = 0;
++ u8 buf[0x20];
++
++ do {
++ err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
++ if (err)
++ break;
++ err = ds_send_control(dev, CTL_RESUME_EXE, 0);
++ if (err)
++ break;
++ err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
++ if (err)
++ break;
++
++ if ((st.status & ST_SPUA) == 0) {
++ err = ds_send_control_mode(dev, MOD_PULSE_EN, 0);
++ if (err)
++ break;
++ }
++ } while(++count < limit);
++
++ return err;
++}
++
++int ds_detect(struct ds_device *dev, struct ds_status *st)
++{
++ int err;
++
++ err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
++ if (err)
++ return err;
++
++ err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
++ if (err)
++ return err;
++
++ err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
++ if (err)
++ return err;
++
++ err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
++ if (err)
++ return err;
++
++ err = ds_recv_status(dev, st);
++
++ return err;
++}
++
++#endif /* 0 */
++
++static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
++{
++ u8 buf[0x20];
++ int err, count = 0;
++
++ do {
++ err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
++#if 0
++ if (err >= 0) {
++ int i;
++ printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
++ for (i=0; i<err; ++i)
++ printk("%02x ", buf[i]);
++ printk("\n");
++ }
++#endif
++ } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
++
++
++ if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
++ ds_recv_status(dev, st);
++ return -1;
++ } else
++ return 0;
++}
++
++int ds_reset(struct ds_device *dev, struct ds_status *st)
++{
++ int err;
++
++ //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
++ err = ds_send_control(dev, 0x43, SPEED_NORMAL);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, st);
++#if 0
++ if (st->command_buffer_status) {
++ printk(KERN_INFO "Short circuit.\n");
++ return -EIO;
++ }
++#endif
++
++ return 0;
++}
++
++#if 0
++int ds_set_speed(struct ds_device *dev, int speed)
++{
++ int err;
++
++ if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE)
++ return -EINVAL;
++
++ if (speed != SPEED_OVERDRIVE)
++ speed = SPEED_FLEXIBLE;
++
++ speed &= 0xff;
++
++ err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
++ if (err)
++ return err;
++
++ return err;
++}
++#endif /* 0 */
++
++static int ds_start_pulse(struct ds_device *dev, int delay)
++{
++ int err;
++ u8 del = 1 + (u8)(delay >> 4);
++ struct ds_status st;
++
++#if 0
++ err = ds_stop_pulse(dev, 10);
++ if (err)
++ return err;
++
++ err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
++ if (err)
++ return err;
++#endif
++ err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
++ if (err)
++ return err;
++
++ err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
++ if (err)
++ return err;
++
++ mdelay(delay);
++
++ ds_wait_status(dev, &st);
++
++ return err;
++}
++
++int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
++{
++ int err, count;
++ struct ds_status st;
++ u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
++ u16 cmd;
++
++ err = ds_send_control(dev, value, 0);
++ if (err)
++ return err;
++
++ count = 0;
++ do {
++ err = ds_wait_status(dev, &st);
++ if (err)
++ return err;
++
++ cmd = st.command0 | (st.command1 << 8);
++ } while (cmd != value && ++count < 10);
++
++ if (err < 0 || count >= 10) {
++ printk(KERN_ERR "Failed to obtain status.\n");
++ return -EINVAL;
++ }
++
++ err = ds_recv_data(dev, tbit, sizeof(*tbit));
++ if (err < 0)
++ return err;
++
++ return 0;
++}
++
++int ds_write_bit(struct ds_device *dev, u8 bit)
++{
++ int err;
++ struct ds_status st;
++
++ err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ return 0;
++}
++
++int ds_write_byte(struct ds_device *dev, u8 byte)
++{
++ int err;
++ struct ds_status st;
++ u8 rbyte;
++
++ err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
++ if (err)
++ return err;
++
++ err = ds_wait_status(dev, &st);
++ if (err)
++ return err;
++
++ err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
++ if (err < 0)
++ return err;
++
++ ds_start_pulse(dev, PULLUP_PULSE_DURATION);
++
++ return !(byte == rbyte);
++}
++
++int ds_read_bit(struct ds_device *dev, u8 *bit)
++{
++ int err;
++
++ err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
++ if (err)
++ return err;
++
++ err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0);
++ if (err)
++ return err;
++
++ err = ds_recv_data(dev, bit, sizeof(*bit));
++ if (err < 0)
++ return err;
++
++ return 0;
++}
++
++int ds_read_byte(struct ds_device *dev, u8 *byte)
++{
++ int err;
++ struct ds_status st;
++
++ err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ err = ds_recv_data(dev, byte, sizeof(*byte));
++ if (err < 0)
++ return err;
++
++ return 0;
++}
++
++int ds_read_block(struct ds_device *dev, u8 *buf, int len)
++{
++ struct ds_status st;
++ int err;
++
++ if (len > 64*1024)
++ return -E2BIG;
++
++ memset(buf, 0xFF, len);
++
++ err = ds_send_data(dev, buf, len);
++ if (err < 0)
++ return err;
++
++ err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ memset(buf, 0x00, len);
++ err = ds_recv_data(dev, buf, len);
++
++ return err;
++}
++
++int ds_write_block(struct ds_device *dev, u8 *buf, int len)
++{
++ int err;
++ struct ds_status st;
++
++ err = ds_send_data(dev, buf, len);
++ if (err < 0)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ err = ds_recv_data(dev, buf, len);
++ if (err < 0)
++ return err;
++
++ ds_start_pulse(dev, PULLUP_PULSE_DURATION);
++
++ return !(err == len);
++}
++
++#if 0
++
++int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
++{
++ int err;
++ u16 value, index;
++ struct ds_status st;
++
++ memset(buf, 0, sizeof(buf));
++
++ err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
++ if (err)
++ return err;
++
++ ds_wait_status(ds_dev, &st);
++
++ value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
++ index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
++ err = ds_send_control(ds_dev, value, index);
++ if (err)
++ return err;
++
++ ds_wait_status(ds_dev, &st);
++
++ err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
++ if (err < 0)
++ return err;
++
++ return err/8;
++}
++
++int ds_match_access(struct ds_device *dev, u64 init)
++{
++ int err;
++ struct ds_status st;
++
++ err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ return 0;
++}
++
++int ds_set_path(struct ds_device *dev, u64 init)
++{
++ int err;
++ struct ds_status st;
++ u8 buf[9];
++
++ memcpy(buf, &init, 8);
++ buf[8] = BRANCH_MAIN;
++
++ err = ds_send_data(dev, buf, sizeof(buf));
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
++ if (err)
++ return err;
++
++ ds_wait_status(dev, &st);
++
++ return 0;
++}
++
++#endif /* 0 */
++
++static int ds_probe(struct usb_interface *intf,
++ const struct usb_device_id *udev_id)
++{
++ struct usb_device *udev = interface_to_usbdev(intf);
++ struct usb_endpoint_descriptor *endpoint;
++ struct usb_host_interface *iface_desc;
++ int i, err;
++
++ ds_dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
++ if (!ds_dev) {
++ printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
++ return -ENOMEM;
++ }
++
++ ds_dev->udev = usb_get_dev(udev);
++ usb_set_intfdata(intf, ds_dev);
++
++ err = usb_set_interface(ds_dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
++ if (err) {
++ printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
++ intf->altsetting[0].desc.bInterfaceNumber, err);
++ return err;
++ }
++
++ err = usb_reset_configuration(ds_dev->udev);
++ if (err) {
++ printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
++ return err;
++ }
++
++ iface_desc = &intf->altsetting[0];
++ if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
++ printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
++ return -ENODEV;
++ }
++
++ atomic_set(&ds_dev->refcnt, 0);
++ memset(ds_dev->ep, 0, sizeof(ds_dev->ep));
++
++ /*
++ * This loop doesn'd show control 0 endpoint,
++ * so we will fill only 1-3 endpoints entry.
++ */
++ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
++ endpoint = &iface_desc->endpoint[i].desc;
++
++ ds_dev->ep[i+1] = endpoint->bEndpointAddress;
++
++ printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
++ i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
++ (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
++ endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
++ }
++
++#if 0
++ {
++ int err, i;
++ u64 buf[3];
++ u64 init=0xb30000002078ee81ull;
++ struct ds_status st;
++
++ ds_reset(ds_dev, &st);
++ err = ds_search(ds_dev, init, buf, 3, 0);
++ if (err < 0)
++ return err;
++ for (i=0; i<err; ++i)
++ printk("%d: %llx\n", i, buf[i]);
++
++ printk("Resetting...\n");
++ ds_reset(ds_dev, &st);
++ printk("Setting path for %llx.\n", init);
++ err = ds_set_path(ds_dev, init);
++ if (err)
++ return err;
++ printk("Calling MATCH_ACCESS.\n");
++ err = ds_match_access(ds_dev, init);
++ if (err)
++ return err;
++
++ printk("Searching the bus...\n");
++ err = ds_search(ds_dev, init, buf, 3, 0);
++
++ printk("ds_search() returned %d\n", err);
++
++ if (err < 0)
++ return err;
++ for (i=0; i<err; ++i)
++ printk("%d: %llx\n", i, buf[i]);
++
++ return 0;
++ }
++#endif
++
++ return 0;
++}
++
++static void ds_disconnect(struct usb_interface *intf)
++{
++ struct ds_device *dev;
++
++ dev = usb_get_intfdata(intf);
++ usb_set_intfdata(intf, NULL);
++
++ while (atomic_read(&dev->refcnt)) {
++ printk(KERN_INFO "Waiting for DS to become free: refcnt=%d.\n",
++ atomic_read(&dev->refcnt));
++
++ if (msleep_interruptible(1000))
++ flush_signals(current);
++ }
++
++ usb_put_dev(dev->udev);
++ kfree(dev);
++ ds_dev = NULL;
++}
++
++static int ds_init(void)
++{
++ int err;
++
++ err = usb_register(&ds_driver);
++ if (err) {
++ printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err);
++ return err;
++ }
++
++ return 0;
++}
++
++static void ds_fini(void)
++{
++ usb_deregister(&ds_driver);
++}
++
++module_init(ds_init);
++module_exit(ds_fini);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
++
++EXPORT_SYMBOL(ds_touch_bit);
++EXPORT_SYMBOL(ds_read_byte);
++EXPORT_SYMBOL(ds_read_bit);
++EXPORT_SYMBOL(ds_read_block);
++EXPORT_SYMBOL(ds_write_byte);
++EXPORT_SYMBOL(ds_write_bit);
++EXPORT_SYMBOL(ds_write_block);
++EXPORT_SYMBOL(ds_reset);
++EXPORT_SYMBOL(ds_get_device);
++EXPORT_SYMBOL(ds_put_device);
++
++/*
++ * This functions can be used for EEPROM programming,
++ * when driver will be included into mainline this will
++ * require uncommenting.
++ */
++#if 0
++EXPORT_SYMBOL(ds_start_pulse);
++EXPORT_SYMBOL(ds_set_speed);
++EXPORT_SYMBOL(ds_detect);
++EXPORT_SYMBOL(ds_stop_pulse);
++EXPORT_SYMBOL(ds_search);
++#endif
+--- /dev/null
++++ gregkh-2.6/drivers/w1/masters/dscore.h
+@@ -0,0 +1,166 @@
++/*
++ * dscore.h
++ *
++ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
++ *
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef __DSCORE_H
++#define __DSCORE_H
++
++#include <linux/usb.h>
++#include <asm/atomic.h>
++
++/* COMMAND TYPE CODES */
++#define CONTROL_CMD 0x00
++#define COMM_CMD 0x01
++#define MODE_CMD 0x02
++
++/* CONTROL COMMAND CODES */
++#define CTL_RESET_DEVICE 0x0000
++#define CTL_START_EXE 0x0001
++#define CTL_RESUME_EXE 0x0002
++#define CTL_HALT_EXE_IDLE 0x0003
++#define CTL_HALT_EXE_DONE 0x0004
++#define CTL_FLUSH_COMM_CMDS 0x0007
++#define CTL_FLUSH_RCV_BUFFER 0x0008
++#define CTL_FLUSH_XMT_BUFFER 0x0009
++#define CTL_GET_COMM_CMDS 0x000A
++
++/* MODE COMMAND CODES */
++#define MOD_PULSE_EN 0x0000
++#define MOD_SPEED_CHANGE_EN 0x0001
++#define MOD_1WIRE_SPEED 0x0002
++#define MOD_STRONG_PU_DURATION 0x0003
++#define MOD_PULLDOWN_SLEWRATE 0x0004
++#define MOD_PROG_PULSE_DURATION 0x0005
++#define MOD_WRITE1_LOWTIME 0x0006
++#define MOD_DSOW0_TREC 0x0007
++
++/* COMMUNICATION COMMAND CODES */
++#define COMM_ERROR_ESCAPE 0x0601
++#define COMM_SET_DURATION 0x0012
++#define COMM_BIT_IO 0x0020
++#define COMM_PULSE 0x0030
++#define COMM_1_WIRE_RESET 0x0042
++#define COMM_BYTE_IO 0x0052
++#define COMM_MATCH_ACCESS 0x0064
++#define COMM_BLOCK_IO 0x0074
++#define COMM_READ_STRAIGHT 0x0080
++#define COMM_DO_RELEASE 0x6092
++#define COMM_SET_PATH 0x00A2
++#define COMM_WRITE_SRAM_PAGE 0x00B2
++#define COMM_WRITE_EPROM 0x00C4
++#define COMM_READ_CRC_PROT_PAGE 0x00D4
++#define COMM_READ_REDIRECT_PAGE_CRC 0x21E4
++#define COMM_SEARCH_ACCESS 0x00F4
++
++/* Communication command bits */
++#define COMM_TYPE 0x0008
++#define COMM_SE 0x0008
++#define COMM_D 0x0008
++#define COMM_Z 0x0008
++#define COMM_CH 0x0008
++#define COMM_SM 0x0008
++#define COMM_R 0x0008
++#define COMM_IM 0x0001
++
++#define COMM_PS 0x4000
++#define COMM_PST 0x4000
++#define COMM_CIB 0x4000
++#define COMM_RTS 0x4000
++#define COMM_DT 0x2000
++#define COMM_SPU 0x1000
++#define COMM_F 0x0800
++#define COMM_NTP 0x0400
++#define COMM_ICP 0x0200
++#define COMM_RST 0x0100
++
++#define PULSE_PROG 0x01
++#define PULSE_SPUE 0x02
++
++#define BRANCH_MAIN 0xCC
++#define BRANCH_AUX 0x33
++
++/*
++ * Duration of the strong pull-up pulse in milliseconds.
++ */
++#define PULLUP_PULSE_DURATION 750
++
++/* Status flags */
++#define ST_SPUA 0x01 /* Strong Pull-up is active */
++#define ST_PRGA 0x02 /* 12V programming pulse is being generated */
++#define ST_12VP 0x04 /* external 12V programming voltage is present */
++#define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */
++#define ST_HALT 0x10 /* DS2490 is currently halted */
++#define ST_IDLE 0x20 /* DS2490 is currently idle */
++#define ST_EPOF 0x80
++
++#define SPEED_NORMAL 0x00
++#define SPEED_FLEXIBLE 0x01
++#define SPEED_OVERDRIVE 0x02
++
++#define NUM_EP 4
++#define EP_CONTROL 0
++#define EP_STATUS 1
++#define EP_DATA_OUT 2
++#define EP_DATA_IN 3
++
++struct ds_device
++{
++ struct usb_device *udev;
++ struct usb_interface *intf;
++
++ int ep[NUM_EP];
++
++ atomic_t refcnt;
++};
++
++struct ds_status
++{
++ u8 enable;
++ u8 speed;
++ u8 pullup_dur;
++ u8 ppuls_dur;
++ u8 pulldown_slew;
++ u8 write1_time;
++ u8 write0_time;
++ u8 reserved0;
++ u8 status;
++ u8 command0;
++ u8 command1;
++ u8 command_buffer_status;
++ u8 data_out_buffer_status;
++ u8 data_in_buffer_status;
++ u8 reserved1;
++ u8 reserved2;
++
++};
++
++int ds_touch_bit(struct ds_device *, u8, u8 *);
++int ds_read_byte(struct ds_device *, u8 *);
++int ds_read_bit(struct ds_device *, u8 *);
++int ds_write_byte(struct ds_device *, u8);
++int ds_write_bit(struct ds_device *, u8);
++int ds_reset(struct ds_device *, struct ds_status *);
++struct ds_device * ds_get_device(void);
++void ds_put_device(struct ds_device *);
++int ds_write_block(struct ds_device *, u8 *, int);
++int ds_read_block(struct ds_device *, u8 *, int);
++
++#endif /* __DSCORE_H */
++
+--- /dev/null
++++ gregkh-2.6/drivers/w1/masters/matrox_w1.c
+@@ -0,0 +1,247 @@
++/*
++ * matrox_w1.c
++ *
++ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
++ *
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <asm/types.h>
++#include <asm/atomic.h>
++#include <asm/io.h>
++
++#include <linux/delay.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/list.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/timer.h>
++#include <linux/slab.h>
++#include <linux/pci_ids.h>
++#include <linux/pci.h>
++#include <linux/timer.h>
++
++#include "../w1.h"
++#include "../w1_int.h"
++#include "../w1_log.h"
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
++MODULE_DESCRIPTION("Driver for transport(Dallas 1-wire prtocol) over VGA DDC(matrox gpio).");
++
++static struct pci_device_id matrox_w1_tbl[] = {
++ { PCI_DEVICE(PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400) },
++ { },
++};
++MODULE_DEVICE_TABLE(pci, matrox_w1_tbl);
++
++static int __devinit matrox_w1_probe(struct pci_dev *, const struct pci_device_id *);
++static void __devexit matrox_w1_remove(struct pci_dev *);
++
++static struct pci_driver matrox_w1_pci_driver = {
++ .name = "matrox_w1",
++ .id_table = matrox_w1_tbl,
++ .probe = matrox_w1_probe,
++ .remove = __devexit_p(matrox_w1_remove),
++};
++
++/*
++ * Matrox G400 DDC registers.
++ */
++
++#define MATROX_G400_DDC_CLK (1<<4)
++#define MATROX_G400_DDC_DATA (1<<1)
++
++#define MATROX_BASE 0x3C00
++#define MATROX_STATUS 0x1e14
++
++#define MATROX_PORT_INDEX_OFFSET 0x00
++#define MATROX_PORT_DATA_OFFSET 0x0A
++
++#define MATROX_GET_CONTROL 0x2A
++#define MATROX_GET_DATA 0x2B
++#define MATROX_CURSOR_CTL 0x06
++
++struct matrox_device
++{
++ void __iomem *base_addr;
++ void __iomem *port_index;
++ void __iomem *port_data;
++ u8 data_mask;
++
++ unsigned long phys_addr;
++ void __iomem *virt_addr;
++ unsigned long found;
++
++ struct w1_bus_master *bus_master;
++};
++
++static u8 matrox_w1_read_ddc_bit(void *);
++static void matrox_w1_write_ddc_bit(void *, u8);
++
++/*
++ * These functions read and write DDC Data bit.
++ *
++ * Using tristate pins, since i can't find any open-drain pin in whole motherboard.
++ * Unfortunately we can't connect to Intel's 82801xx IO controller
++ * since we don't know motherboard schema, wich has pretty unused(may be not) GPIO.
++ *
++ * I've heard that PIIX also has open drain pin.
++ *
++ * Port mapping.
++ */
++static __inline__ u8 matrox_w1_read_reg(struct matrox_device *dev, u8 reg)
++{
++ u8 ret;
++
++ writeb(reg, dev->port_index);
++ ret = readb(dev->port_data);
++ barrier();
++
++ return ret;
++}
++
++static __inline__ void matrox_w1_write_reg(struct matrox_device *dev, u8 reg, u8 val)
++{
++ writeb(reg, dev->port_index);
++ writeb(val, dev->port_data);
++ wmb();
++}
++
++static void matrox_w1_write_ddc_bit(void *data, u8 bit)
++{
++ u8 ret;
++ struct matrox_device *dev = data;
++
++ if (bit)
++ bit = 0;
++ else
++ bit = dev->data_mask;
++
++ ret = matrox_w1_read_reg(dev, MATROX_GET_CONTROL);
++ matrox_w1_write_reg(dev, MATROX_GET_CONTROL, ((ret & ~dev->data_mask) | bit));
++ matrox_w1_write_reg(dev, MATROX_GET_DATA, 0x00);
++}
++
++static u8 matrox_w1_read_ddc_bit(void *data)
++{
++ u8 ret;
++ struct matrox_device *dev = data;
++
++ ret = matrox_w1_read_reg(dev, MATROX_GET_DATA);
++
++ return ret;
++}
++
++static void matrox_w1_hw_init(struct matrox_device *dev)
++{
++ matrox_w1_write_reg(dev, MATROX_GET_DATA, 0xFF);
++ matrox_w1_write_reg(dev, MATROX_GET_CONTROL, 0x00);
++}
++
++static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
++{
++ struct matrox_device *dev;
++ int err;
++
++ assert(pdev != NULL);
++ assert(ent != NULL);
++
++ if (pdev->vendor != PCI_VENDOR_ID_MATROX || pdev->device != PCI_DEVICE_ID_MATROX_G400)
++ return -ENODEV;
++
++ dev = kmalloc(sizeof(struct matrox_device) +
++ sizeof(struct w1_bus_master), GFP_KERNEL);
++ if (!dev) {
++ dev_err(&pdev->dev,
++ "%s: Failed to create new matrox_device object.\n",
++ __func__);
++ return -ENOMEM;
++ }
++
++ memset(dev, 0, sizeof(struct matrox_device) + sizeof(struct w1_bus_master));
++
++ dev->bus_master = (struct w1_bus_master *)(dev + 1);
++
++ /*
++ * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c
++ */
++
++ dev->phys_addr = pci_resource_start(pdev, 1);
++
++ dev->virt_addr = ioremap_nocache(dev->phys_addr, 16384);
++ if (!dev->virt_addr) {
++ dev_err(&pdev->dev, "%s: failed to ioremap(0x%lx, %d).\n",
++ __func__, dev->phys_addr, 16384);
++ err = -EIO;
++ goto err_out_free_device;
++ }
++
++ dev->base_addr = dev->virt_addr + MATROX_BASE;
++ dev->port_index = dev->base_addr + MATROX_PORT_INDEX_OFFSET;
++ dev->port_data = dev->base_addr + MATROX_PORT_DATA_OFFSET;
++ dev->data_mask = (MATROX_G400_DDC_DATA);
++
++ matrox_w1_hw_init(dev);
++
++ dev->bus_master->data = dev;
++ dev->bus_master->read_bit = &matrox_w1_read_ddc_bit;
++ dev->bus_master->write_bit = &matrox_w1_write_ddc_bit;
++
++ err = w1_add_master_device(dev->bus_master);
++ if (err)
++ goto err_out_free_device;
++
++ pci_set_drvdata(pdev, dev);
++
++ dev->found = 1;
++
++ dev_info(&pdev->dev, "Matrox G400 GPIO transport layer for 1-wire.\n");
++
++ return 0;
++
++err_out_free_device:
++ kfree(dev);
++
++ return err;
++}
++
++static void __devexit matrox_w1_remove(struct pci_dev *pdev)
++{
++ struct matrox_device *dev = pci_get_drvdata(pdev);
++
++ assert(dev != NULL);
++
++ if (dev->found) {
++ w1_remove_master_device(dev->bus_master);
++ iounmap(dev->virt_addr);
++ }
++ kfree(dev);
++}
++
++static int __init matrox_w1_init(void)
++{
++ return pci_register_driver(&matrox_w1_pci_driver);
++}
++
++static void __exit matrox_w1_fini(void)
++{
++ pci_unregister_driver(&matrox_w1_pci_driver);
++}
++
++module_init(matrox_w1_init);
++module_exit(matrox_w1_fini);
+--- gregkh-2.6.orig/drivers/w1/matrox_w1.c
++++ /dev/null
+@@ -1,247 +0,0 @@
+-/*
+- * matrox_w1.c
+- *
+- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+- *
+- *
+- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#include <asm/atomic.h>
+-#include <asm/types.h>
+-#include <asm/io.h>
+-
+-#include <linux/delay.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/list.h>
+-#include <linux/interrupt.h>
+-#include <linux/spinlock.h>
+-#include <linux/timer.h>
+-#include <linux/slab.h>
+-#include <linux/pci_ids.h>
+-#include <linux/pci.h>
+-#include <linux/timer.h>
+-
+-#include "w1.h"
+-#include "w1_int.h"
+-#include "w1_log.h"
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+-MODULE_DESCRIPTION("Driver for transport(Dallas 1-wire prtocol) over VGA DDC(matrox gpio).");
+-
+-static struct pci_device_id matrox_w1_tbl[] = {
+- { PCI_DEVICE(PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400) },
+- { },
+-};
+-MODULE_DEVICE_TABLE(pci, matrox_w1_tbl);
+-
+-static int __devinit matrox_w1_probe(struct pci_dev *, const struct pci_device_id *);
+-static void __devexit matrox_w1_remove(struct pci_dev *);
+-
+-static struct pci_driver matrox_w1_pci_driver = {
+- .name = "matrox_w1",
+- .id_table = matrox_w1_tbl,
+- .probe = matrox_w1_probe,
+- .remove = __devexit_p(matrox_w1_remove),
+-};
+-
+-/*
+- * Matrox G400 DDC registers.
+- */
+-
+-#define MATROX_G400_DDC_CLK (1<<4)
+-#define MATROX_G400_DDC_DATA (1<<1)
+-
+-#define MATROX_BASE 0x3C00
+-#define MATROX_STATUS 0x1e14
+-
+-#define MATROX_PORT_INDEX_OFFSET 0x00
+-#define MATROX_PORT_DATA_OFFSET 0x0A
+-
+-#define MATROX_GET_CONTROL 0x2A
+-#define MATROX_GET_DATA 0x2B
+-#define MATROX_CURSOR_CTL 0x06
+-
+-struct matrox_device
+-{
+- void __iomem *base_addr;
+- void __iomem *port_index;
+- void __iomem *port_data;
+- u8 data_mask;
+-
+- unsigned long phys_addr;
+- void __iomem *virt_addr;
+- unsigned long found;
+-
+- struct w1_bus_master *bus_master;
+-};
+-
+-static u8 matrox_w1_read_ddc_bit(void *);
+-static void matrox_w1_write_ddc_bit(void *, u8);
+-
+-/*
+- * These functions read and write DDC Data bit.
+- *
+- * Using tristate pins, since i can't find any open-drain pin in whole motherboard.
+- * Unfortunately we can't connect to Intel's 82801xx IO controller
+- * since we don't know motherboard schema, wich has pretty unused(may be not) GPIO.
+- *
+- * I've heard that PIIX also has open drain pin.
+- *
+- * Port mapping.
+- */
+-static __inline__ u8 matrox_w1_read_reg(struct matrox_device *dev, u8 reg)
+-{
+- u8 ret;
+-
+- writeb(reg, dev->port_index);
+- ret = readb(dev->port_data);
+- barrier();
+-
+- return ret;
+-}
+-
+-static __inline__ void matrox_w1_write_reg(struct matrox_device *dev, u8 reg, u8 val)
+-{
+- writeb(reg, dev->port_index);
+- writeb(val, dev->port_data);
+- wmb();
+-}
+-
+-static void matrox_w1_write_ddc_bit(void *data, u8 bit)
+-{
+- u8 ret;
+- struct matrox_device *dev = data;
+-
+- if (bit)
+- bit = 0;
+- else
+- bit = dev->data_mask;
+-
+- ret = matrox_w1_read_reg(dev, MATROX_GET_CONTROL);
+- matrox_w1_write_reg(dev, MATROX_GET_CONTROL, ((ret & ~dev->data_mask) | bit));
+- matrox_w1_write_reg(dev, MATROX_GET_DATA, 0x00);
+-}
+-
+-static u8 matrox_w1_read_ddc_bit(void *data)
+-{
+- u8 ret;
+- struct matrox_device *dev = data;
+-
+- ret = matrox_w1_read_reg(dev, MATROX_GET_DATA);
+-
+- return ret;
+-}
+-
+-static void matrox_w1_hw_init(struct matrox_device *dev)
+-{
+- matrox_w1_write_reg(dev, MATROX_GET_DATA, 0xFF);
+- matrox_w1_write_reg(dev, MATROX_GET_CONTROL, 0x00);
+-}
+-
+-static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+-{
+- struct matrox_device *dev;
+- int err;
+-
+- assert(pdev != NULL);
+- assert(ent != NULL);
+-
+- if (pdev->vendor != PCI_VENDOR_ID_MATROX || pdev->device != PCI_DEVICE_ID_MATROX_G400)
+- return -ENODEV;
+-
+- dev = kmalloc(sizeof(struct matrox_device) +
+- sizeof(struct w1_bus_master), GFP_KERNEL);
+- if (!dev) {
+- dev_err(&pdev->dev,
+- "%s: Failed to create new matrox_device object.\n",
+- __func__);
+- return -ENOMEM;
+- }
+-
+- memset(dev, 0, sizeof(struct matrox_device) + sizeof(struct w1_bus_master));
+-
+- dev->bus_master = (struct w1_bus_master *)(dev + 1);
+-
+- /*
+- * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c
+- */
+-
+- dev->phys_addr = pci_resource_start(pdev, 1);
+-
+- dev->virt_addr = ioremap_nocache(dev->phys_addr, 16384);
+- if (!dev->virt_addr) {
+- dev_err(&pdev->dev, "%s: failed to ioremap(0x%lx, %d).\n",
+- __func__, dev->phys_addr, 16384);
+- err = -EIO;
+- goto err_out_free_device;
+- }
+-
+- dev->base_addr = dev->virt_addr + MATROX_BASE;
+- dev->port_index = dev->base_addr + MATROX_PORT_INDEX_OFFSET;
+- dev->port_data = dev->base_addr + MATROX_PORT_DATA_OFFSET;
+- dev->data_mask = (MATROX_G400_DDC_DATA);
+-
+- matrox_w1_hw_init(dev);
+-
+- dev->bus_master->data = dev;
+- dev->bus_master->read_bit = &matrox_w1_read_ddc_bit;
+- dev->bus_master->write_bit = &matrox_w1_write_ddc_bit;
+-
+- err = w1_add_master_device(dev->bus_master);
+- if (err)
+- goto err_out_free_device;
+-
+- pci_set_drvdata(pdev, dev);
+-
+- dev->found = 1;
+-
+- dev_info(&pdev->dev, "Matrox G400 GPIO transport layer for 1-wire.\n");
+-
+- return 0;
+-
+-err_out_free_device:
+- kfree(dev);
+-
+- return err;
+-}
+-
+-static void __devexit matrox_w1_remove(struct pci_dev *pdev)
+-{
+- struct matrox_device *dev = pci_get_drvdata(pdev);
+-
+- assert(dev != NULL);
+-
+- if (dev->found) {
+- w1_remove_master_device(dev->bus_master);
+- iounmap(dev->virt_addr);
+- }
+- kfree(dev);
+-}
+-
+-static int __init matrox_w1_init(void)
+-{
+- return pci_register_driver(&matrox_w1_pci_driver);
+-}
+-
+-static void __exit matrox_w1_fini(void)
+-{
+- pci_unregister_driver(&matrox_w1_pci_driver);
+-}
+-
+-module_init(matrox_w1_init);
+-module_exit(matrox_w1_fini);
+--- /dev/null
++++ gregkh-2.6/drivers/w1/slaves/Kconfig
+@@ -0,0 +1,38 @@
++#
++# 1-wire slaves configuration
++#
++
++menu "1-wire Slaves"
++ depends on W1
++
++config W1_SLAVE_THERM
++ tristate "Thermal family implementation"
++ depends on W1
++ help
++ Say Y here if you want to connect 1-wire thermal sensors to you
++ wire.
++
++config W1_SLAVE_SMEM
++ tristate "Simple 64bit memory family implementation"
++ depends on W1
++ help
++ Say Y here if you want to connect 1-wire
++ simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
++
++config W1_SLAVE_DS2433
++ tristate "4kb EEPROM family support (DS2433)"
++ depends on W1
++ help
++ Say Y here if you want to use a 1-wire
++ 4kb EEPROM family device (DS2433).
++
++config W1_SLAVE_DS2433_CRC
++ bool "Protect DS2433 data with a CRC16"
++ depends on W1_DS2433
++ select CRC16
++ help
++ Say Y here to protect DS2433 data with a CRC16.
++ Each block has 30 bytes of data and a two byte CRC16.
++ Full block writes are only allowed if the CRC is valid.
++
++endmenu
+--- /dev/null
++++ gregkh-2.6/drivers/w1/slaves/Makefile
+@@ -0,0 +1,12 @@
++#
++# Makefile for the Dallas's 1-wire slaves.
++#
++
++ifeq ($(CONFIG_W1_SLAVE_DS2433_CRC), y)
++EXTRA_CFLAGS += -DCONFIG_W1_F23_CRC
++endif
++
++obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o
++obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o
++obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o
++
+--- /dev/null
++++ gregkh-2.6/drivers/w1/slaves/w1_ds2433.c
+@@ -0,0 +1,329 @@
++/*
++ * w1_ds2433.c - w1 family 23 (DS2433) driver
++ *
++ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
++ *
++ * This source code is licensed under the GNU General Public License,
++ * Version 2. See the file COPYING for more details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/device.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#ifdef CONFIG_W1_F23_CRC
++#include <linux/crc16.h>
++
++#define CRC16_INIT 0
++#define CRC16_VALID 0xb001
++
++#endif
++
++#include "../w1.h"
++#include "../w1_io.h"
++#include "../w1_int.h"
++#include "../w1_family.h"
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
++MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM");
++
++#define W1_EEPROM_SIZE 512
++#define W1_PAGE_COUNT 16
++#define W1_PAGE_SIZE 32
++#define W1_PAGE_BITS 5
++#define W1_PAGE_MASK 0x1F
++
++#define W1_F23_TIME 300
++
++#define W1_F23_READ_EEPROM 0xF0
++#define W1_F23_WRITE_SCRATCH 0x0F
++#define W1_F23_READ_SCRATCH 0xAA
++#define W1_F23_COPY_SCRATCH 0x55
++
++struct w1_f23_data {
++ u8 memory[W1_EEPROM_SIZE];
++ u32 validcrc;
++};
++
++/**
++ * Check the file size bounds and adjusts count as needed.
++ * This would not be needed if the file size didn't reset to 0 after a write.
++ */
++static inline size_t w1_f23_fix_count(loff_t off, size_t count, size_t size)
++{
++ if (off > size)
++ return 0;
++
++ if ((off + count) > size)
++ return (size - off);
++
++ return count;
++}
++
++#ifdef CONFIG_W1_F23_CRC
++static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
++ int block)
++{
++ u8 wrbuf[3];
++ int off = block * W1_PAGE_SIZE;
++
++ if (data->validcrc & (1 << block))
++ return 0;
++
++ if (w1_reset_select_slave(sl)) {
++ data->validcrc = 0;
++ return -EIO;
++ }
++
++ wrbuf[0] = W1_F23_READ_EEPROM;
++ wrbuf[1] = off & 0xff;
++ wrbuf[2] = off >> 8;
++ w1_write_block(sl->master, wrbuf, 3);
++ w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE);
++
++ /* cache the block if the CRC is valid */
++ if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID)
++ data->validcrc |= (1 << block);
++
++ return 0;
++}
++#endif /* CONFIG_W1_F23_CRC */
++
++static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
++ size_t count)
++{
++ struct w1_slave *sl = kobj_to_w1_slave(kobj);
++#ifdef CONFIG_W1_F23_CRC
++ struct w1_f23_data *data = sl->family_data;
++ int i, min_page, max_page;
++#else
++ u8 wrbuf[3];
++#endif
++
++ if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
++ return 0;
++
++ atomic_inc(&sl->refcnt);
++ if (down_interruptible(&sl->master->mutex)) {
++ count = 0;
++ goto out_dec;
++ }
++
++#ifdef CONFIG_W1_F23_CRC
++
++ min_page = (off >> W1_PAGE_BITS);
++ max_page = (off + count - 1) >> W1_PAGE_BITS;
++ for (i = min_page; i <= max_page; i++) {
++ if (w1_f23_refresh_block(sl, data, i)) {
++ count = -EIO;
++ goto out_up;
++ }
++ }
++ memcpy(buf, &data->memory[off], count);
++
++#else /* CONFIG_W1_F23_CRC */
++
++ /* read directly from the EEPROM */
++ if (w1_reset_select_slave(sl)) {
++ count = -EIO;
++ goto out_up;
++ }
++
++ wrbuf[0] = W1_F23_READ_EEPROM;
++ wrbuf[1] = off & 0xff;
++ wrbuf[2] = off >> 8;
++ w1_write_block(sl->master, wrbuf, 3);
++ w1_read_block(sl->master, buf, count);
++
++#endif /* CONFIG_W1_F23_CRC */
++
++out_up:
++ up(&sl->master->mutex);
++out_dec:
++ atomic_dec(&sl->refcnt);
++
++ return count;
++}
++
++/**
++ * Writes to the scratchpad and reads it back for verification.
++ * Then copies the scratchpad to EEPROM.
++ * The data must be on one page.
++ * The master must be locked.
++ *
++ * @param sl The slave structure
++ * @param addr Address for the write
++ * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
++ * @param data The data to write
++ * @return 0=Success -1=failure
++ */
++static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
++{
++ u8 wrbuf[4];
++ u8 rdbuf[W1_PAGE_SIZE + 3];
++ u8 es = (addr + len - 1) & 0x1f;
++
++ /* Write the data to the scratchpad */
++ if (w1_reset_select_slave(sl))
++ return -1;
++
++ wrbuf[0] = W1_F23_WRITE_SCRATCH;
++ wrbuf[1] = addr & 0xff;
++ wrbuf[2] = addr >> 8;
++
++ w1_write_block(sl->master, wrbuf, 3);
++ w1_write_block(sl->master, data, len);
++
++ /* Read the scratchpad and verify */
++ if (w1_reset_select_slave(sl))
++ return -1;
++
++ w1_write_8(sl->master, W1_F23_READ_SCRATCH);
++ w1_read_block(sl->master, rdbuf, len + 3);
++
++ /* Compare what was read against the data written */
++ if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) ||
++ (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0))
++ return -1;
++
++ /* Copy the scratchpad to EEPROM */
++ if (w1_reset_select_slave(sl))
++ return -1;
++
++ wrbuf[0] = W1_F23_COPY_SCRATCH;
++ wrbuf[3] = es;
++ w1_write_block(sl->master, wrbuf, 4);
++
++ /* Sleep for 5 ms to wait for the write to complete */
++ msleep(5);
++
++ /* Reset the bus to wake up the EEPROM (this may not be needed) */
++ w1_reset_bus(sl->master);
++
++ return 0;
++}
++
++static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
++ size_t count)
++{
++ struct w1_slave *sl = kobj_to_w1_slave(kobj);
++ int addr, len, idx;
++
++ if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
++ return 0;
++
++#ifdef CONFIG_W1_F23_CRC
++ /* can only write full blocks in cached mode */
++ if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
++ dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
++ (int)off, count);
++ return -EINVAL;
++ }
++
++ /* make sure the block CRCs are valid */
++ for (idx = 0; idx < count; idx += W1_PAGE_SIZE) {
++ if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE) != CRC16_VALID) {
++ dev_err(&sl->dev, "bad CRC at offset %d\n", (int)off);
++ return -EINVAL;
++ }
++ }
++#endif /* CONFIG_W1_F23_CRC */
++
++ atomic_inc(&sl->refcnt);
++ if (down_interruptible(&sl->master->mutex)) {
++ count = 0;
++ goto out_dec;
++ }
++
++ /* Can only write data to one page at a time */
++ idx = 0;
++ while (idx < count) {
++ addr = off + idx;
++ len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK);
++ if (len > (count - idx))
++ len = count - idx;
++
++ if (w1_f23_write(sl, addr, len, &buf[idx]) < 0) {
++ count = -EIO;
++ goto out_up;
++ }
++ idx += len;
++ }
++
++out_up:
++ up(&sl->master->mutex);
++out_dec:
++ atomic_dec(&sl->refcnt);
++
++ return count;
++}
++
++static struct bin_attribute w1_f23_bin_attr = {
++ .attr = {
++ .name = "eeprom",
++ .mode = S_IRUGO | S_IWUSR,
++ .owner = THIS_MODULE,
++ },
++ .size = W1_EEPROM_SIZE,
++ .read = w1_f23_read_bin,
++ .write = w1_f23_write_bin,
++};
++
++static int w1_f23_add_slave(struct w1_slave *sl)
++{
++ int err;
++#ifdef CONFIG_W1_F23_CRC
++ struct w1_f23_data *data;
++
++ data = kmalloc(sizeof(struct w1_f23_data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++ memset(data, 0, sizeof(struct w1_f23_data));
++ sl->family_data = data;
++
++#endif /* CONFIG_W1_F23_CRC */
++
++ err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
++
++#ifdef CONFIG_W1_F23_CRC
++ if (err)
++ kfree(data);
++#endif /* CONFIG_W1_F23_CRC */
++
++ return err;
++}
++
++static void w1_f23_remove_slave(struct w1_slave *sl)
++{
++#ifdef CONFIG_W1_F23_CRC
++ kfree(sl->family_data);
++ sl->family_data = NULL;
++#endif /* CONFIG_W1_F23_CRC */
++ sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
++}
++
++static struct w1_family_ops w1_f23_fops = {
++ .add_slave = w1_f23_add_slave,
++ .remove_slave = w1_f23_remove_slave,
++};
++
++static struct w1_family w1_family_23 = {
++ .fid = W1_EEPROM_DS2433,
++ .fops = &w1_f23_fops,
++};
++
++static int __init w1_f23_init(void)
++{
++ return w1_register_family(&w1_family_23);
++}
++
++static void __exit w1_f23_fini(void)
++{
++ w1_unregister_family(&w1_family_23);
++}
++
++module_init(w1_f23_init);
++module_exit(w1_f23_fini);
+--- /dev/null
++++ gregkh-2.6/drivers/w1/slaves/w1_smem.c
+@@ -0,0 +1,71 @@
++/*
++ * w1_smem.c
++ *
++ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the smems 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <asm/types.h>
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/device.h>
++#include <linux/types.h>
++
++#include "../w1.h"
++#include "../w1_io.h"
++#include "../w1_int.h"
++#include "../w1_family.h"
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
++MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
++
++static struct w1_family w1_smem_family_01 = {
++ .fid = W1_FAMILY_SMEM_01,
++};
++
++static struct w1_family w1_smem_family_81 = {
++ .fid = W1_FAMILY_SMEM_81,
++};
++
++static int __init w1_smem_init(void)
++{
++ int err;
++
++ err = w1_register_family(&w1_smem_family_01);
++ if (err)
++ return err;
++
++ err = w1_register_family(&w1_smem_family_81);
++ if (err) {
++ w1_unregister_family(&w1_smem_family_01);
++ return err;
++ }
++
++ return 0;
++}
++
++static void __exit w1_smem_fini(void)
++{
++ w1_unregister_family(&w1_smem_family_01);
++ w1_unregister_family(&w1_smem_family_81);
++}
++
++module_init(w1_smem_init);
++module_exit(w1_smem_fini);
+--- /dev/null
++++ gregkh-2.6/drivers/w1/slaves/w1_therm.c
+@@ -0,0 +1,268 @@
++/*
++ * w1_therm.c
++ *
++ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the therms 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <asm/types.h>
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/device.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++
++#include "../w1.h"
++#include "../w1_io.h"
++#include "../w1_int.h"
++#include "../w1_family.h"
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
++MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
++
++static u8 bad_roms[][9] = {
++ {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87},
++ {}
++ };
++
++static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
++
++static struct bin_attribute w1_therm_bin_attr = {
++ .attr = {
++ .name = "w1_slave",
++ .mode = S_IRUGO,
++ .owner = THIS_MODULE,
++ },
++ .size = W1_SLAVE_DATA_SIZE,
++ .read = w1_therm_read_bin,
++};
++
++static int w1_therm_add_slave(struct w1_slave *sl)
++{
++ return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
++}
++
++static void w1_therm_remove_slave(struct w1_slave *sl)
++{
++ sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
++}
++
++static struct w1_family_ops w1_therm_fops = {
++ .add_slave = w1_therm_add_slave,
++ .remove_slave = w1_therm_remove_slave,
++};
++
++static struct w1_family w1_therm_family_DS18S20 = {
++ .fid = W1_THERM_DS18S20,
++ .fops = &w1_therm_fops,
++};
++
++static struct w1_family w1_therm_family_DS18B20 = {
++ .fid = W1_THERM_DS18B20,
++ .fops = &w1_therm_fops,
++};
++
++static struct w1_family w1_therm_family_DS1822 = {
++ .fid = W1_THERM_DS1822,
++ .fops = &w1_therm_fops,
++};
++
++struct w1_therm_family_converter
++{
++ u8 broken;
++ u16 reserved;
++ struct w1_family *f;
++ int (*convert)(u8 rom[9]);
++};
++
++static inline int w1_DS18B20_convert_temp(u8 rom[9]);
++static inline int w1_DS18S20_convert_temp(u8 rom[9]);
++
++static struct w1_therm_family_converter w1_therm_families[] = {
++ {
++ .f = &w1_therm_family_DS18S20,
++ .convert = w1_DS18S20_convert_temp
++ },
++ {
++ .f = &w1_therm_family_DS1822,
++ .convert = w1_DS18B20_convert_temp
++ },
++ {
++ .f = &w1_therm_family_DS18B20,
++ .convert = w1_DS18B20_convert_temp
++ },
++};
++
++static inline int w1_DS18B20_convert_temp(u8 rom[9])
++{
++ int t = (rom[1] << 8) | rom[0];
++ t /= 16;
++ return t;
++}
++
++static inline int w1_DS18S20_convert_temp(u8 rom[9])
++{
++ int t, h;
++
++ if (!rom[7])
++ return 0;
++
++ if (rom[1] == 0)
++ t = ((s32)rom[0] >> 1)*1000;
++ else
++ t = 1000*(-1*(s32)(0x100-rom[0]) >> 1);
++
++ t -= 250;
++ h = 1000*((s32)rom[7] - (s32)rom[6]);
++ h /= (s32)rom[7];
++ t += h;
++
++ return t;
++}
++
++static inline int w1_convert_temp(u8 rom[9], u8 fid)
++{
++ int i;
++
++ for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
++ if (w1_therm_families[i].f->fid == fid)
++ return w1_therm_families[i].convert(rom);
++
++ return 0;
++}
++
++static int w1_therm_check_rom(u8 rom[9])
++{
++ int i;
++
++ for (i=0; i<sizeof(bad_roms)/9; ++i)
++ if (!memcmp(bad_roms[i], rom, 9))
++ return 1;
++
++ return 0;
++}
++
++static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
++{
++ struct w1_slave *sl = kobj_to_w1_slave(kobj);
++ struct w1_master *dev = sl->master;
++ u8 rom[9], crc, verdict;
++ int i, max_trying = 10;
++
++ atomic_inc(&sl->refcnt);
++ smp_mb__after_atomic_inc();
++ if (down_interruptible(&sl->master->mutex)) {
++ count = 0;
++ goto out_dec;
++ }
++
++ if (off > W1_SLAVE_DATA_SIZE) {
++ count = 0;
++ goto out;
++ }
++ if (off + count > W1_SLAVE_DATA_SIZE) {
++ count = 0;
++ goto out;
++ }
++
++ memset(buf, 0, count);
++ memset(rom, 0, sizeof(rom));
++
++ count = 0;
++ verdict = 0;
++ crc = 0;
++
++ while (max_trying--) {
++ if (!w1_reset_select_slave(sl)) {
++ int count = 0;
++ unsigned int tm = 750;
++
++ w1_write_8(dev, W1_CONVERT_TEMP);
++
++ while (tm) {
++ tm = msleep_interruptible(tm);
++ if (signal_pending(current))
++ flush_signals(current);
++ }
++
++ if (!w1_reset_select_slave(sl)) {
++
++ w1_write_8(dev, W1_READ_SCRATCHPAD);
++ if ((count = w1_read_block(dev, rom, 9)) != 9) {
++ dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
++ }
++
++ crc = w1_calc_crc8(rom, 8);
++
++ if (rom[8] == crc && rom[0])
++ verdict = 1;
++ }
++ }
++
++ if (!w1_therm_check_rom(rom))
++ break;
++ }
++
++ for (i = 0; i < 9; ++i)
++ count += sprintf(buf + count, "%02x ", rom[i]);
++ count += sprintf(buf + count, ": crc=%02x %s\n",
++ crc, (verdict) ? "YES" : "NO");
++ if (verdict)
++ memcpy(sl->rom, rom, sizeof(sl->rom));
++ else
++ dev_warn(&dev->dev, "18S20 doesn't respond to CONVERT_TEMP.\n");
++
++ for (i = 0; i < 9; ++i)
++ count += sprintf(buf + count, "%02x ", sl->rom[i]);
++
++ count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid));
++out:
++ up(&dev->mutex);
++out_dec:
++ smp_mb__before_atomic_inc();
++ atomic_dec(&sl->refcnt);
++
++ return count;
++}
++
++static int __init w1_therm_init(void)
++{
++ int err, i;
++
++ for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i) {
++ err = w1_register_family(w1_therm_families[i].f);
++ if (err)
++ w1_therm_families[i].broken = 1;
++ }
++
++ return 0;
++}
++
++static void __exit w1_therm_fini(void)
++{
++ int i;
++
++ for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
++ if (!w1_therm_families[i].broken)
++ w1_unregister_family(w1_therm_families[i].f);
++}
++
++module_init(w1_therm_init);
++module_exit(w1_therm_fini);
+--- gregkh-2.6.orig/drivers/w1/w1_ds2433.c
++++ /dev/null
+@@ -1,329 +0,0 @@
+-/*
+- * w1_ds2433.c - w1 family 23 (DS2433) driver
+- *
+- * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+- *
+- * This source code is licensed under the GNU General Public License,
+- * Version 2. See the file COPYING for more details.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/device.h>
+-#include <linux/types.h>
+-#include <linux/delay.h>
+-#ifdef CONFIG_W1_F23_CRC
+-#include <linux/crc16.h>
+-
+-#define CRC16_INIT 0
+-#define CRC16_VALID 0xb001
+-
+-#endif
+-
+-#include "w1.h"
+-#include "w1_io.h"
+-#include "w1_int.h"
+-#include "w1_family.h"
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+-MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM");
+-
+-#define W1_EEPROM_SIZE 512
+-#define W1_PAGE_COUNT 16
+-#define W1_PAGE_SIZE 32
+-#define W1_PAGE_BITS 5
+-#define W1_PAGE_MASK 0x1F
+-
+-#define W1_F23_TIME 300
+-
+-#define W1_F23_READ_EEPROM 0xF0
+-#define W1_F23_WRITE_SCRATCH 0x0F
+-#define W1_F23_READ_SCRATCH 0xAA
+-#define W1_F23_COPY_SCRATCH 0x55
+-
+-struct w1_f23_data {
+- u8 memory[W1_EEPROM_SIZE];
+- u32 validcrc;
+-};
+-
+-/**
+- * Check the file size bounds and adjusts count as needed.
+- * This would not be needed if the file size didn't reset to 0 after a write.
+- */
+-static inline size_t w1_f23_fix_count(loff_t off, size_t count, size_t size)
+-{
+- if (off > size)
+- return 0;
+-
+- if ((off + count) > size)
+- return (size - off);
+-
+- return count;
+-}
+-
+-#ifdef CONFIG_W1_F23_CRC
+-static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
+- int block)
+-{
+- u8 wrbuf[3];
+- int off = block * W1_PAGE_SIZE;
+-
+- if (data->validcrc & (1 << block))
+- return 0;
+-
+- if (w1_reset_select_slave(sl)) {
+- data->validcrc = 0;
+- return -EIO;
+- }
+-
+- wrbuf[0] = W1_F23_READ_EEPROM;
+- wrbuf[1] = off & 0xff;
+- wrbuf[2] = off >> 8;
+- w1_write_block(sl->master, wrbuf, 3);
+- w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE);
+-
+- /* cache the block if the CRC is valid */
+- if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID)
+- data->validcrc |= (1 << block);
+-
+- return 0;
+-}
+-#endif /* CONFIG_W1_F23_CRC */
+-
+-static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
+- size_t count)
+-{
+- struct w1_slave *sl = kobj_to_w1_slave(kobj);
+-#ifdef CONFIG_W1_F23_CRC
+- struct w1_f23_data *data = sl->family_data;
+- int i, min_page, max_page;
+-#else
+- u8 wrbuf[3];
+-#endif
+-
+- if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
+- return 0;
+-
+- atomic_inc(&sl->refcnt);
+- if (down_interruptible(&sl->master->mutex)) {
+- count = 0;
+- goto out_dec;
+- }
+-
+-#ifdef CONFIG_W1_F23_CRC
+-
+- min_page = (off >> W1_PAGE_BITS);
+- max_page = (off + count - 1) >> W1_PAGE_BITS;
+- for (i = min_page; i <= max_page; i++) {
+- if (w1_f23_refresh_block(sl, data, i)) {
+- count = -EIO;
+- goto out_up;
+- }
+- }
+- memcpy(buf, &data->memory[off], count);
+-
+-#else /* CONFIG_W1_F23_CRC */
+-
+- /* read directly from the EEPROM */
+- if (w1_reset_select_slave(sl)) {
+- count = -EIO;
+- goto out_up;
+- }
+-
+- wrbuf[0] = W1_F23_READ_EEPROM;
+- wrbuf[1] = off & 0xff;
+- wrbuf[2] = off >> 8;
+- w1_write_block(sl->master, wrbuf, 3);
+- w1_read_block(sl->master, buf, count);
+-
+-#endif /* CONFIG_W1_F23_CRC */
+-
+-out_up:
+- up(&sl->master->mutex);
+-out_dec:
+- atomic_dec(&sl->refcnt);
+-
+- return count;
+-}
+-
+-/**
+- * Writes to the scratchpad and reads it back for verification.
+- * Then copies the scratchpad to EEPROM.
+- * The data must be on one page.
+- * The master must be locked.
+- *
+- * @param sl The slave structure
+- * @param addr Address for the write
+- * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
+- * @param data The data to write
+- * @return 0=Success -1=failure
+- */
+-static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
+-{
+- u8 wrbuf[4];
+- u8 rdbuf[W1_PAGE_SIZE + 3];
+- u8 es = (addr + len - 1) & 0x1f;
+-
+- /* Write the data to the scratchpad */
+- if (w1_reset_select_slave(sl))
+- return -1;
+-
+- wrbuf[0] = W1_F23_WRITE_SCRATCH;
+- wrbuf[1] = addr & 0xff;
+- wrbuf[2] = addr >> 8;
+-
+- w1_write_block(sl->master, wrbuf, 3);
+- w1_write_block(sl->master, data, len);
+-
+- /* Read the scratchpad and verify */
+- if (w1_reset_select_slave(sl))
+- return -1;
+-
+- w1_write_8(sl->master, W1_F23_READ_SCRATCH);
+- w1_read_block(sl->master, rdbuf, len + 3);
+-
+- /* Compare what was read against the data written */
+- if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) ||
+- (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0))
+- return -1;
+-
+- /* Copy the scratchpad to EEPROM */
+- if (w1_reset_select_slave(sl))
+- return -1;
+-
+- wrbuf[0] = W1_F23_COPY_SCRATCH;
+- wrbuf[3] = es;
+- w1_write_block(sl->master, wrbuf, 4);
+-
+- /* Sleep for 5 ms to wait for the write to complete */
+- msleep(5);
+-
+- /* Reset the bus to wake up the EEPROM (this may not be needed) */
+- w1_reset_bus(sl->master);
+-
+- return 0;
+-}
+-
+-static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
+- size_t count)
+-{
+- struct w1_slave *sl = kobj_to_w1_slave(kobj);
+- int addr, len, idx;
+-
+- if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
+- return 0;
+-
+-#ifdef CONFIG_W1_F23_CRC
+- /* can only write full blocks in cached mode */
+- if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
+- dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
+- (int)off, count);
+- return -EINVAL;
+- }
+-
+- /* make sure the block CRCs are valid */
+- for (idx = 0; idx < count; idx += W1_PAGE_SIZE) {
+- if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE) != CRC16_VALID) {
+- dev_err(&sl->dev, "bad CRC at offset %d\n", (int)off);
+- return -EINVAL;
+- }
+- }
+-#endif /* CONFIG_W1_F23_CRC */
+-
+- atomic_inc(&sl->refcnt);
+- if (down_interruptible(&sl->master->mutex)) {
+- count = 0;
+- goto out_dec;
+- }
+-
+- /* Can only write data to one page at a time */
+- idx = 0;
+- while (idx < count) {
+- addr = off + idx;
+- len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK);
+- if (len > (count - idx))
+- len = count - idx;
+-
+- if (w1_f23_write(sl, addr, len, &buf[idx]) < 0) {
+- count = -EIO;
+- goto out_up;
+- }
+- idx += len;
+- }
+-
+-out_up:
+- up(&sl->master->mutex);
+-out_dec:
+- atomic_dec(&sl->refcnt);
+-
+- return count;
+-}
+-
+-static struct bin_attribute w1_f23_bin_attr = {
+- .attr = {
+- .name = "eeprom",
+- .mode = S_IRUGO | S_IWUSR,
+- .owner = THIS_MODULE,
+- },
+- .size = W1_EEPROM_SIZE,
+- .read = w1_f23_read_bin,
+- .write = w1_f23_write_bin,
+-};
+-
+-static int w1_f23_add_slave(struct w1_slave *sl)
+-{
+- int err;
+-#ifdef CONFIG_W1_F23_CRC
+- struct w1_f23_data *data;
+-
+- data = kmalloc(sizeof(struct w1_f23_data), GFP_KERNEL);
+- if (!data)
+- return -ENOMEM;
+- memset(data, 0, sizeof(struct w1_f23_data));
+- sl->family_data = data;
+-
+-#endif /* CONFIG_W1_F23_CRC */
+-
+- err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
+-
+-#ifdef CONFIG_W1_F23_CRC
+- if (err)
+- kfree(data);
+-#endif /* CONFIG_W1_F23_CRC */
+-
+- return err;
+-}
+-
+-static void w1_f23_remove_slave(struct w1_slave *sl)
+-{
+-#ifdef CONFIG_W1_F23_CRC
+- kfree(sl->family_data);
+- sl->family_data = NULL;
+-#endif /* CONFIG_W1_F23_CRC */
+- sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
+-}
+-
+-static struct w1_family_ops w1_f23_fops = {
+- .add_slave = w1_f23_add_slave,
+- .remove_slave = w1_f23_remove_slave,
+-};
+-
+-static struct w1_family w1_family_23 = {
+- .fid = W1_EEPROM_DS2433,
+- .fops = &w1_f23_fops,
+-};
+-
+-static int __init w1_f23_init(void)
+-{
+- return w1_register_family(&w1_family_23);
+-}
+-
+-static void __exit w1_f23_fini(void)
+-{
+- w1_unregister_family(&w1_family_23);
+-}
+-
+-module_init(w1_f23_init);
+-module_exit(w1_f23_fini);
+--- gregkh-2.6.orig/drivers/w1/w1_smem.c
++++ /dev/null
+@@ -1,71 +0,0 @@
+-/*
+- * w1_smem.c
+- *
+- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+- *
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the smems 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#include <asm/types.h>
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/device.h>
+-#include <linux/types.h>
+-
+-#include "w1.h"
+-#include "w1_io.h"
+-#include "w1_int.h"
+-#include "w1_family.h"
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+-MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
+-
+-static struct w1_family w1_smem_family_01 = {
+- .fid = W1_FAMILY_SMEM_01,
+-};
+-
+-static struct w1_family w1_smem_family_81 = {
+- .fid = W1_FAMILY_SMEM_81,
+-};
+-
+-static int __init w1_smem_init(void)
+-{
+- int err;
+-
+- err = w1_register_family(&w1_smem_family_01);
+- if (err)
+- return err;
+-
+- err = w1_register_family(&w1_smem_family_81);
+- if (err) {
+- w1_unregister_family(&w1_smem_family_01);
+- return err;
+- }
+-
+- return 0;
+-}
+-
+-static void __exit w1_smem_fini(void)
+-{
+- w1_unregister_family(&w1_smem_family_01);
+- w1_unregister_family(&w1_smem_family_81);
+-}
+-
+-module_init(w1_smem_init);
+-module_exit(w1_smem_fini);
+--- gregkh-2.6.orig/drivers/w1/w1_therm.c
++++ /dev/null
+@@ -1,268 +0,0 @@
+-/*
+- * w1_therm.c
+- *
+- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+- *
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the therms 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#include <asm/types.h>
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/device.h>
+-#include <linux/types.h>
+-#include <linux/delay.h>
+-
+-#include "w1.h"
+-#include "w1_io.h"
+-#include "w1_int.h"
+-#include "w1_family.h"
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+-MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
+-
+-static u8 bad_roms[][9] = {
+- {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87},
+- {}
+- };
+-
+-static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
+-
+-static struct bin_attribute w1_therm_bin_attr = {
+- .attr = {
+- .name = "w1_slave",
+- .mode = S_IRUGO,
+- .owner = THIS_MODULE,
+- },
+- .size = W1_SLAVE_DATA_SIZE,
+- .read = w1_therm_read_bin,
+-};
+-
+-static int w1_therm_add_slave(struct w1_slave *sl)
+-{
+- return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+-}
+-
+-static void w1_therm_remove_slave(struct w1_slave *sl)
+-{
+- sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+-}
+-
+-static struct w1_family_ops w1_therm_fops = {
+- .add_slave = w1_therm_add_slave,
+- .remove_slave = w1_therm_remove_slave,
+-};
+-
+-static struct w1_family w1_therm_family_DS18S20 = {
+- .fid = W1_THERM_DS18S20,
+- .fops = &w1_therm_fops,
+-};
+-
+-static struct w1_family w1_therm_family_DS18B20 = {
+- .fid = W1_THERM_DS18B20,
+- .fops = &w1_therm_fops,
+-};
+-
+-static struct w1_family w1_therm_family_DS1822 = {
+- .fid = W1_THERM_DS1822,
+- .fops = &w1_therm_fops,
+-};
+-
+-struct w1_therm_family_converter
+-{
+- u8 broken;
+- u16 reserved;
+- struct w1_family *f;
+- int (*convert)(u8 rom[9]);
+-};
+-
+-static inline int w1_DS18B20_convert_temp(u8 rom[9]);
+-static inline int w1_DS18S20_convert_temp(u8 rom[9]);
+-
+-static struct w1_therm_family_converter w1_therm_families[] = {
+- {
+- .f = &w1_therm_family_DS18S20,
+- .convert = w1_DS18S20_convert_temp
+- },
+- {
+- .f = &w1_therm_family_DS1822,
+- .convert = w1_DS18B20_convert_temp
+- },
+- {
+- .f = &w1_therm_family_DS18B20,
+- .convert = w1_DS18B20_convert_temp
+- },
+-};
+-
+-static inline int w1_DS18B20_convert_temp(u8 rom[9])
+-{
+- int t = (rom[1] << 8) | rom[0];
+- t /= 16;
+- return t;
+-}
+-
+-static inline int w1_DS18S20_convert_temp(u8 rom[9])
+-{
+- int t, h;
+-
+- if (!rom[7])
+- return 0;
+-
+- if (rom[1] == 0)
+- t = ((s32)rom[0] >> 1)*1000;
+- else
+- t = 1000*(-1*(s32)(0x100-rom[0]) >> 1);
+-
+- t -= 250;
+- h = 1000*((s32)rom[7] - (s32)rom[6]);
+- h /= (s32)rom[7];
+- t += h;
+-
+- return t;
+-}
+-
+-static inline int w1_convert_temp(u8 rom[9], u8 fid)
+-{
+- int i;
+-
+- for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+- if (w1_therm_families[i].f->fid == fid)
+- return w1_therm_families[i].convert(rom);
+-
+- return 0;
+-}
+-
+-static int w1_therm_check_rom(u8 rom[9])
+-{
+- int i;
+-
+- for (i=0; i<sizeof(bad_roms)/9; ++i)
+- if (!memcmp(bad_roms[i], rom, 9))
+- return 1;
+-
+- return 0;
+-}
+-
+-static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
+-{
+- struct w1_slave *sl = kobj_to_w1_slave(kobj);
+- struct w1_master *dev = sl->master;
+- u8 rom[9], crc, verdict;
+- int i, max_trying = 10;
+-
+- atomic_inc(&sl->refcnt);
+- smp_mb__after_atomic_inc();
+- if (down_interruptible(&sl->master->mutex)) {
+- count = 0;
+- goto out_dec;
+- }
+-
+- if (off > W1_SLAVE_DATA_SIZE) {
+- count = 0;
+- goto out;
+- }
+- if (off + count > W1_SLAVE_DATA_SIZE) {
+- count = 0;
+- goto out;
+- }
+-
+- memset(buf, 0, count);
+- memset(rom, 0, sizeof(rom));
+-
+- count = 0;
+- verdict = 0;
+- crc = 0;
+-
+- while (max_trying--) {
+- if (!w1_reset_select_slave(sl)) {
+- int count = 0;
+- unsigned int tm = 750;
+-
+- w1_write_8(dev, W1_CONVERT_TEMP);
+-
+- while (tm) {
+- tm = msleep_interruptible(tm);
+- if (signal_pending(current))
+- flush_signals(current);
+- }
+-
+- if (!w1_reset_select_slave(sl)) {
+-
+- w1_write_8(dev, W1_READ_SCRATCHPAD);
+- if ((count = w1_read_block(dev, rom, 9)) != 9) {
+- dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
+- }
+-
+- crc = w1_calc_crc8(rom, 8);
+-
+- if (rom[8] == crc && rom[0])
+- verdict = 1;
+- }
+- }
+-
+- if (!w1_therm_check_rom(rom))
+- break;
+- }
+-
+- for (i = 0; i < 9; ++i)
+- count += sprintf(buf + count, "%02x ", rom[i]);
+- count += sprintf(buf + count, ": crc=%02x %s\n",
+- crc, (verdict) ? "YES" : "NO");
+- if (verdict)
+- memcpy(sl->rom, rom, sizeof(sl->rom));
+- else
+- dev_warn(&dev->dev, "18S20 doesn't respond to CONVERT_TEMP.\n");
+-
+- for (i = 0; i < 9; ++i)
+- count += sprintf(buf + count, "%02x ", sl->rom[i]);
+-
+- count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid));
+-out:
+- up(&dev->mutex);
+-out_dec:
+- smp_mb__before_atomic_inc();
+- atomic_dec(&sl->refcnt);
+-
+- return count;
+-}
+-
+-static int __init w1_therm_init(void)
+-{
+- int err, i;
+-
+- for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i) {
+- err = w1_register_family(w1_therm_families[i].f);
+- if (err)
+- w1_therm_families[i].broken = 1;
+- }
+-
+- return 0;
+-}
+-
+-static void __exit w1_therm_fini(void)
+-{
+- int i;
+-
+- for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+- if (!w1_therm_families[i].broken)
+- w1_unregister_family(w1_therm_families[i].f);
+-}
+-
+-module_init(w1_therm_init);
+-module_exit(w1_therm_fini);