Re: [PATCH 3/6] IIO:ADC:ad799x initial import.

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

 



On 09/27/2011 04:29 PM, Jonathan Cameron wrote:
From: Michael Hennerich<michael.hennerich@xxxxxxxxxx>

Signed-off-by: Jonathan Cameron<jic23@xxxxxxxxx>
Signed-off-by: Michael Hennerich<michael.hennerich@xxxxxxxxxx>

---
  drivers/iio/adc/Kconfig       |   11 +
  drivers/iio/adc/Makefile      |    3 +
  drivers/iio/adc/ad799x_core.c |  722 +++++++++++++++++++++++++++++++++++++++++
  include/linux/iio/ad799x.h    |   12 +
  4 files changed, 748 insertions(+), 0 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 0673d78..3d97b21 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -3,6 +3,17 @@
  #
  menu "Analog to digital convertors"

+config IIO_AD799X
+       tristate "Analog Devices AD799x ADC driver"
+       depends on I2C
+       select IIO_TRIGGER if IIO_BUFFER
+       select AD799X_RING_BUFFER
+       help
+         Say yes here to build support for Analog Devices:
+         ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997, ad7998
+         i2c analog to digital convertors (ADC). Provides direct access
+         via sysfs.
+
  config IIO_MAX1363
         tristate "Maxim max1363 ADC driver"
         depends on I2C
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 8d6a7f9..c197334 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -2,5 +2,8 @@
  # Makefile for IIO ADCs
  #

+iio_ad799x-y := ad799x_core.o
+obj-$(CONFIG_IIO_AD799X) += iio_ad799x.o
+
  iio_max1363-y := max1363_core.o
  obj-$(CONFIG_IIO_MAX1363) += iio_max1363.o
\ No newline at end of file
diff --git a/drivers/iio/adc/ad799x_core.c b/drivers/iio/adc/ad799x_core.c
new file mode 100644
index 0000000..0833ee9
--- /dev/null
+++ b/drivers/iio/adc/ad799x_core.c
@@ -0,0 +1,722 @@
+/*
+ * iio/adc/ad799x.c
+ * Copyright (C) 2010-1011 Michael Hennerich, Analog Devices Inc.
+ *
+ * based on iio/adc/max1363
+ * Copyright (C) 2008-2010 Jonathan Cameron
+ *
+ * based on linux/drivers/i2c/chips/max123x
+ * Copyright (C) 2002-2004 Stefan Eletzhofer
+ *
+ * based on linux/drivers/acron/char/pcf8583.c
+ * Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ad799x.c
+ *
+ * Support for ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997,
+ * ad7998 and similar chips.
+ *
+ */
+
+#include<linux/interrupt.h>
+#include<linux/device.h>
+#include<linux/kernel.h>
+#include<linux/sysfs.h>
+#include<linux/i2c.h>
+#include<linux/regulator/consumer.h>
+#include<linux/slab.h>
+#include<linux/types.h>
+#include<linux/err.h>
+#include<linux/module.h>
+
+#include<linux/iio/iio.h>
+#include<linux/iio/sysfs.h>
+#include<linux/iio/ad799x.h>
+
+#define AD799X_CHANNEL_SHIFT                   4
+/*
+ * AD7991, AD7995 and AD7999 defines
+ */
+
+#define AD7991_REF_SEL                         0x08
+#define AD7991_FLTR                            0x04
+#define AD7991_BIT_TRIAL_DELAY                 0x02
+#define AD7991_SAMPLE_DELAY                    0x01
+
+/*
+ * AD7992, AD7993, AD7994, AD7997 and AD7998 defines
+ */
+
+#define AD7998_FLTR                            0x08
+#define AD7998_ALERT_EN                                0x04
+#define AD7998_BUSY_ALERT                      0x02
+#define AD7998_BUSY_ALERT_POL                  0x01
+
+#define AD7998_CONV_RES_REG                    0x0
+#define AD7998_ALERT_STAT_REG                  0x1
+#define AD7998_CONF_REG                                0x2
+#define AD7998_CYCLE_TMR_REG                   0x3
+#define AD7998_DATALOW_CH1_REG                 0x4
+#define AD7998_DATAHIGH_CH1_REG                        0x5
+#define AD7998_HYST_CH1_REG                    0x6
+#define AD7998_DATALOW_CH2_REG                 0x7
+#define AD7998_DATAHIGH_CH2_REG                        0x8
+#define AD7998_HYST_CH2_REG                    0x9
+#define AD7998_DATALOW_CH3_REG                 0xA
+#define AD7998_DATAHIGH_CH3_REG                        0xB
+#define AD7998_HYST_CH3_REG                    0xC
+#define AD7998_DATALOW_CH4_REG                 0xD
+#define AD7998_DATAHIGH_CH4_REG                        0xE
+#define AD7998_HYST_CH4_REG                    0xF
+
+#define AD7998_CYC_MASK                                0x7
+#define AD7998_CYC_DIS                         0x0
+#define AD7998_CYC_TCONF_32                    0x1
+#define AD7998_CYC_TCONF_64                    0x2
+#define AD7998_CYC_TCONF_128                   0x3
+#define AD7998_CYC_TCONF_256                   0x4
+#define AD7998_CYC_TCONF_512                   0x5
+#define AD7998_CYC_TCONF_1024                  0x6
+#define AD7998_CYC_TCONF_2048                  0x7
+
+#define AD7998_ALERT_STAT_CLEAR                        0xFF
+
+/*
+ * AD7997 and AD7997 defines
+ */
+
+#define AD7997_8_READ_SINGLE                   0x80
+#define AD7997_8_READ_SEQUENCE                 0x70
+/* TODO: move this into a common header */
+#define RES_MASK(bits) ((1<<  (bits)) - 1)
+
+enum {
+       ad7991,
+       ad7995,
+       ad7999,
+       ad7992,
+       ad7993,
+       ad7994,
+       ad7997,
+       ad7998
+};
+
+struct ad799x_state;
+
+/**
+ * struct ad799x_chip_info - chip specifc information
+ * @channel:           channel specification
+ * @num_channels:      number of channels
+ * @int_vref_mv:       the internal reference voltage
+ */
+struct ad799x_chip_info {
+       struct iio_chan_spec            channel[9];
+       int                             num_channels;
+       u16                             int_vref_mv;
+};
+
+struct ad799x_state {
+       struct i2c_client               *client;
+       const struct ad799x_chip_info   *chip_info;
+       struct regulator                *reg;
+       u16                             int_vref_mv;
+       unsigned                        id;
+       char                            *name;
+       u16                             config;
+};
+
+/*
+ * ad799x register access by I2C
+ */
+static int ad799x_i2c_read16(struct ad799x_state *st, u8 reg, u16 *data)
+{
+       struct i2c_client *client = st->client;
+       int ret = 0;
+
+       ret = i2c_smbus_read_word_data(client, reg);
+       if (ret<  0) {
+               dev_err(&client->dev, "I2C read error\n");
+               return ret;
+       }
+
+       *data = swab16((u16)ret);
+
+       return 0;
+}
+
+static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch)
+{
+       u16 rxbuf;
+       u8 cmd;
+       int ret;
+
+       switch (st->id) {
+       case ad7991:
+       case ad7995:
+       case ad7999:
+               cmd = st->config | ((1<<  ch)<<  AD799X_CHANNEL_SHIFT);
+               break;
+       case ad7992:
+       case ad7993:
+       case ad7994:
+               cmd = (1<<  ch)<<  AD799X_CHANNEL_SHIFT;
+               break;
+       case ad7997:
+       case ad7998:
+               cmd = (ch<<  AD799X_CHANNEL_SHIFT) | AD7997_8_READ_SINGLE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = ad799x_i2c_read16(st, cmd,&rxbuf);
+       if (ret<  0)
+               return ret;
+
+       return rxbuf;
+}
+
+static int ad799x_read_raw(struct iio_dev *dev_info,
+                          struct iio_chan_spec const *chan,
+                          int *val,
+                          int *val2,
+                          long m)
+{
+       int ret;
+       struct ad799x_state *st = iio_priv(dev_info);
+       unsigned int scale_uv;
+
+       switch (m) {
+       case 0:
+               mutex_lock(&dev_info->mlock);
+               ret = ad799x_scan_direct(st, chan->channel);
+               mutex_unlock(&dev_info->mlock);
+
+               if (ret<  0)
+                       return ret;
+               *val = (ret>>  chan->scan_type.shift)&
+                       RES_MASK(chan->scan_type.realbits);
+               return IIO_VAL_INT;
+       case (1<<  IIO_CHAN_INFO_SCALE_SHARED):
+               scale_uv = (st->int_vref_mv * 1000)>>  chan->scan_type.realbits;
+               *val =  scale_uv / 1000;
+               *val2 = (scale_uv % 1000) * 1000;
+               return IIO_VAL_INT_PLUS_MICRO;
+       }
+       return -EINVAL;
+}
+
+static const struct iio_info ad799X_info = {
+       .read_raw =&ad799x_read_raw,
+       .driver_module = THIS_MODULE,
+};
+
+
+static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
+       [ad7991] = {
+               .channel = {
+                       [0] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 0,
+                               .scan_type =  {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [1] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 1,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [2] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 2,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [3] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 3,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+               },
+               .num_channels = 5,
+               .int_vref_mv = 4096,
+       },
+       [ad7995] = {
+               .channel = {
+                       [0] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 0,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [1] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 1,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [2] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 2,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [3] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 3,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+               },
+               .num_channels = 5,
+               .int_vref_mv = 1024,
+       },
+       [ad7999] = {
+               .channel = {
+                       [0] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 0,
+                               .scan_type = {
+                                       .realbits = 8,
+                                       .shift = 4,
+                               },
+                       },
+                       [1] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 1,
+                               .scan_type = {
+                                       .realbits = 8,
+                                       .shift = 4,
+                               },
+                       },
+                       [2] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 2,
+                               .scan_type = {
+                                       .realbits = 8,
+                                       .shift = 4,
+                               },
+                       },
+                       [3] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 3,
+                               .scan_type = {
+                                       .realbits = 8,
+                                       .shift = 4,
+                               },
+                       },
+               },
+               .num_channels = 5,
+               .int_vref_mv = 1024,
+       },
+       [ad7992] = {
+               .channel = {
+                       [0] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 0,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [1] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 1,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+               },
+               .num_channels = 3,
+               .int_vref_mv = 4096,
+       },
+       [ad7993] = {
+               .channel = {
+                       [0] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 0,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [1] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 1,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [2] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 2,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [3] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 3,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+               },
+               .num_channels = 5,
+               .int_vref_mv = 1024,
+       },
+       [ad7994] = {
+               .channel = {
+                       [0] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 0,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [1] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 1,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [2] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 2,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [3] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 3,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+               },
+               .num_channels = 5,
+               .int_vref_mv = 4096,
+       },
+       [ad7997] = {
+               .channel = {
+                       [0] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 0,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [1] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 1,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [2] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 2,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [3] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 3,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [4] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 4,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [5] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 5,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [6] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 6,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+                       [7] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 7,
+                               .scan_type = {
+                                       .realbits = 10,
+                                       .shift = 2,
+                               },
+                       },
+               },
+               .num_channels = 9,
+               .int_vref_mv = 1024,
+       },
+       [ad7998] = {
+               .channel = {
+                       [0] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 0,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [1] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 1,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [2] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 2,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [3] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 3,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [4] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 4,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [5] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 5,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [6] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 6,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+                       [7] = {
+                               .type = IIO_VOLTAGE,
+                               .indexed = 1,
+                               .channel = 7,
+                               .scan_type = {
+                                       .realbits = 12,
+                                       .shift = 0,
+                               },
+                       },
+               },
+               .num_channels = 9,
+               .int_vref_mv = 4096,
+       },
+};
+
+static int __devinit ad799x_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
+{
+       int ret;
+       struct ad799x_platform_data *pdata = client->dev.platform_data;
+       struct ad799x_state *st;
+       struct iio_dev *indio_dev = iio_device_allocate(sizeof(*st));
+
+       if (indio_dev == NULL)
+               return -ENOMEM;
+
+       st = iio_priv(indio_dev);
+       /* this is only used for device removal purposes */
+       i2c_set_clientdata(client, indio_dev);
+
+       st->id = id->driver_data;
+       st->chip_info =&ad799x_chip_info_tbl[st->id];
+
+       /* TODO: Add pdata options for filtering and bit delay */
+
+       if (pdata)
+               st->int_vref_mv = pdata->vref_mv;
+       else
+               st->int_vref_mv = st->chip_info->int_vref_mv;
+
+       st->reg = regulator_get(&client->dev, "vcc");
+       if (!IS_ERR(st->reg)) {
+               ret = regulator_enable(st->reg);
+               if (ret)
+                       goto error_put_reg;
+       }
+       st->client = client;
+
+       indio_dev->dev.parent =&client->dev;
+       indio_dev->name = id->name;
+       indio_dev->info =&ad799X_info;
+
+       indio_dev->channels = st->chip_info->channel;
+       indio_dev->num_channels = st->chip_info->num_channels;
+
+       ret = iio_device_register(indio_dev);
+       if (ret)
+               goto error_disable_reg;
+
+       return 0;
+
+error_disable_reg:
+       if (!IS_ERR(st->reg))
+               regulator_disable(st->reg);
+error_put_reg:
+       if (!IS_ERR(st->reg))
+               regulator_put(st->reg);
+       iio_device_free(indio_dev);
+
+       return ret;
+}
+
+static __devexit int ad799x_remove(struct i2c_client *client)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct ad799x_state *st = iio_priv(indio_dev);
+
+       if (!IS_ERR(st->reg)) {
+               regulator_disable(st->reg);
+               regulator_put(st->reg);
+       }
+       iio_device_unregister(indio_dev);
+
+       return 0;
+}
+
+static const struct i2c_device_id ad799x_id[] = {
+       { "ad7991", ad7991 },
+       { "ad7995", ad7995 },
+       { "ad7999", ad7999 },
+       { "ad7992", ad7992 },
+       { "ad7993", ad7993 },
+       { "ad7994", ad7994 },
+       { "ad7997", ad7997 },
+       { "ad7998", ad7998 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ad799x_id);
+
+static struct i2c_driver ad799x_driver = {
+       .driver = {
+               .name = "ad799x",
+       },
+       .probe = ad799x_probe,
+       .remove = __devexit_p(ad799x_remove),
+       .id_table = ad799x_id,
+};
+
+static __init int ad799x_init(void)
+{
+       return i2c_add_driver(&ad799x_driver);
+}
+
+static __exit void ad799x_exit(void)
+{
+       i2c_del_driver(&ad799x_driver);
+}
+
+MODULE_AUTHOR("Michael Hennerich<hennerich@xxxxxxxxxxxxxxxxxxxx>");
+MODULE_DESCRIPTION("Analog Devices AD799x ADC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("i2c:ad799x");
+
+module_init(ad799x_init);
+module_exit(ad799x_exit);
diff --git a/include/linux/iio/ad799x.h b/include/linux/iio/ad799x.h
new file mode 100644
index 0000000..38517be
--- /dev/null
+++ b/include/linux/iio/ad799x.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc.
+ * Copyright (C) 2008-2010 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+struct ad799x_platform_data {
+       u16                             vref_mv;
+};
--
1.7.3.4




--
Greetings,
Michael

--
Analog Devices GmbH      Wilhelm-Wagenfeld-Str. 6      80807 Muenchen
Sitz der Gesellschaft: Muenchen; Registergericht: Muenchen HRB 40368;
Geschaeftsfuehrer:Dr.Carsten Suckrow, Thomas Wessel, William A. Martin,
Margaret Seif


--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux