summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS6
-rw-r--r--Documentation/ide.txt50
-rw-r--r--MAINTAINERS6
-rw-r--r--drivers/bluetooth/Config.help14
-rw-r--r--drivers/bluetooth/Config.in2
-rw-r--r--drivers/bluetooth/Makefile1
-rw-r--r--drivers/bluetooth/bluecard_cs.c95
-rw-r--r--drivers/bluetooth/bt3c_cs.c944
-rw-r--r--drivers/bluetooth/dtl1_cs.c1249
-rw-r--r--drivers/ide/ali14xx.c6
-rw-r--r--drivers/ide/cs5530.c11
-rw-r--r--drivers/ide/dtc2278.c7
-rw-r--r--drivers/ide/hd.c80
-rw-r--r--drivers/ide/ht6560b.c15
-rw-r--r--drivers/ide/ide-cd.c7
-rw-r--r--drivers/ide/ide-disk.c6
-rw-r--r--drivers/ide/ide-floppy.c9
-rw-r--r--drivers/ide/ide-pci.c3
-rw-r--r--drivers/ide/ide-tape.c422
-rw-r--r--drivers/ide/ioctl.c9
-rw-r--r--drivers/ide/it8172.c3
-rw-r--r--drivers/ide/main.c189
-rw-r--r--drivers/ide/opti621.c11
-rw-r--r--drivers/ide/probe.c7
-rw-r--r--drivers/ide/qd65xx.c78
-rw-r--r--drivers/scsi/ide-scsi.c32
-rw-r--r--drivers/usb/storage/freecom.c42
-rw-r--r--include/linux/hdreg.h522
-rw-r--r--include/linux/ide.h499
-rw-r--r--kernel/fork.c73
30 files changed, 2455 insertions, 1943 deletions
diff --git a/CREDITS b/CREDITS
index a94765c5e4ca..19a4516ee5ae 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1337,6 +1337,12 @@ S: 998 East 900 South, Suite 26
S: Provo, Utah 84606-5607
S: USA
+N: Marcel Holtmann
+E: marcel@holtmann.org
+W: http://www.holtmann.org
+D: Author of the Linux Bluetooth Subsystem PC Card drivers
+S: Germany
+
N: Rob W. W. Hooft
E: hooft@EMBL-Heidelberg.DE
D: Shared libs for graphics-tools and for the f2c compiler
diff --git a/Documentation/ide.txt b/Documentation/ide.txt
index 9da199ed4108..3adb7cabfbcd 100644
--- a/Documentation/ide.txt
+++ b/Documentation/ide.txt
@@ -1,9 +1,6 @@
-
-
Information regarding the Enhanced IDE drive in Linux 2.5
-
==============================================================================
@@ -303,6 +300,53 @@ Everything else is rejected with a "BAD OPTION" message.
================================================================================
+IDE ATAPI streaming tape driver
+-------------------------------
+
+This driver is a part of the Linux ide driver and works in co-operation
+with linux/drivers/block/ide.c.
+
+The driver, in co-operation with ide.c, basically traverses the
+request-list for the block device interface. The character device
+interface, on the other hand, creates new requests, adds them
+to the request-list of the block device, and waits for their completion.
+
+Pipelined operation mode is now supported on both reads and writes.
+
+The block device major and minor numbers are determined from the
+tape's relative position in the ide interfaces, as explained in ide.c.
+
+The character device interface consists of the following devices:
+
+ ht0 major 37, minor 0 first IDE tape, rewind on close.
+ ht1 major 37, minor 1 second IDE tape, rewind on close.
+ ...
+ nht0 major 37, minor 128 first IDE tape, no rewind on close.
+ nht1 major 37, minor 129 second IDE tape, no rewind on close.
+ ...
+
+Run linux/scripts/MAKEDEV.ide to create the above entries.
+
+The general magnetic tape commands compatible interface, as defined by
+include/linux/mtio.h, is accessible through the character device.
+
+General ide driver configuration options, such as the interrupt-unmask
+flag, can be configured by issuing an ioctl to the block device interface,
+as any other ide device.
+
+Our own ide-tape ioctl's can be issued to either the block device or
+the character device interface.
+
+Maximal throughput with minimal bus load will usually be achieved in the
+following scenario:
+
+ 1. ide-tape is operating in the pipelined operation mode.
+ 2. No buffering is performed by the user backup program.
+
+
+
+================================================================================
+
Some Terminology
----------------
IDE = Integrated Drive Electronics, meaning that each drive has a built-in
diff --git a/MAINTAINERS b/MAINTAINERS
index 493c93ec438b..ebcd5fe6fa67 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -270,6 +270,12 @@ M: maxk@qualcomm.com
W: http://bluez.sf.net
S: Maintained
+BLUETOOTH SUBSYSTEM (PC Card Drivers)
+P: Marcel Holtmann
+M: marcel@holtmann.org
+W: http://www.holtmann.org/linux/bluetooth/
+S: Maintained
+
BTTV VIDEO4LINUX DRIVER
P: Gerd Knorr
M: kraxel@bytesex.org
diff --git a/drivers/bluetooth/Config.help b/drivers/bluetooth/Config.help
index b59648ceaae5..e5a9f19a6290 100644
--- a/drivers/bluetooth/Config.help
+++ b/drivers/bluetooth/Config.help
@@ -62,6 +62,20 @@ CONFIG_BLUEZ_HCIDTL1
Say Y here to compile support for HCI DTL1 devices into the
kernel or say M to compile it as module (dtl1_cs.o).
+HCI BT3C (PC Card) device driver
+CONFIG_BLUEZ_HCIBT3C
+ Bluetooth HCI BT3C (PC Card) driver.
+ This driver provides support for Bluetooth PCMCIA devices with
+ 3Com BT3C interface:
+ 3Com Bluetooth Card (3CRWB6096)
+ HP Bluetooth Card
+
+ The HCI BT3C driver uses external firmware loader program provided in
+ the BlueFW package. For more information, see <http://bluez.sf.net>.
+
+ Say Y here to compile support for HCI BT3C devices into the
+ kernel or say M to compile it as module (bt3c_cs.o).
+
HCI BlueCard (PC Card) device driver
CONFIG_BLUEZ_HCIBLUECARD
Bluetooth HCI BlueCard (PC Card) driver.
diff --git a/drivers/bluetooth/Config.in b/drivers/bluetooth/Config.in
index a4d71734c64f..9aef303fc289 100644
--- a/drivers/bluetooth/Config.in
+++ b/drivers/bluetooth/Config.in
@@ -14,6 +14,8 @@ fi
dep_tristate 'HCI DTL1 (PC Card) driver' CONFIG_BLUEZ_HCIDTL1 $CONFIG_PCMCIA $CONFIG_BLUEZ
+dep_tristate 'HCI BT3C (PC Card) driver' CONFIG_BLUEZ_HCIBT3C $CONFIG_PCMCIA $CONFIG_BLUEZ
+
dep_tristate 'HCI BlueCard (PC Card) driver' CONFIG_BLUEZ_HCIBLUECARD $CONFIG_PCMCIA $CONFIG_BLUEZ
dep_tristate 'HCI VHCI (Virtual HCI device) driver' CONFIG_BLUEZ_HCIVHCI $CONFIG_BLUEZ
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index ada41c6689a4..76d3def3ba65 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_BLUEZ_HCIUSB) += hci_usb.o
obj-$(CONFIG_BLUEZ_HCIVHCI) += hci_vhci.o
obj-$(CONFIG_BLUEZ_HCIUART) += hci_uart.o
obj-$(CONFIG_BLUEZ_HCIDTL1) += dtl1_cs.o
+obj-$(CONFIG_BLUEZ_HCIBT3C) += bt3c_cs.o
obj-$(CONFIG_BLUEZ_HCIBLUECARD) += bluecard_cs.o
hci_uart-y := hci_ldisc.o
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index e358601d42f7..296d674bc38a 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -89,16 +89,16 @@ typedef struct bluecard_info_t {
} bluecard_info_t;
-void bluecard_config(dev_link_t * link);
+void bluecard_config(dev_link_t *link);
void bluecard_release(u_long arg);
-int bluecard_event(event_t event, int priority, event_callback_args_t * args);
+int bluecard_event(event_t event, int priority, event_callback_args_t *args);
static dev_info_t dev_info = "bluecard_cs";
dev_link_t *bluecard_attach(void);
void bluecard_detach(dev_link_t *);
-dev_link_t *dev_list = NULL;
+static dev_link_t *dev_list = NULL;
/* Default baud rate: 57600, 115200, 230400 or 460800 */
@@ -171,7 +171,7 @@ dev_link_t *dev_list = NULL;
void bluecard_activity_led_timeout(u_long arg)
{
- bluecard_info_t *info = (bluecard_info_t *) arg;
+ bluecard_info_t *info = (bluecard_info_t *)arg;
unsigned int iobase = info->link.io.BasePort1;
if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) {
@@ -184,7 +184,7 @@ void bluecard_activity_led_timeout(u_long arg)
}
-static void bluecard_enable_activity_led(bluecard_info_t * info)
+static void bluecard_enable_activity_led(bluecard_info_t *info)
{
unsigned int iobase = info->link.io.BasePort1;
@@ -208,8 +208,7 @@ static void bluecard_enable_activity_led(bluecard_info_t * info)
/* ======================== Interrupt handling ======================== */
-static int bluecard_write(unsigned int iobase, unsigned int offset,
- __u8 * buf, int len)
+static int bluecard_write(unsigned int iobase, unsigned int offset, __u8 *buf, int len)
{
int i, actual;
@@ -224,7 +223,7 @@ static int bluecard_write(unsigned int iobase, unsigned int offset,
}
-static void bluecard_write_wakeup(bluecard_info_t * info)
+static void bluecard_write_wakeup(bluecard_info_t *info)
{
if (!info) {
printk(KERN_WARNING "bluecard_cs: Call of write_wakeup for unknown device.\n");
@@ -253,15 +252,13 @@ static void bluecard_write_wakeup(bluecard_info_t * info)
return;
if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) {
- if (!test_bit
- (XMIT_BUF_TWO_READY, &(info->tx_state)))
+ if (!test_bit(XMIT_BUF_TWO_READY, &(info->tx_state)))
break;
offset = 0x10;
command = REG_COMMAND_TX_BUF_TWO;
ready_bit = XMIT_BUF_TWO_READY;
} else {
- if (!test_bit
- (XMIT_BUF_ONE_READY, &(info->tx_state)))
+ if (!test_bit(XMIT_BUF_ONE_READY, &(info->tx_state)))
break;
offset = 0x00;
command = REG_COMMAND_TX_BUF_ONE;
@@ -272,11 +269,9 @@ static void bluecard_write_wakeup(bluecard_info_t * info)
break;
if (skb->pkt_type & 0x80) {
-
/* Disable RTS */
info->ctrl_reg |= REG_CONTROL_RTS;
outb(info->ctrl_reg, iobase + REG_CONTROL);
-
}
/* Activate LED */
@@ -349,8 +344,7 @@ static void bluecard_write_wakeup(bluecard_info_t * info)
}
-static int bluecard_read(unsigned int iobase, unsigned int offset,
- __u8 * buf, int size)
+static int bluecard_read(unsigned int iobase, unsigned int offset, __u8 *buf, int size)
{
int i, n, len;
@@ -378,7 +372,7 @@ static int bluecard_read(unsigned int iobase, unsigned int offset,
}
-static void bluecard_receive(bluecard_info_t * info, unsigned int offset)
+static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
{
unsigned int iobase;
unsigned char buf[31];
@@ -410,7 +404,7 @@ static void bluecard_receive(bluecard_info_t * info, unsigned int offset)
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
- info->rx_skb->dev = (void *) &(info->hdev);
+ info->rx_skb->dev = (void *)&(info->hdev);
info->rx_skb->pkt_type = buf[i];
switch (info->rx_skb->pkt_type) {
@@ -469,20 +463,20 @@ static void bluecard_receive(bluecard_info_t * info, unsigned int offset)
switch (info->rx_state) {
case RECV_WAIT_EVENT_HEADER:
- eh = (hci_event_hdr *) (info->rx_skb->data);
+ eh = (hci_event_hdr *)(info->rx_skb->data);
info->rx_state = RECV_WAIT_DATA;
info->rx_count = eh->plen;
break;
case RECV_WAIT_ACL_HEADER:
- ah = (hci_acl_hdr *) (info->rx_skb->data);
+ ah = (hci_acl_hdr *)(info->rx_skb->data);
dlen = __le16_to_cpu(ah->dlen);
info->rx_state = RECV_WAIT_DATA;
info->rx_count = dlen;
break;
case RECV_WAIT_SCO_HEADER:
- sh = (hci_sco_hdr *) (info->rx_skb->data);
+ sh = (hci_sco_hdr *)(info->rx_skb->data);
info->rx_state = RECV_WAIT_DATA;
info->rx_count = sh->dlen;
break;
@@ -571,9 +565,8 @@ void bluecard_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
{
- bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data);
+ bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
struct sk_buff *skb;
- int i;
/* Ericsson baud rate command */
unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 };
@@ -604,8 +597,7 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
break;
}
- for (i = 0; i < sizeof(cmd); i++)
- *skb_put(skb, 1) = cmd[i];
+ memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
skb_queue_tail(&(info->txq), skb);
@@ -621,7 +613,7 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
static int bluecard_hci_flush(struct hci_dev *hdev)
{
- bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data);
+ bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
/* Drop TX queue */
skb_queue_purge(&(info->txq));
@@ -632,7 +624,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
static int bluecard_hci_open(struct hci_dev *hdev)
{
- bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data);
+ bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
unsigned int iobase = info->link.io.BasePort1;
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
@@ -649,7 +641,7 @@ static int bluecard_hci_open(struct hci_dev *hdev)
static int bluecard_hci_close(struct hci_dev *hdev)
{
- bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data);
+ bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
unsigned int iobase = info->link.io.BasePort1;
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
@@ -667,14 +659,14 @@ static int bluecard_hci_close(struct hci_dev *hdev)
static int bluecard_hci_send_frame(struct sk_buff *skb)
{
bluecard_info_t *info;
- struct hci_dev *hdev = (struct hci_dev *) (skb->dev);
+ struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
if (!hdev) {
printk(KERN_WARNING "bluecard_cs: Frame for unknown HCI device (hdev=NULL).");
return -ENODEV;
}
- info = (bluecard_info_t *) (hdev->driver_data);
+ info = (bluecard_info_t *)(hdev->driver_data);
switch (skb->pkt_type) {
case HCI_COMMAND_PKT:
@@ -703,8 +695,7 @@ static void bluecard_hci_destruct(struct hci_dev *hdev)
}
-static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,
- unsigned long arg)
+static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
{
return -ENOIOCTLCMD;
}
@@ -714,7 +705,7 @@ static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,
/* ======================== Card services HCI interaction ======================== */
-int bluecard_open(bluecard_info_t * info)
+int bluecard_open(bluecard_info_t *info)
{
unsigned int iobase = info->link.io.BasePort1;
struct hci_dev *hdev;
@@ -724,7 +715,7 @@ int bluecard_open(bluecard_info_t * info)
init_timer(&(info->timer));
info->timer.function = &bluecard_activity_led_timeout;
- info->timer.data = (u_long) info;
+ info->timer.data = (u_long)info;
skb_queue_head_init(&(info->txq));
@@ -781,7 +772,8 @@ int bluecard_open(bluecard_info_t * info)
/* Timeout before it is safe to send the first HCI packet */
set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout((HZ * 5) / 4); // or set it to 3/2
+ schedule_timeout((HZ * 5) / 4); // or set it to 3/2
+
/* Initialize and register HCI device */
@@ -806,7 +798,7 @@ int bluecard_open(bluecard_info_t * info)
}
-int bluecard_close(bluecard_info_t * info)
+int bluecard_close(bluecard_info_t *info)
{
unsigned int iobase = info->link.io.BasePort1;
struct hci_dev *hdev = &(info->hdev);
@@ -858,7 +850,7 @@ dev_link_t *bluecard_attach(void)
link->priv = info;
link->release.function = &bluecard_release;
- link->release.data = (u_long) link;
+ link->release.data = (u_long)link;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.NumPorts1 = 8;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
@@ -883,9 +875,9 @@ dev_link_t *bluecard_attach(void)
client_reg.dev_info = &dev_info;
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+ CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+ CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+ CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
client_reg.event_handler = &bluecard_event;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
@@ -901,7 +893,7 @@ dev_link_t *bluecard_attach(void)
}
-void bluecard_detach(dev_link_t * link)
+void bluecard_detach(dev_link_t *link)
{
bluecard_info_t *info = link->priv;
dev_link_t **linkp;
@@ -917,7 +909,7 @@ void bluecard_detach(dev_link_t * link)
del_timer(&link->release);
if (link->state & DEV_CONFIG)
- bluecard_release((u_long) link);
+ bluecard_release((u_long)link);
if (link->handle) {
ret = CardServices(DeregisterClient, link->handle);
@@ -932,8 +924,7 @@ void bluecard_detach(dev_link_t * link)
}
-static int get_tuple(int fn, client_handle_t handle, tuple_t * tuple,
- cisparse_t * parse)
+static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
{
int i;
@@ -952,7 +943,7 @@ static int get_tuple(int fn, client_handle_t handle, tuple_t * tuple,
#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
-void bluecard_config(dev_link_t * link)
+void bluecard_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
bluecard_info_t *info = link->priv;
@@ -962,7 +953,7 @@ void bluecard_config(dev_link_t * link)
config_info_t config;
int i, n, last_ret, last_fn;
- tuple.TupleData = (cisdata_t *) buf;
+ tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
@@ -1010,12 +1001,12 @@ void bluecard_config(dev_link_t * link)
goto failed;
}
-
MOD_INC_USE_COUNT;
if (bluecard_open(info) != 0)
goto failed;
+ strcpy(info->node.dev_name, info->hdev.name);
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
@@ -1025,13 +1016,13 @@ cs_failed:
cs_error(link->handle, last_fn, last_ret);
failed:
- bluecard_release((u_long) link);
+ bluecard_release((u_long)link);
}
void bluecard_release(u_long arg)
{
- dev_link_t *link = (dev_link_t *) arg;
+ dev_link_t *link = (dev_link_t *)arg;
bluecard_info_t *info = link->priv;
if (link->state & DEV_PRESENT)
@@ -1049,8 +1040,7 @@ void bluecard_release(u_long arg)
}
-int bluecard_event(event_t event, int priority,
- event_callback_args_t * args)
+int bluecard_event(event_t event, int priority, event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
bluecard_info_t *info = link->priv;
@@ -1079,8 +1069,7 @@ int bluecard_event(event_t event, int priority,
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (DEV_OK(link))
- CardServices(RequestConfiguration, link->handle,
- &link->conf);
+ CardServices(RequestConfiguration, link->handle, &link->conf);
break;
}
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
new file mode 100644
index 000000000000..d50e4e945d34
--- /dev/null
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -0,0 +1,944 @@
+/*
+ *
+ * Driver for the 3Com Bluetooth PCMCIA card
+ *
+ * Copyright (C) 2001-2002 Marcel Holtmann <marcel@holtmann.org>
+ * Jose Orlando Pereira <jop@di.uminho.pt>
+ *
+ *
+ * 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;
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#define __KERNEL_SYSCALLS__
+
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+
+
+/* ======================== Module parameters ======================== */
+
+
+/* Bit map of interrupts to choose from */
+static u_int irq_mask = 0xffff;
+static int irq_list[4] = { -1 };
+
+MODULE_PARM(irq_mask, "i");
+MODULE_PARM(irq_list, "1-4i");
+
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>");
+MODULE_DESCRIPTION("BlueZ driver for the 3Com Bluetooth PCMCIA card");
+MODULE_LICENSE("GPL");
+
+
+
+/* ======================== Local structures ======================== */
+
+
+typedef struct bt3c_info_t {
+ dev_link_t link;
+ dev_node_t node;
+
+ struct hci_dev hdev;
+
+ spinlock_t lock; /* For serializing operations */
+
+ struct sk_buff_head txq;
+ unsigned long tx_state;
+
+ unsigned long rx_state;
+ unsigned long rx_count;
+ struct sk_buff *rx_skb;
+} bt3c_info_t;
+
+
+void bt3c_config(dev_link_t *link);
+void bt3c_release(u_long arg);
+int bt3c_event(event_t event, int priority, event_callback_args_t *args);
+
+static dev_info_t dev_info = "bt3c_cs";
+
+dev_link_t *bt3c_attach(void);
+void bt3c_detach(dev_link_t *);
+
+static dev_link_t *dev_list = NULL;
+
+
+/* Transmit states */
+#define XMIT_SENDING 1
+#define XMIT_WAKEUP 2
+#define XMIT_WAITING 8
+
+/* Receiver states */
+#define RECV_WAIT_PACKET_TYPE 0
+#define RECV_WAIT_EVENT_HEADER 1
+#define RECV_WAIT_ACL_HEADER 2
+#define RECV_WAIT_SCO_HEADER 3
+#define RECV_WAIT_DATA 4
+
+
+
+/* ======================== Special I/O functions ======================== */
+
+
+#define DATA_L 0
+#define DATA_H 1
+#define ADDR_L 2
+#define ADDR_H 3
+#define CONTROL 4
+
+
+inline void bt3c_address(unsigned int iobase, unsigned short addr)
+{
+ outb(addr & 0xff, iobase + ADDR_L);
+ outb((addr >> 8) & 0xff, iobase + ADDR_H);
+}
+
+
+inline void bt3c_put(unsigned int iobase, unsigned short value)
+{
+ outb(value & 0xff, iobase + DATA_L);
+ outb((value >> 8) & 0xff, iobase + DATA_H);
+}
+
+
+inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value)
+{
+ bt3c_address(iobase, addr);
+ bt3c_put(iobase, value);
+}
+
+
+inline unsigned short bt3c_get(unsigned int iobase)
+{
+ unsigned short value = inb(iobase + DATA_L);
+
+ value |= inb(iobase + DATA_H) << 8;
+
+ return value;
+}
+
+
+inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr)
+{
+ bt3c_address(iobase, addr);
+
+ return bt3c_get(iobase);
+}
+
+
+
+/* ======================== Interrupt handling ======================== */
+
+
+static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
+{
+ int actual = 0;
+
+ bt3c_address(iobase, 0x7080);
+
+ /* Fill FIFO with current frame */
+ while (actual < len) {
+ /* Transmit next byte */
+ bt3c_put(iobase, buf[actual]);
+ actual++;
+ }
+
+ bt3c_io_write(iobase, 0x7005, actual);
+
+ return actual;
+}
+
+
+static void bt3c_write_wakeup(bt3c_info_t *info, int from)
+{
+ unsigned long flags;
+
+ if (!info) {
+ printk(KERN_WARNING "bt3c_cs: Call of write_wakeup for unknown device.\n");
+ return;
+ }
+
+ if (test_and_set_bit(XMIT_SENDING, &(info->tx_state)))
+ return;
+
+ spin_lock_irqsave(&(info->lock), flags);
+
+ do {
+ register unsigned int iobase = info->link.io.BasePort1;
+ register struct sk_buff *skb;
+ register int len;
+
+ if (!(info->link.state & DEV_PRESENT))
+ break;
+
+
+ if (!(skb = skb_dequeue(&(info->txq)))) {
+ clear_bit(XMIT_SENDING, &(info->tx_state));
+ break;
+ }
+
+ /* Send frame */
+ len = bt3c_write(iobase, 256, skb->data, skb->len);
+
+ if (len != skb->len) {
+ printk(KERN_WARNING "bt3c_cs: very strange\n");
+ }
+
+ kfree_skb(skb);
+
+ info->hdev.stat.byte_tx += len;
+
+ } while (0);
+
+ spin_unlock_irqrestore(&(info->lock), flags);
+}
+
+
+static void bt3c_receive(bt3c_info_t *info)
+{
+ unsigned int iobase;
+ int size = 0, avail;
+
+ if (!info) {
+ printk(KERN_WARNING "bt3c_cs: Call of receive for unknown device.\n");
+ return;
+ }
+
+ iobase = info->link.io.BasePort1;
+
+ avail = bt3c_read(iobase, 0x7006);
+ //printk("bt3c_cs: receiving %d bytes\n", avail);
+
+ bt3c_address(iobase, 0x7480);
+ while (size < avail) {
+ size++;
+ info->hdev.stat.byte_rx++;
+
+ /* Allocate packet */
+ if (info->rx_skb == NULL) {
+ info->rx_state = RECV_WAIT_PACKET_TYPE;
+ info->rx_count = 0;
+ if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
+ printk(KERN_WARNING "bt3c_cs: Can't allocate mem for new packet.\n");
+ return;
+ }
+ }
+
+
+ if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
+
+ info->rx_skb->dev = (void *)&(info->hdev);
+ info->rx_skb->pkt_type = inb(iobase + DATA_L);
+ inb(iobase + DATA_H);
+ //printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type);
+
+ switch (info->rx_skb->pkt_type) {
+
+ case HCI_EVENT_PKT:
+ info->rx_state = RECV_WAIT_EVENT_HEADER;
+ info->rx_count = HCI_EVENT_HDR_SIZE;
+ break;
+
+ case HCI_ACLDATA_PKT:
+ info->rx_state = RECV_WAIT_ACL_HEADER;
+ info->rx_count = HCI_ACL_HDR_SIZE;
+ break;
+
+ case HCI_SCODATA_PKT:
+ info->rx_state = RECV_WAIT_SCO_HEADER;
+ info->rx_count = HCI_SCO_HDR_SIZE;
+ break;
+
+ default:
+ /* Unknown packet */
+ printk(KERN_WARNING "bt3c_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
+ info->hdev.stat.err_rx++;
+ clear_bit(HCI_RUNNING, &(info->hdev.flags));
+
+ kfree_skb(info->rx_skb);
+ info->rx_skb = NULL;
+ break;
+
+ }
+
+ } else {
+
+ __u8 x = inb(iobase + DATA_L);
+
+ *skb_put(info->rx_skb, 1) = x;
+ inb(iobase + DATA_H);
+ info->rx_count--;
+
+ if (info->rx_count == 0) {
+
+ int dlen;
+ hci_event_hdr *eh;
+ hci_acl_hdr *ah;
+ hci_sco_hdr *sh;
+
+ switch (info->rx_state) {
+
+ case RECV_WAIT_EVENT_HEADER:
+ eh = (hci_event_hdr *)(info->rx_skb->data);
+ info->rx_state = RECV_WAIT_DATA;
+ info->rx_count = eh->plen;
+ break;
+
+ case RECV_WAIT_ACL_HEADER:
+ ah = (hci_acl_hdr *)(info->rx_skb->data);
+ dlen = __le16_to_cpu(ah->dlen);
+ info->rx_state = RECV_WAIT_DATA;
+ info->rx_count = dlen;
+ break;
+
+ case RECV_WAIT_SCO_HEADER:
+ sh = (hci_sco_hdr *)(info->rx_skb->data);
+ info->rx_state = RECV_WAIT_DATA;
+ info->rx_count = sh->dlen;
+ break;
+
+ case RECV_WAIT_DATA:
+ hci_recv_frame(info->rx_skb);
+ info->rx_skb = NULL;
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ bt3c_io_write(iobase, 0x7006, 0x0000);
+}
+
+
+void bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
+{
+ bt3c_info_t *info = dev_inst;
+ unsigned int iobase;
+ int iir;
+
+ if (!info) {
+ printk(KERN_WARNING "bt3c_cs: Call of irq %d for unknown device.\n", irq);
+ return;
+ }
+
+ iobase = info->link.io.BasePort1;
+
+ spin_lock(&(info->lock));
+
+ iir = inb(iobase + CONTROL);
+ if (iir & 0x80) {
+ int stat = bt3c_read(iobase, 0x7001);
+
+ if ((stat & 0xff) == 0x7f) {
+ printk(KERN_WARNING "bt3c_cs: STRANGE stat=%04x\n", stat);
+ } else if ((stat & 0xff) != 0xff) {
+ if (stat & 0x0020) {
+ int stat = bt3c_read(iobase, 0x7002) & 0x10;
+ printk(KERN_WARNING "bt3c_cs: antena %s\n", stat ? "OUT" : "IN");
+ }
+ if (stat & 0x0001)
+ bt3c_receive(info);
+ if (stat & 0x0002) {
+ //printk("bt3c_cs: ACK %04x\n", stat);
+ clear_bit(XMIT_SENDING, &(info->tx_state));
+ bt3c_write_wakeup(info, 1);
+ }
+
+ bt3c_io_write(iobase, 0x7001, 0x0000);
+
+ outb(iir, iobase + CONTROL);
+ }
+ }
+
+ spin_unlock(&(info->lock));
+}
+
+
+
+
+/* ======================== HCI interface ======================== */
+
+
+static int bt3c_hci_flush(struct hci_dev *hdev)
+{
+ bt3c_info_t *info = (bt3c_info_t *)(hdev->driver_data);
+
+ /* Drop TX queue */
+ skb_queue_purge(&(info->txq));
+
+ return 0;
+}
+
+
+static int bt3c_hci_open(struct hci_dev *hdev)
+{
+ set_bit(HCI_RUNNING, &(hdev->flags));
+
+ return 0;
+}
+
+
+static int bt3c_hci_close(struct hci_dev *hdev)
+{
+ if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
+ return 0;
+
+ bt3c_hci_flush(hdev);
+
+ return 0;
+}
+
+
+static int bt3c_hci_send_frame(struct sk_buff *skb)
+{
+ bt3c_info_t *info;
+ struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
+
+ if (!hdev) {
+ printk(KERN_WARNING "bt3c_cs: Frame for unknown HCI device (hdev=NULL).");
+ return -ENODEV;
+ }
+
+ info = (bt3c_info_t *) (hdev->driver_data);
+
+ switch (skb->pkt_type) {
+ case HCI_COMMAND_PKT:
+ hdev->stat.cmd_tx++;
+ break;
+ case HCI_ACLDATA_PKT:
+ hdev->stat.acl_tx++;
+ break;
+ case HCI_SCODATA_PKT:
+ hdev->stat.sco_tx++;
+ break;
+ };
+
+ /* Prepend skb with frame type */
+ memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+ skb_queue_tail(&(info->txq), skb);
+
+ bt3c_write_wakeup(info, 0);
+
+ return 0;
+}
+
+
+static void bt3c_hci_destruct(struct hci_dev *hdev)
+{
+}
+
+
+static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
+{
+ return -ENOIOCTLCMD;
+}
+
+
+
+/* ======================== User mode firmware loader ======================== */
+
+
+#define FW_LOADER "/sbin/bluefw"
+static int errno;
+
+
+static int bt3c_fw_loader_exec(void *dev)
+{
+ char *argv[] = { FW_LOADER, "pccard", dev, NULL };
+ char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
+ int err;
+
+ err = exec_usermodehelper(FW_LOADER, argv, envp);
+ if (err)
+ printk(KERN_WARNING "bt3c_cs: Failed to exec \"%s pccard %s\".\n", FW_LOADER, (char *)dev);
+
+ return err;
+}
+
+
+static int bt3c_firmware_load(bt3c_info_t *info)
+{
+ sigset_t tmpsig;
+ char dev[16];
+ pid_t pid;
+ int result;
+
+ /* Check if root fs is mounted */
+ if (!current->fs->root) {
+ printk(KERN_WARNING "bt3c_cs: Root filesystem is not mounted.\n");
+ return -EPERM;
+ }
+
+ sprintf(dev, "%04x", info->link.io.BasePort1);
+
+ pid = kernel_thread(bt3c_fw_loader_exec, (void *)dev, 0);
+ if (pid < 0) {
+ printk(KERN_WARNING "bt3c_cs: Forking of kernel thread failed (errno=%d).\n", -pid);
+ return pid;
+ }
+
+ /* Block signals, everything but SIGKILL/SIGSTOP */
+ spin_lock_irq(&current->sigmask_lock);
+ tmpsig = current->blocked;
+ siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
+ recalc_sigpending();
+ spin_unlock_irq(&current->sigmask_lock);
+
+ result = waitpid(pid, NULL, __WCLONE);
+
+ /* Allow signals again */
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = tmpsig;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if (result != pid) {
+ printk(KERN_WARNING "bt3c_cs: Waiting for pid %d failed (errno=%d).\n", pid, -result);
+ return -result;
+ }
+
+ return 0;
+}
+
+
+
+/* ======================== Card services HCI interaction ======================== */
+
+
+int bt3c_open(bt3c_info_t *info)
+{
+ struct hci_dev *hdev;
+ int err;
+
+ spin_lock_init(&(info->lock));
+
+ skb_queue_head_init(&(info->txq));
+
+ info->rx_state = RECV_WAIT_PACKET_TYPE;
+ info->rx_count = 0;
+ info->rx_skb = NULL;
+
+ /* Load firmware */
+
+ if ((err = bt3c_firmware_load(info)) < 0)
+ return err;
+
+ /* Timeout before it is safe to send the first HCI packet */
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+
+
+ /* Initialize and register HCI device */
+
+ hdev = &(info->hdev);
+
+ hdev->type = HCI_PCCARD;
+ hdev->driver_data = info;
+
+ hdev->open = bt3c_hci_open;
+ hdev->close = bt3c_hci_close;
+ hdev->flush = bt3c_hci_flush;
+ hdev->send = bt3c_hci_send_frame;
+ hdev->destruct = bt3c_hci_destruct;
+ hdev->ioctl = bt3c_hci_ioctl;
+
+ if (hci_register_dev(hdev) < 0) {
+ printk(KERN_WARNING "bt3c_cs: Can't register HCI device %s.\n", hdev->name);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+
+int bt3c_close(bt3c_info_t *info)
+{
+ struct hci_dev *hdev = &(info->hdev);
+
+ bt3c_hci_close(hdev);
+
+ if (hci_unregister_dev(hdev) < 0)
+ printk(KERN_WARNING "bt3c_cs: Can't unregister HCI device %s.\n", hdev->name);
+
+ return 0;
+}
+
+
+
+/* ======================== Card services ======================== */
+
+
+static void cs_error(client_handle_t handle, int func, int ret)
+{
+ error_info_t err = { func, ret };
+
+ CardServices(ReportError, handle, &err);
+}
+
+
+dev_link_t *bt3c_attach(void)
+{
+ bt3c_info_t *info;
+ client_reg_t client_reg;
+ dev_link_t *link;
+ int i, ret;
+
+ /* Create new info device */
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return NULL;
+ memset(info, 0, sizeof(*info));
+
+ link = &info->link;
+ link->priv = info;
+
+ link->release.function = &bt3c_release;
+ link->release.data = (u_long)link;
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ link->io.NumPorts1 = 8;
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
+
+ if (irq_list[0] == -1)
+ link->irq.IRQInfo2 = irq_mask;
+ else
+ for (i = 0; i < 4; i++)
+ link->irq.IRQInfo2 |= 1 << irq_list[i];
+
+ link->irq.Handler = bt3c_interrupt;
+ link->irq.Instance = info;
+
+ link->conf.Attributes = CONF_ENABLE_IRQ;
+ link->conf.Vcc = 50;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+
+ /* Register with Card Services */
+ link->next = dev_list;
+ dev_list = link;
+ client_reg.dev_info = &dev_info;
+ client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+ client_reg.EventMask =
+ CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+ CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+ CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+ client_reg.event_handler = &bt3c_event;
+ client_reg.Version = 0x0210;
+ client_reg.event_callback_args.client_data = link;
+
+ ret = CardServices(RegisterClient, &link->handle, &client_reg);
+ if (ret != CS_SUCCESS) {
+ cs_error(link->handle, RegisterClient, ret);
+ bt3c_detach(link);
+ return NULL;
+ }
+
+ return link;
+}
+
+
+void bt3c_detach(dev_link_t *link)
+{
+ bt3c_info_t *info = link->priv;
+ dev_link_t **linkp;
+ int ret;
+
+ /* Locate device structure */
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+ if (*linkp == link)
+ break;
+
+ if (*linkp == NULL)
+ return;
+
+ del_timer(&link->release);
+
+ if (link->state & DEV_CONFIG)
+ bt3c_release((u_long)link);
+
+ if (link->handle) {
+ ret = CardServices(DeregisterClient, link->handle);
+ if (ret != CS_SUCCESS)
+ cs_error(link->handle, DeregisterClient, ret);
+ }
+
+ /* Unlink device structure, free bits */
+ *linkp = link->next;
+
+ kfree(info);
+}
+
+
+static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+{
+ int i;
+
+ i = CardServices(fn, handle, tuple);
+ if (i != CS_SUCCESS)
+ return CS_NO_MORE_ITEMS;
+
+ i = CardServices(GetTupleData, handle, tuple);
+ if (i != CS_SUCCESS)
+ return i;
+
+ return CardServices(ParseTuple, handle, tuple, parse);
+}
+
+
+#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
+#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
+
+void bt3c_config(dev_link_t *link)
+{
+ static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ client_handle_t handle = link->handle;
+ bt3c_info_t *info = link->priv;
+ tuple_t tuple;
+ u_short buf[256];
+ cisparse_t parse;
+ cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+ config_info_t config;
+ int i, j, try, last_ret, last_fn;
+
+ tuple.TupleData = (cisdata_t *)buf;
+ tuple.TupleOffset = 0;
+ tuple.TupleDataMax = 255;
+ tuple.Attributes = 0;
+
+ /* Get configuration register information */
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ last_ret = first_tuple(handle, &tuple, &parse);
+ if (last_ret != CS_SUCCESS) {
+ last_fn = ParseTuple;
+ goto cs_failed;
+ }
+ link->conf.ConfigBase = parse.config.base;
+ link->conf.Present = parse.config.rmask[0];
+
+ /* Configure card */
+ link->state |= DEV_CONFIG;
+ i = CardServices(GetConfigurationInfo, handle, &config);
+ link->conf.Vcc = config.Vcc;
+
+ /* First pass: look for a config entry that looks normal. */
+ tuple.TupleData = (cisdata_t *)buf;
+ tuple.TupleOffset = 0;
+ tuple.TupleDataMax = 255;
+ tuple.Attributes = 0;
+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ /* Two tries: without IO aliases, then with aliases */
+ for (try = 0; try < 2; try++) {
+ i = first_tuple(handle, &tuple, &parse);
+ while (i != CS_NO_MORE_ITEMS) {
+ if (i != CS_SUCCESS)
+ goto next_entry;
+ if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
+ link->conf.ConfigIndex = cf->index;
+ link->io.BasePort1 = cf->io.win[0].base;
+ link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+ i = CardServices(RequestIO, link->handle, &link->io);
+ if (i == CS_SUCCESS)
+ goto found_port;
+ }
+next_entry:
+ i = next_tuple(handle, &tuple, &parse);
+ }
+ }
+
+ /* Second pass: try to find an entry that isn't picky about
+ its base address, then try to grab any standard serial port
+ address, and finally try to get any free port. */
+ i = first_tuple(handle, &tuple, &parse);
+ while (i != CS_NO_MORE_ITEMS) {
+ if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
+ link->conf.ConfigIndex = cf->index;
+ for (j = 0; j < 5; j++) {
+ link->io.BasePort1 = base[j];
+ link->io.IOAddrLines = base[j] ? 16 : 3;
+ i = CardServices(RequestIO, link->handle, &link->io);
+ if (i == CS_SUCCESS)
+ goto found_port;
+ }
+ }
+ i = next_tuple(handle, &tuple, &parse);
+ }
+
+found_port:
+ if (i != CS_SUCCESS) {
+ printk(KERN_NOTICE "bt3c_cs: No usable port range found. Giving up.\n");
+ cs_error(link->handle, RequestIO, i);
+ goto failed;
+ }
+
+ i = CardServices(RequestIRQ, link->handle, &link->irq);
+ if (i != CS_SUCCESS) {
+ cs_error(link->handle, RequestIRQ, i);
+ link->irq.AssignedIRQ = 0;
+ }
+
+ i = CardServices(RequestConfiguration, link->handle, &link->conf);
+ if (i != CS_SUCCESS) {
+ cs_error(link->handle, RequestConfiguration, i);
+ goto failed;
+ }
+
+ MOD_INC_USE_COUNT;
+
+ if (bt3c_open(info) != 0)
+ goto failed;
+
+ strcpy(info->node.dev_name, info->hdev.name);
+ link->dev = &info->node;
+ link->state &= ~DEV_CONFIG_PENDING;
+
+ return;
+
+cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+
+failed:
+ bt3c_release((u_long)link);
+}
+
+
+void bt3c_release(u_long arg)
+{
+ dev_link_t *link = (dev_link_t *)arg;
+ bt3c_info_t *info = link->priv;
+
+ if (link->state & DEV_PRESENT)
+ bt3c_close(info);
+
+ MOD_DEC_USE_COUNT;
+
+ link->dev = NULL;
+
+ CardServices(ReleaseConfiguration, link->handle);
+ CardServices(ReleaseIO, link->handle, &link->io);
+ CardServices(ReleaseIRQ, link->handle, &link->irq);
+
+ link->state &= ~DEV_CONFIG;
+}
+
+
+int bt3c_event(event_t event, int priority, event_callback_args_t *args)
+{
+ dev_link_t *link = args->client_data;
+ bt3c_info_t *info = link->priv;
+
+ switch (event) {
+ case CS_EVENT_CARD_REMOVAL:
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG) {
+ bt3c_close(info);
+ mod_timer(&link->release, jiffies + HZ / 20);
+ }
+ break;
+ case CS_EVENT_CARD_INSERTION:
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ bt3c_config(link);
+ break;
+ case CS_EVENT_PM_SUSPEND:
+ link->state |= DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_RESET_PHYSICAL:
+ if (link->state & DEV_CONFIG)
+ CardServices(ReleaseConfiguration, link->handle);
+ break;
+ case CS_EVENT_PM_RESUME:
+ link->state &= ~DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_CARD_RESET:
+ if (DEV_OK(link))
+ CardServices(RequestConfiguration, link->handle, &link->conf);
+ break;
+ }
+
+ return 0;
+}
+
+
+
+/* ======================== Module initialization ======================== */
+
+
+int __init init_bt3c_cs(void)
+{
+ servinfo_t serv;
+ int err;
+
+ CardServices(GetCardServicesInfo, &serv);
+ if (serv.Revision != CS_RELEASE_CODE) {
+ printk(KERN_NOTICE "bt3c_cs: Card Services release does not match!\n");
+ return -1;
+ }
+
+ err = register_pccard_driver(&dev_info, &bt3c_attach, &bt3c_detach);
+
+ return err;
+}
+
+
+void __exit exit_bt3c_cs(void)
+{
+ unregister_pccard_driver(&dev_info);
+
+ while (dev_list != NULL)
+ bt3c_detach(dev_list);
+}
+
+
+module_init(init_bt3c_cs);
+module_exit(exit_bt3c_cs);
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 97f32d8e0049..80df236ec1dc 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -75,23 +75,22 @@ MODULE_LICENSE("GPL");
typedef struct dtl1_info_t {
- dev_link_t link;
- dev_node_t node;
+ dev_link_t link;
+ dev_node_t node;
- struct hci_dev hdev;
+ struct hci_dev hdev;
- spinlock_t lock; /* For serializing operations */
+ spinlock_t lock; /* For serializing operations */
- unsigned long flowmask; /* HCI flow mask */
- int ri_latch;
+ unsigned long flowmask; /* HCI flow mask */
+ int ri_latch;
- struct sk_buff_head txq;
- unsigned long tx_state;
-
- unsigned long rx_state;
- unsigned long rx_count;
- struct sk_buff *rx_skb;
+ struct sk_buff_head txq;
+ unsigned long tx_state;
+ unsigned long rx_state;
+ unsigned long rx_count;
+ struct sk_buff *rx_skb;
} dtl1_info_t;
@@ -104,7 +103,7 @@ static dev_info_t dev_info = "dtl1_cs";
dev_link_t *dtl1_attach(void);
void dtl1_detach(dev_link_t *);
-dev_link_t *dev_list = NULL;
+static dev_link_t *dev_list = NULL;
/* Transmit states */
@@ -118,282 +117,253 @@ dev_link_t *dev_list = NULL;
typedef struct {
- u8 type;
- u8 zero;
- u16 len;
-} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */
+ u8 type;
+ u8 zero;
+ u16 len;
+} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */
-#define NSHL 4 /* Nokia Specific Header Length */
+#define NSHL 4 /* Nokia Specific Header Length */
/* ======================== Interrupt handling ======================== */
-static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) {
-
- int actual = 0;
-
-
- /* Tx FIFO should be empty */
- if (!(inb(iobase + UART_LSR) & UART_LSR_THRE))
- return 0;
-
+static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
+{
+ int actual = 0;
- /* Fill FIFO with current frame */
- while ((fifo_size-- > 0) && (actual < len)) {
- /* Transmit next byte */
- outb(buf[actual], iobase + UART_TX);
- actual++;
- }
+ /* Tx FIFO should be empty */
+ if (!(inb(iobase + UART_LSR) & UART_LSR_THRE))
+ return 0;
+ /* Fill FIFO with current frame */
+ while ((fifo_size-- > 0) && (actual < len)) {
+ /* Transmit next byte */
+ outb(buf[actual], iobase + UART_TX);
+ actual++;
+ }
- return actual;
-
+ return actual;
}
-static void dtl1_write_wakeup(dtl1_info_t *info) {
-
- if (!info) {
- printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n");
- return;
- }
-
-
- if (test_bit(XMIT_WAITING, &(info->tx_state))) {
- set_bit(XMIT_WAKEUP, &(info->tx_state));
- return;
- }
-
- if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
- set_bit(XMIT_WAKEUP, &(info->tx_state));
- return;
- }
+static void dtl1_write_wakeup(dtl1_info_t *info)
+{
+ if (!info) {
+ printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n");
+ return;
+ }
+ if (test_bit(XMIT_WAITING, &(info->tx_state))) {
+ set_bit(XMIT_WAKEUP, &(info->tx_state));
+ return;
+ }
- do {
- register unsigned int iobase = info->link.io.BasePort1;
- register struct sk_buff *skb;
- register int len;
+ if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
+ set_bit(XMIT_WAKEUP, &(info->tx_state));
+ return;
+ }
- clear_bit(XMIT_WAKEUP, &(info->tx_state));
+ do {
+ register unsigned int iobase = info->link.io.BasePort1;
+ register struct sk_buff *skb;
+ register int len;
- if (!(info->link.state & DEV_PRESENT))
- return;
+ clear_bit(XMIT_WAKEUP, &(info->tx_state));
+ if (!(info->link.state & DEV_PRESENT))
+ return;
- if (!(skb = skb_dequeue(&(info->txq))))
- break;
+ if (!(skb = skb_dequeue(&(info->txq))))
+ break;
+ /* Send frame */
+ len = dtl1_write(iobase, 32, skb->data, skb->len);
- /* Send frame */
- len = dtl1_write(iobase, 32, skb->data, skb->len);
+ if (len == skb->len) {
+ set_bit(XMIT_WAITING, &(info->tx_state));
+ kfree_skb(skb);
+ } else {
+ skb_pull(skb, len);
+ skb_queue_head(&(info->txq), skb);
+ }
- if (len == skb->len) {
- set_bit(XMIT_WAITING, &(info->tx_state));
- kfree_skb(skb);
- }
- else {
- skb_pull(skb, len);
- skb_queue_head(&(info->txq), skb);
- }
+ info->hdev.stat.byte_tx += len;
- info->hdev.stat.byte_tx += len;
-
- } while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
-
-
- clear_bit(XMIT_SENDING, &(info->tx_state));
+ } while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
+ clear_bit(XMIT_SENDING, &(info->tx_state));
}
-static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb) {
-
- u8 flowmask = *(u8 *)skb->data;
- int i;
-
+static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb)
+{
+ u8 flowmask = *(u8 *)skb->data;
+ int i;
- printk(KERN_INFO "dtl1_cs: Nokia control data = ");
- for (i = 0; i < skb->len; i++) {
- printk("%02x ", skb->data[i]);
- }
- printk("\n");
+ printk(KERN_INFO "dtl1_cs: Nokia control data = ");
+ for (i = 0; i < skb->len; i++) {
+ printk("%02x ", skb->data[i]);
+ }
+ printk("\n");
+ /* transition to active state */
+ if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) {
+ clear_bit(XMIT_WAITING, &(info->tx_state));
+ dtl1_write_wakeup(info);
+ }
- /* transition to active state */
- if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) {
- clear_bit(XMIT_WAITING, &(info->tx_state));
- dtl1_write_wakeup(info);
- }
-
- info->flowmask = flowmask;
-
-
- kfree_skb(skb);
+ info->flowmask = flowmask;
+ kfree_skb(skb);
}
-static void dtl1_receive(dtl1_info_t *info) {
-
- unsigned int iobase;
- nsh_t *nsh;
- int boguscount = 0;
-
-
- if (!info) {
- printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n");
- return;
- }
-
-
- iobase = info->link.io.BasePort1;
-
- do {
- info->hdev.stat.byte_rx++;
-
- /* Allocate packet */
- if (info->rx_skb == NULL)
- if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
- printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n");
- info->rx_state = RECV_WAIT_NSH;
- info->rx_count = NSHL;
- return;
- }
-
-
- *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
- nsh = (nsh_t *)info->rx_skb->data;
-
- info->rx_count--;
-
-
- if (info->rx_count == 0) {
-
- switch (info->rx_state) {
- case RECV_WAIT_NSH:
- info->rx_state = RECV_WAIT_DATA;
- info->rx_count = nsh->len + (nsh->len & 0x0001);
- break;
- case RECV_WAIT_DATA:
- info->rx_skb->pkt_type = nsh->type;
-
- /* remove PAD byte if it exists */
- if (nsh->len & 0x0001) {
- info->rx_skb->tail--;
- info->rx_skb->len--;
- }
-
- /* remove NSH */
- skb_pull(info->rx_skb, NSHL);
-
-
- switch (info->rx_skb->pkt_type) {
- case 0x80:
- /* control data for the Nokia Card */
- dtl1_control(info, info->rx_skb);
- break;
- case 0x82:
- case 0x83:
- case 0x84:
- /* send frame to the HCI layer */
- info->rx_skb->dev = (void *)&(info->hdev);
- info->rx_skb->pkt_type &= 0x0f;
- hci_recv_frame(info->rx_skb);
- break;
- default:
- /* unknown packet */
- printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
- kfree_skb(info->rx_skb);
- break;
- }
-
-
- info->rx_state = RECV_WAIT_NSH;
- info->rx_count = NSHL;
- info->rx_skb = NULL;
- break;
- }
-
- }
-
-
- /* Make sure we don't stay here to long */
- if (boguscount++ > 32)
- break;
-
- } while (inb(iobase + UART_LSR) & UART_LSR_DR);
-
-
+static void dtl1_receive(dtl1_info_t *info)
+{
+ unsigned int iobase;
+ nsh_t *nsh;
+ int boguscount = 0;
+
+ if (!info) {
+ printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n");
+ return;
+ }
+
+ iobase = info->link.io.BasePort1;
+
+ do {
+ info->hdev.stat.byte_rx++;
+
+ /* Allocate packet */
+ if (info->rx_skb == NULL)
+ if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
+ printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n");
+ info->rx_state = RECV_WAIT_NSH;
+ info->rx_count = NSHL;
+ return;
+ }
+
+ *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
+ nsh = (nsh_t *)info->rx_skb->data;
+
+ info->rx_count--;
+
+ if (info->rx_count == 0) {
+
+ switch (info->rx_state) {
+ case RECV_WAIT_NSH:
+ info->rx_state = RECV_WAIT_DATA;
+ info->rx_count = nsh->len + (nsh->len & 0x0001);
+ break;
+ case RECV_WAIT_DATA:
+ info->rx_skb->pkt_type = nsh->type;
+
+ /* remove PAD byte if it exists */
+ if (nsh->len & 0x0001) {
+ info->rx_skb->tail--;
+ info->rx_skb->len--;
+ }
+
+ /* remove NSH */
+ skb_pull(info->rx_skb, NSHL);
+
+ switch (info->rx_skb->pkt_type) {
+ case 0x80:
+ /* control data for the Nokia Card */
+ dtl1_control(info, info->rx_skb);
+ break;
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ /* send frame to the HCI layer */
+ info->rx_skb->dev = (void *)&(info->hdev);
+ info->rx_skb->pkt_type &= 0x0f;
+ hci_recv_frame(info->rx_skb);
+ break;
+ default:
+ /* unknown packet */
+ printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
+ kfree_skb(info->rx_skb);
+ break;
+ }
+
+ info->rx_state = RECV_WAIT_NSH;
+ info->rx_count = NSHL;
+ info->rx_skb = NULL;
+ break;
+ }
+
+ }
+
+ /* Make sure we don't stay here to long */
+ if (boguscount++ > 32)
+ break;
+
+ } while (inb(iobase + UART_LSR) & UART_LSR_DR);
}
-void dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs) {
-
- dtl1_info_t *info = dev_inst;
- unsigned int iobase;
- unsigned char msr;
- int boguscount = 0;
- int iir, lsr;
-
-
- if (!info) {
- printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq);
- return;
- }
-
-
- iobase = info->link.io.BasePort1;
-
-
- spin_lock(&(info->lock));
-
- iir = inb(iobase + UART_IIR) & UART_IIR_ID;
- while (iir) {
-
- /* Clear interrupt */
- lsr = inb(iobase + UART_LSR);
-
- switch (iir) {
- case UART_IIR_RLSI:
- printk(KERN_NOTICE "dtl1_cs: RLSI\n");
- break;
- case UART_IIR_RDI:
- /* Receive interrupt */
- dtl1_receive(info);
- break;
- case UART_IIR_THRI:
- if (lsr & UART_LSR_THRE) {
- /* Transmitter ready for data */
- dtl1_write_wakeup(info);
- }
- break;
- default:
- printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir);
- break;
- }
-
- /* Make sure we don't stay here to long */
- if (boguscount++ > 100)
- break;
-
- iir = inb(iobase + UART_IIR) & UART_IIR_ID;
-
- }
-
-
- msr = inb(iobase + UART_MSR);
-
- if (info->ri_latch ^ (msr & UART_MSR_RI)) {
- info->ri_latch = msr & UART_MSR_RI;
- clear_bit(XMIT_WAITING, &(info->tx_state));
- dtl1_write_wakeup(info);
- }
-
- spin_unlock(&(info->lock));
-
+void dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
+{
+ dtl1_info_t *info = dev_inst;
+ unsigned int iobase;
+ unsigned char msr;
+ int boguscount = 0;
+ int iir, lsr;
+
+ if (!info) {
+ printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq);
+ return;
+ }
+
+ iobase = info->link.io.BasePort1;
+
+ spin_lock(&(info->lock));
+
+ iir = inb(iobase + UART_IIR) & UART_IIR_ID;
+ while (iir) {
+
+ /* Clear interrupt */
+ lsr = inb(iobase + UART_LSR);
+
+ switch (iir) {
+ case UART_IIR_RLSI:
+ printk(KERN_NOTICE "dtl1_cs: RLSI\n");
+ break;
+ case UART_IIR_RDI:
+ /* Receive interrupt */
+ dtl1_receive(info);
+ break;
+ case UART_IIR_THRI:
+ if (lsr & UART_LSR_THRE) {
+ /* Transmitter ready for data */
+ dtl1_write_wakeup(info);
+ }
+ break;
+ default:
+ printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir);
+ break;
+ }
+
+ /* Make sure we don't stay here to long */
+ if (boguscount++ > 100)
+ break;
+
+ iir = inb(iobase + UART_IIR) & UART_IIR_ID;
+
+ }
+
+ msr = inb(iobase + UART_MSR);
+
+ if (info->ri_latch ^ (msr & UART_MSR_RI)) {
+ info->ri_latch = msr & UART_MSR_RI;
+ clear_bit(XMIT_WAITING, &(info->tx_state));
+ dtl1_write_wakeup(info);
+ }
+
+ spin_unlock(&(info->lock));
}
@@ -401,107 +371,94 @@ void dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs) {
/* ======================== HCI interface ======================== */
-static int dtl1_hci_open(struct hci_dev *hdev) {
-
- set_bit(HCI_RUNNING, &(hdev->flags));
-
-
- return 0;
+static int dtl1_hci_open(struct hci_dev *hdev)
+{
+ set_bit(HCI_RUNNING, &(hdev->flags));
+ return 0;
}
-static int dtl1_hci_flush(struct hci_dev *hdev) {
-
- dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data);
+static int dtl1_hci_flush(struct hci_dev *hdev)
+{
+ dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data);
+ /* Drop TX queue */
+ skb_queue_purge(&(info->txq));
- /* Drop TX queue */
- skb_queue_purge(&(info->txq));
-
-
- return 0;
-
+ return 0;
}
-static int dtl1_hci_close(struct hci_dev *hdev) {
-
- if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
- return 0;
-
+static int dtl1_hci_close(struct hci_dev *hdev)
+{
+ if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
+ return 0;
- dtl1_hci_flush(hdev);
-
-
- return 0;
+ dtl1_hci_flush(hdev);
+ return 0;
}
-static int dtl1_hci_send_frame(struct sk_buff *skb) {
-
- dtl1_info_t *info;
- struct hci_dev* hdev = (struct hci_dev *)(skb->dev);
- struct sk_buff *s;
- nsh_t nsh;
-
-
- if (!hdev) {
- printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL).");
- return -ENODEV;
- }
-
- info = (dtl1_info_t *)(hdev->driver_data);
-
-
- switch (skb->pkt_type) {
- case HCI_COMMAND_PKT:
- hdev->stat.cmd_tx++;
- nsh.type = 0x81;
- break;
- case HCI_ACLDATA_PKT:
- hdev->stat.acl_tx++;
- nsh.type = 0x82;
- break;
- case HCI_SCODATA_PKT:
- hdev->stat.sco_tx++;
- nsh.type = 0x83;
- break;
- };
-
- nsh.zero = 0;
- nsh.len = skb->len;
-
- s = bluez_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC);
- skb_reserve(s, NSHL);
- memcpy(skb_put(s, skb->len), skb->data, skb->len);
- if (skb->len & 0x0001)
- *skb_put(s, 1) = 0; /* PAD */
-
- /* Prepend skb with Nokia frame header and queue */
- memcpy(skb_push(s, NSHL), &nsh, NSHL);
- skb_queue_tail(&(info->txq), s);
-
-
- dtl1_write_wakeup(info);
-
- kfree_skb(skb);
-
-
- return 0;
-
+static int dtl1_hci_send_frame(struct sk_buff *skb)
+{
+ dtl1_info_t *info;
+ struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
+ struct sk_buff *s;
+ nsh_t nsh;
+
+ if (!hdev) {
+ printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL).");
+ return -ENODEV;
+ }
+
+ info = (dtl1_info_t *)(hdev->driver_data);
+
+ switch (skb->pkt_type) {
+ case HCI_COMMAND_PKT:
+ hdev->stat.cmd_tx++;
+ nsh.type = 0x81;
+ break;
+ case HCI_ACLDATA_PKT:
+ hdev->stat.acl_tx++;
+ nsh.type = 0x82;
+ break;
+ case HCI_SCODATA_PKT:
+ hdev->stat.sco_tx++;
+ nsh.type = 0x83;
+ break;
+ };
+
+ nsh.zero = 0;
+ nsh.len = skb->len;
+
+ s = bluez_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC);
+ skb_reserve(s, NSHL);
+ memcpy(skb_put(s, skb->len), skb->data, skb->len);
+ if (skb->len & 0x0001)
+ *skb_put(s, 1) = 0; /* PAD */
+
+ /* Prepend skb with Nokia frame header and queue */
+ memcpy(skb_push(s, NSHL), &nsh, NSHL);
+ skb_queue_tail(&(info->txq), s);
+
+ dtl1_write_wakeup(info);
+
+ kfree_skb(skb);
+
+ return 0;
}
-static void dtl1_hci_destruct(struct hci_dev *hdev) {
+static void dtl1_hci_destruct(struct hci_dev *hdev)
+{
}
-static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) {
-
- return -ENOIOCTLCMD;
-
+static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
+{
+ return -ENOIOCTLCMD;
}
@@ -509,101 +466,91 @@ static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long
/* ======================== Card services HCI interaction ======================== */
-int dtl1_open(dtl1_info_t *info) {
-
- unsigned long flags;
- unsigned int iobase = info->link.io.BasePort1;
- struct hci_dev *hdev;
+int dtl1_open(dtl1_info_t *info)
+{
+ unsigned long flags;
+ unsigned int iobase = info->link.io.BasePort1;
+ struct hci_dev *hdev;
+ spin_lock_init(&(info->lock));
- spin_lock_init(&(info->lock));
+ skb_queue_head_init(&(info->txq));
- skb_queue_head_init(&(info->txq));
+ info->rx_state = RECV_WAIT_NSH;
+ info->rx_count = NSHL;
+ info->rx_skb = NULL;
- info->rx_state = RECV_WAIT_NSH;
- info->rx_count = NSHL;
- info->rx_skb = NULL;
+ set_bit(XMIT_WAITING, &(info->tx_state));
- set_bit(XMIT_WAITING, &(info->tx_state));
+ spin_lock_irqsave(&(info->lock), flags);
+ /* Reset UART */
+ outb(0, iobase + UART_MCR);
- spin_lock_irqsave(&(info->lock), flags);
+ /* Turn off interrupts */
+ outb(0, iobase + UART_IER);
- /* Reset UART */
- outb(0, iobase + UART_MCR);
+ /* Initialize UART */
+ outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */
+ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
- /* Turn off interrupts */
- outb(0, iobase + UART_IER);
+ info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI;
- /* Initialize UART */
- outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */
- outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
+ /* Turn on interrupts */
+ outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
- info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI;
+ spin_unlock_irqrestore(&(info->lock), flags);
- /* Turn on interrupts */
- outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
+ /* Timeout before it is safe to send the first HCI packet */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ * 2);
- spin_unlock_irqrestore(&(info->lock), flags);
+ /* Initialize and register HCI device */
- /* Timeout before it is safe to send the first HCI packet */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ * 2);
+ hdev = &(info->hdev);
+ hdev->type = HCI_PCCARD;
+ hdev->driver_data = info;
- /* Initialize and register HCI device */
+ hdev->open = dtl1_hci_open;
+ hdev->close = dtl1_hci_close;
+ hdev->flush = dtl1_hci_flush;
+ hdev->send = dtl1_hci_send_frame;
+ hdev->destruct = dtl1_hci_destruct;
+ hdev->ioctl = dtl1_hci_ioctl;
- hdev = &(info->hdev);
-
- hdev->type = HCI_PCCARD;
- hdev->driver_data = info;
-
- hdev->open = dtl1_hci_open;
- hdev->close = dtl1_hci_close;
- hdev->flush = dtl1_hci_flush;
- hdev->send = dtl1_hci_send_frame;
- hdev->destruct = dtl1_hci_destruct;
- hdev->ioctl = dtl1_hci_ioctl;
-
- if (hci_register_dev(hdev) < 0) {
- printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name);
- return -ENODEV;
- }
-
-
- return 0;
+ if (hci_register_dev(hdev) < 0) {
+ printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name);
+ return -ENODEV;
+ }
+ return 0;
}
-int dtl1_close(dtl1_info_t *info) {
-
- unsigned long flags;
- unsigned int iobase = info->link.io.BasePort1;
- struct hci_dev *hdev = &(info->hdev);
-
-
- dtl1_hci_close(hdev);
-
-
- spin_lock_irqsave(&(info->lock), flags);
+int dtl1_close(dtl1_info_t *info)
+{
+ unsigned long flags;
+ unsigned int iobase = info->link.io.BasePort1;
+ struct hci_dev *hdev = &(info->hdev);
- /* Reset UART */
- outb(0, iobase + UART_MCR);
+ dtl1_hci_close(hdev);
- /* Turn off interrupts */
- outb(0, iobase + UART_IER);
+ spin_lock_irqsave(&(info->lock), flags);
- spin_unlock_irqrestore(&(info->lock), flags);
+ /* Reset UART */
+ outb(0, iobase + UART_MCR);
+ /* Turn off interrupts */
+ outb(0, iobase + UART_IER);
- if (hci_unregister_dev(hdev) < 0)
- printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name);
+ spin_unlock_irqrestore(&(info->lock), flags);
+ if (hci_unregister_dev(hdev) < 0)
+ printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name);
- return 0;
-
+ return 0;
}
@@ -611,291 +558,267 @@ int dtl1_close(dtl1_info_t *info) {
/* ======================== Card services ======================== */
-static void cs_error(client_handle_t handle, int func, int ret) {
-
- error_info_t err = { func, ret };
-
-
- CardServices(ReportError, handle, &err);
+static void cs_error(client_handle_t handle, int func, int ret)
+{
+ error_info_t err = { func, ret };
+ CardServices(ReportError, handle, &err);
}
-dev_link_t *dtl1_attach(void) {
-
- dtl1_info_t *info;
- client_reg_t client_reg;
- dev_link_t *link;
- int i, ret;
-
-
- /* Create new info device */
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- return NULL;
- memset(info, 0, sizeof(*info));
-
-
- link = &info->link;
- link->priv = info;
-
- link->release.function = &dtl1_release;
- link->release.data = (u_long)link;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.NumPorts1 = 8;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
- link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
-
- if (irq_list[0] == -1)
- link->irq.IRQInfo2 = irq_mask;
- else
- for (i = 0; i < 4; i++)
- link->irq.IRQInfo2 |= 1 << irq_list[i];
-
- link->irq.Handler = dtl1_interrupt;
- link->irq.Instance = info;
-
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
-
- /* Register with Card Services */
- link->next = dev_list;
- dev_list = link;
- client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
- client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
- client_reg.event_handler = &dtl1_event;
- client_reg.Version = 0x0210;
- client_reg.event_callback_args.client_data = link;
-
- ret = CardServices(RegisterClient, &link->handle, &client_reg);
- if (ret != CS_SUCCESS) {
- cs_error(link->handle, RegisterClient, ret);
- dtl1_detach(link);
- return NULL;
- }
-
-
- return link;
-
+dev_link_t *dtl1_attach(void)
+{
+ dtl1_info_t *info;
+ client_reg_t client_reg;
+ dev_link_t *link;
+ int i, ret;
+
+ /* Create new info device */
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return NULL;
+ memset(info, 0, sizeof(*info));
+
+ link = &info->link;
+ link->priv = info;
+
+ link->release.function = &dtl1_release;
+ link->release.data = (u_long)link;
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ link->io.NumPorts1 = 8;
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
+
+ if (irq_list[0] == -1)
+ link->irq.IRQInfo2 = irq_mask;
+ else
+ for (i = 0; i < 4; i++)
+ link->irq.IRQInfo2 |= 1 << irq_list[i];
+
+ link->irq.Handler = dtl1_interrupt;
+ link->irq.Instance = info;
+
+ link->conf.Attributes = CONF_ENABLE_IRQ;
+ link->conf.Vcc = 50;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+
+ /* Register with Card Services */
+ link->next = dev_list;
+ dev_list = link;
+ client_reg.dev_info = &dev_info;
+ client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+ client_reg.EventMask =
+ CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+ CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+ CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+ client_reg.event_handler = &dtl1_event;
+ client_reg.Version = 0x0210;
+ client_reg.event_callback_args.client_data = link;
+
+ ret = CardServices(RegisterClient, &link->handle, &client_reg);
+ if (ret != CS_SUCCESS) {
+ cs_error(link->handle, RegisterClient, ret);
+ dtl1_detach(link);
+ return NULL;
+ }
+
+ return link;
}
-void dtl1_detach(dev_link_t *link) {
-
- dtl1_info_t *info = link->priv;
- dev_link_t **linkp;
- int ret;
+void dtl1_detach(dev_link_t *link)
+{
+ dtl1_info_t *info = link->priv;
+ dev_link_t **linkp;
+ int ret;
+ /* Locate device structure */
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+ if (*linkp == link)
+ break;
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
+ if (*linkp == NULL)
+ return;
- if (*linkp == NULL)
- return;
+ del_timer(&link->release);
+ if (link->state & DEV_CONFIG)
+ dtl1_release((u_long)link);
+ if (link->handle) {
+ ret = CardServices(DeregisterClient, link->handle);
+ if (ret != CS_SUCCESS)
+ cs_error(link->handle, DeregisterClient, ret);
+ }
- del_timer(&link->release);
- if (link->state & DEV_CONFIG)
- dtl1_release((u_long)link);
-
-
- if (link->handle) {
- ret = CardServices(DeregisterClient, link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
- }
-
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
-
- kfree(info);
+ /* Unlink device structure, free bits */
+ *linkp = link->next;
+ kfree(info);
}
-static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple,
- cisparse_t *parse) {
+static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+{
+ int i;
- int i;
+ i = CardServices(fn, handle, tuple);
+ if (i != CS_SUCCESS)
+ return CS_NO_MORE_ITEMS;
+ i = CardServices(GetTupleData, handle, tuple);
+ if (i != CS_SUCCESS)
+ return i;
- i = CardServices(fn, handle, tuple);
- if (i != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
-
- i = CardServices(GetTupleData, handle, tuple);
- if (i != CS_SUCCESS)
- return i;
-
- return CardServices(ParseTuple, handle, tuple, parse);
-
+ return CardServices(ParseTuple, handle, tuple, parse);
}
#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
-void dtl1_config(dev_link_t *link) {
-
- client_handle_t handle = link->handle;
- dtl1_info_t *info = link->priv;
- tuple_t tuple;
- u_short buf[256];
- cisparse_t parse;
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- config_info_t config;
- int i, last_ret, last_fn;
-
-
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
-
- /* Get configuration register information */
- tuple.DesiredTuple = CISTPL_CONFIG;
- last_ret = first_tuple(handle, &tuple, &parse);
- if (last_ret != CS_SUCCESS) {
- last_fn = ParseTuple;
- goto cs_failed;
- }
- link->conf.ConfigBase = parse.config.base;
- link->conf.Present = parse.config.rmask[0];
-
-
- /* Configure card */
- link->state |= DEV_CONFIG;
- i = CardServices(GetConfigurationInfo, handle, &config);
- link->conf.Vcc = config.Vcc;
-
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
- /* Look for a generic full-sized window */
- link->io.NumPorts1 = 8;
- i = first_tuple(handle, &tuple, &parse);
- while (i != CS_NO_MORE_ITEMS) {
- if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.NumPorts1 = cf->io.win[0].len; /*yo*/
- link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
- i = CardServices(RequestIO, link->handle, &link->io);
- if (i == CS_SUCCESS)
- break;
- }
- i = next_tuple(handle, &tuple, &parse);
- }
-
- if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIO, i);
- goto failed;
- }
-
- i = CardServices(RequestIRQ, link->handle, &link->irq);
- if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestIRQ, i);
- link->irq.AssignedIRQ = 0;
- }
-
- i = CardServices(RequestConfiguration, link->handle, &link->conf);
- if (i != CS_SUCCESS) {
- cs_error(link->handle, RequestConfiguration, i);
- goto failed;
- }
-
-
- MOD_INC_USE_COUNT;
-
- if (dtl1_open(info) != 0)
- goto failed;
-
-
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
-
-
- return;
-
+void dtl1_config(dev_link_t *link)
+{
+ client_handle_t handle = link->handle;
+ dtl1_info_t *info = link->priv;
+ tuple_t tuple;
+ u_short buf[256];
+ cisparse_t parse;
+ cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+ config_info_t config;
+ int i, last_ret, last_fn;
+
+ tuple.TupleData = (cisdata_t *)buf;
+ tuple.TupleOffset = 0;
+ tuple.TupleDataMax = 255;
+ tuple.Attributes = 0;
+
+ /* Get configuration register information */
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ last_ret = first_tuple(handle, &tuple, &parse);
+ if (last_ret != CS_SUCCESS) {
+ last_fn = ParseTuple;
+ goto cs_failed;
+ }
+ link->conf.ConfigBase = parse.config.base;
+ link->conf.Present = parse.config.rmask[0];
+
+ /* Configure card */
+ link->state |= DEV_CONFIG;
+ i = CardServices(GetConfigurationInfo, handle, &config);
+ link->conf.Vcc = config.Vcc;
+
+ tuple.TupleData = (cisdata_t *)buf;
+ tuple.TupleOffset = 0;
+ tuple.TupleDataMax = 255;
+ tuple.Attributes = 0;
+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+
+ /* Look for a generic full-sized window */
+ link->io.NumPorts1 = 8;
+ i = first_tuple(handle, &tuple, &parse);
+ while (i != CS_NO_MORE_ITEMS) {
+ if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
+ link->conf.ConfigIndex = cf->index;
+ link->io.BasePort1 = cf->io.win[0].base;
+ link->io.NumPorts1 = cf->io.win[0].len; /*yo */
+ link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+ i = CardServices(RequestIO, link->handle, &link->io);
+ if (i == CS_SUCCESS)
+ break;
+ }
+ i = next_tuple(handle, &tuple, &parse);
+ }
+
+ if (i != CS_SUCCESS) {
+ cs_error(link->handle, RequestIO, i);
+ goto failed;
+ }
+
+ i = CardServices(RequestIRQ, link->handle, &link->irq);
+ if (i != CS_SUCCESS) {
+ cs_error(link->handle, RequestIRQ, i);
+ link->irq.AssignedIRQ = 0;
+ }
+
+ i = CardServices(RequestConfiguration, link->handle, &link->conf);
+ if (i != CS_SUCCESS) {
+ cs_error(link->handle, RequestConfiguration, i);
+ goto failed;
+ }
+
+ MOD_INC_USE_COUNT;
+
+ if (dtl1_open(info) != 0)
+ goto failed;
+
+ strcpy(info->node.dev_name, info->hdev.name);
+ link->dev = &info->node;
+ link->state &= ~DEV_CONFIG_PENDING;
+
+ return;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
-failed:
- dtl1_release((u_long)link);
+ cs_error(link->handle, last_fn, last_ret);
+failed:
+ dtl1_release((u_long)link);
}
-void dtl1_release(u_long arg) {
-
- dev_link_t *link = (dev_link_t *)arg;
- dtl1_info_t *info = link->priv;
+void dtl1_release(u_long arg)
+{
+ dev_link_t *link = (dev_link_t *)arg;
+ dtl1_info_t *info = link->priv;
+ if (link->state & DEV_PRESENT)
+ dtl1_close(info);
- if (link->state & DEV_PRESENT)
- dtl1_close(info);
+ MOD_DEC_USE_COUNT;
- MOD_DEC_USE_COUNT;
+ link->dev = NULL;
+ CardServices(ReleaseConfiguration, link->handle);
+ CardServices(ReleaseIO, link->handle, &link->io);
+ CardServices(ReleaseIRQ, link->handle, &link->irq);
- link->dev = NULL;
-
- CardServices(ReleaseConfiguration, link->handle);
- CardServices(ReleaseIO, link->handle, &link->io);
- CardServices(ReleaseIRQ, link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
-
+ link->state &= ~DEV_CONFIG;
}
-int dtl1_event(event_t event, int priority, event_callback_args_t *args) {
-
- dev_link_t *link = args->client_data;
- dtl1_info_t *info = link->priv;
-
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- dtl1_close(info);
- mod_timer(&link->release, jiffies + HZ/20);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- dtl1_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- CardServices(ReleaseConfiguration, link->handle);
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (DEV_OK(link))
- CardServices(RequestConfiguration, link->handle, &link->conf);
- break;
- }
-
-
- return 0;
-
+int dtl1_event(event_t event, int priority, event_callback_args_t *args)
+{
+ dev_link_t *link = args->client_data;
+ dtl1_info_t *info = link->priv;
+
+ switch (event) {
+ case CS_EVENT_CARD_REMOVAL:
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG) {
+ dtl1_close(info);
+ mod_timer(&link->release, jiffies + HZ / 20);
+ }
+ break;
+ case CS_EVENT_CARD_INSERTION:
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ dtl1_config(link);
+ break;
+ case CS_EVENT_PM_SUSPEND:
+ link->state |= DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_RESET_PHYSICAL:
+ if (link->state & DEV_CONFIG)
+ CardServices(ReleaseConfiguration, link->handle);
+ break;
+ case CS_EVENT_PM_RESUME:
+ link->state &= ~DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_CARD_RESET:
+ if (DEV_OK(link))
+ CardServices(RequestConfiguration, link->handle, &link->conf);
+ break;
+ }
+
+ return 0;
}
@@ -903,33 +826,29 @@ int dtl1_event(event_t event, int priority, event_callback_args_t *args) {
/* ======================== Module initialization ======================== */
-int __init init_dtl1_cs(void) {
-
- servinfo_t serv;
- int err;
+int __init init_dtl1_cs(void)
+{
+ servinfo_t serv;
+ int err;
+ CardServices(GetCardServicesInfo, &serv);
+ if (serv.Revision != CS_RELEASE_CODE) {
+ printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n");
+ return -1;
+ }
- CardServices(GetCardServicesInfo, &serv);
- if (serv.Revision != CS_RELEASE_CODE) {
- printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n");
- return -1;
- }
-
-
- err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach);
-
-
- return err;
+ err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach);
+ return err;
}
-void __exit exit_dtl1_cs(void) {
-
- unregister_pccard_driver(&dev_info);
- while (dev_list != NULL)
- dtl1_detach(dev_list);
+void __exit exit_dtl1_cs(void)
+{
+ unregister_pccard_driver(&dev_info);
+ while (dev_list != NULL)
+ dtl1_detach(dev_list);
}
diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c
index 9d2e97c47d36..bf0600ed7ede 100644
--- a/drivers/ide/ali14xx.c
+++ b/drivers/ide/ali14xx.c
@@ -107,13 +107,14 @@ static inline void out_reg(u8 data, u8 reg)
* Set PIO mode for the specified drive.
* This function computes timing parameters
* and sets controller registers accordingly.
+ * It assumes IRQ's are disabled or at least that no other process will
+ * attempt to access the IDE registers concurrently.
*/
static void ali14xx_tune_drive(struct ata_device *drive, u8 pio)
{
int drive_num;
int time1, time2;
u8 param1, param2, param3, param4;
- unsigned long flags;
struct ata_timing *t;
if (pio == 255)
@@ -140,15 +141,12 @@ static void ali14xx_tune_drive(struct ata_device *drive, u8 pio)
/* stuff timing parameters into controller registers */
drive_num = (drive->channel->index << 1) + drive->select.b.unit;
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
outb_p(reg_on, base_port);
out_reg(param1, reg_tab[drive_num].reg1);
out_reg(param2, reg_tab[drive_num].reg2);
out_reg(param3, reg_tab[drive_num].reg3);
out_reg(param4, reg_tab[drive_num].reg4);
outb_p(reg_off, base_port);
- restore_flags(flags); /* all CPUs */
}
/*
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
index 89ee79cfcda3..86540a2709fe 100644
--- a/drivers/ide/cs5530.c
+++ b/drivers/ide/cs5530.c
@@ -218,6 +218,7 @@ static unsigned int __init pci_init_cs5530(struct pci_dev *dev)
}
}
}
+
if (!master_0) {
printk("%s: unable to locate PCI MASTER function\n", dev->name);
return 0;
@@ -227,15 +228,13 @@ static unsigned int __init pci_init_cs5530(struct pci_dev *dev)
return 0;
}
- save_flags(flags);
- cli(); /* all CPUs (there should only be one CPU with this chipset) */
-
/*
* Enable BusMaster and MemoryWriteAndInvalidate for the cs5530:
* --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530
*/
- pci_read_config_word (cs5530_0, PCI_COMMAND, &pcicmd);
- pci_write_config_word(cs5530_0, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
+
+ pci_set_master(cs5530_0);
+ pci_set_mwi(cs5530_0);
/*
* Set PCI CacheLineSize to 16-bytes:
@@ -274,8 +273,6 @@ static unsigned int __init pci_init_cs5530(struct pci_dev *dev)
pci_write_config_byte(master_0, 0x42, 0x00);
pci_write_config_byte(master_0, 0x43, 0xc1);
- restore_flags(flags);
-
return 0;
}
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
index 8d947231d2ab..61583d9c8001 100644
--- a/drivers/ide/dtc2278.c
+++ b/drivers/ide/dtc2278.c
@@ -66,21 +66,18 @@ static void sub22 (char b, char c)
}
}
+/* Assumes IRQ's are disabled or at least that no other process will
+ attempt to access the IDE registers concurrently. */
static void tune_dtc2278(struct ata_device *drive, u8 pio)
{
- unsigned long flags;
-
pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
if (pio >= 3) {
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
/*
* This enables PIO mode4 (3?) on the first interface
*/
sub22(1,0xc3);
sub22(0,0xa0);
- restore_flags(flags); /* all CPUs */
} else {
/* we don't know how to set it back again.. */
}
diff --git a/drivers/ide/hd.c b/drivers/ide/hd.c
index f5fb26632eb2..31de0290cd79 100644
--- a/drivers/ide/hd.c
+++ b/drivers/ide/hd.c
@@ -1,15 +1,11 @@
/*
- * linux/drivers/ide/hd.c
- *
* Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-/*
+ *
* This is the low-level hd interrupt support. It traverses the
* request-list, using interrupts to jump between functions. As
* all the functions are called within interrupts, we may not
* sleep. Special care is recommended.
- *
+ *
* modified by Drew Eckhardt to check nr of hd's from the CMOS.
*
* Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
@@ -26,10 +22,10 @@
* Bugfix: max_sectors must be <= 255 or the wheels tend to come
* off in a hurry once you queue things up - Paul G. 02/2001
*/
-
+
/* Uncomment the following if you want verbose error reports. */
/* #define VERBOSE_ERRORS */
-
+
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
@@ -37,7 +33,6 @@
#include <linux/fs.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/kernel.h>
-#include <linux/hdreg.h>
#include <linux/genhd.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -45,6 +40,7 @@
#include <linux/mc146818rtc.h> /* CMOS defines */
#include <linux/init.h>
#include <linux/blkpg.h>
+#include <linux/hdreg.h>
#define REALLY_SLOW_IO
#include <asm/system.h>
@@ -55,6 +51,15 @@
#define DEVICE_NR(device) (minor(device)>>6)
#include <linux/blk.h>
+/* ATA commands we use.
+ */
+#define WIN_SPECIFY 0x91 /* set drive geometry translation */
+#define WIN_RESTORE 0x10
+#define WIN_READ 0x20 /* 28-Bit */
+#define WIN_WRITE 0x30 /* 28-Bit */
+
+#define HD_IRQ 14 /* the standard disk interrupt */
+
#ifdef __arm__
#undef HD_IRQ
#endif
@@ -63,6 +68,45 @@
#define HD_IRQ IRQ_HARDDISK
#endif
+/* Hd controller regster ports */
+
+#define HD_DATA 0x1f0 /* _CTL when writing */
+#define HD_ERROR 0x1f1 /* see err-bits */
+#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
+#define HD_SECTOR 0x1f3 /* starting sector */
+#define HD_LCYL 0x1f4 /* starting cylinder */
+#define HD_HCYL 0x1f5 /* high byte of starting cyl */
+#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
+#define HD_STATUS 0x1f7 /* see status-bits */
+#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */
+#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */
+#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
+
+#define HD_CMD 0x3f6 /* used for resets */
+#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
+
+/* Bits of HD_STATUS */
+#define ERR_STAT 0x01
+#define INDEX_STAT 0x02
+#define ECC_STAT 0x04 /* Corrected error */
+#define DRQ_STAT 0x08
+#define SEEK_STAT 0x10
+#define SERVICE_STAT SEEK_STAT
+#define WRERR_STAT 0x20
+#define READY_STAT 0x40
+#define BUSY_STAT 0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR 0x01 /* Bad address mark */
+#define TRK0_ERR 0x02 /* couldn't find track 0 */
+#define ABRT_ERR 0x04 /* Command aborted */
+#define MCR_ERR 0x08 /* media change request */
+#define ID_ERR 0x10 /* ID field not found */
+#define MC_ERR 0x20 /* media changed */
+#define ECC_ERR 0x40 /* Uncorrectable ECC error */
+#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
+#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
+
static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED;
static int revalidate_hddisk(kdev_t, int);
@@ -162,12 +206,9 @@ void __init hd_setup(char *str, int *ints)
static void dump_status (const char *msg, unsigned int stat)
{
- unsigned long flags;
char devc;
devc = !blk_queue_empty(QUEUE) ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?';
- save_flags (flags);
- sti();
#ifdef VERBOSE_ERRORS
printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
if (stat & BUSY_STAT) printk("Busy ");
@@ -207,8 +248,7 @@ static void dump_status (const char *msg, unsigned int stat)
hd_error = inb(HD_ERROR);
printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff);
}
-#endif /* verbose errors */
- restore_flags (flags);
+#endif
}
void check_status(void)
@@ -467,7 +507,7 @@ ok_to_write:
if (i > 0) {
SET_HANDLER(&write_intr);
outsw(HD_DATA,CURRENT->buffer,256);
- sti();
+ local_irq_enable();
} else {
#if (HD_DELAY > 0)
last_req = read_timer();
@@ -500,7 +540,7 @@ static void hd_times_out(unsigned long dummy)
return;
disable_irq(HD_IRQ);
- sti();
+ local_irq_enable();
reset = 1;
dev = DEVICE_NR(CURRENT->rq_dev);
printk("hd%c: timeout\n", dev+'a');
@@ -510,7 +550,7 @@ static void hd_times_out(unsigned long dummy)
#endif
end_request(CURRENT, 0);
}
- cli();
+ local_irq_disable();
hd_request();
enable_irq(HD_IRQ);
}
@@ -548,7 +588,7 @@ static void hd_request(void)
return;
repeat:
del_timer(&device_timer);
- sti();
+ local_irq_enable();
if (blk_queue_empty(QUEUE)) {
do_hd = NULL;
@@ -556,7 +596,7 @@ repeat:
}
if (reset) {
- cli();
+ local_irq_disable();
reset_hd();
return;
}
@@ -688,7 +728,7 @@ static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!handler)
handler = unexpected_hd_interrupt;
handler();
- sti();
+ local_irq_enable();
}
static struct block_device_operations hd_fops = {
diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c
index 34207cd5d911..4594368da382 100644
--- a/drivers/ide/ht6560b.c
+++ b/drivers/ide/ht6560b.c
@@ -249,12 +249,8 @@ static u8 ht_pio2timings(struct ata_device *drive, u8 pio)
*/
static void ht_set_prefetch(struct ata_device *drive, u8 state)
{
- unsigned long flags;
int t = HT_PREFETCH_MODE << 8;
- save_flags (flags); /* all CPUs */
- cli(); /* all CPUs */
-
/*
* Prefetch mode and unmask irq seems to conflict
*/
@@ -267,16 +263,16 @@ static void ht_set_prefetch(struct ata_device *drive, u8 state)
drive->channel->no_unmask = 0;
}
- restore_flags (flags); /* all CPUs */
-
#ifdef DEBUG
printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis"));
#endif
}
+/* Assumes IRQ's are disabled or at least that no other process will attempt to
+ * access the IDE registers concurrently.
+ */
static void tune_ht6560b(struct ata_device *drive, u8 pio)
{
- unsigned long flags;
u8 timing;
switch (pio) {
@@ -288,14 +284,9 @@ static void tune_ht6560b(struct ata_device *drive, u8 pio)
timing = ht_pio2timings(drive, pio);
- save_flags (flags); /* all CPUs */
- cli(); /* all CPUs */
-
drive->drive_data &= 0xff00;
drive->drive_data |= timing;
- restore_flags (flags); /* all CPUs */
-
#ifdef DEBUG
printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing);
#endif
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 1e4dbbebcec7..574895510c0e 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -305,8 +305,9 @@
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/cdrom.h>
-#include <linux/ide.h>
#include <linux/completion.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -2914,7 +2915,7 @@ int ide_cdrom_cleanup(struct ata_device *drive)
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *devinfo = &info->devinfo;
- if (ide_unregister_subdriver (drive))
+ if (ata_unregister_device(drive))
return 1;
if (info->buffer != NULL)
kfree(info->buffer);
@@ -2973,7 +2974,7 @@ static void ide_cdrom_attach(struct ata_device *drive)
printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
return;
}
- if (ide_register_subdriver (drive, &ide_cdrom_driver)) {
+ if (ata_register_device(drive, &ide_cdrom_driver)) {
printk(KERN_ERR "%s: Failed to register the driver with ide.c\n", drive->name);
kfree (info);
return;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 4070de3d2832..ccd271701974 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1279,7 +1279,7 @@ static int idedisk_cleanup(struct ata_device *drive)
printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
drive->name);
}
- ret = ide_unregister_subdriver(drive);
+ ret = ata_unregister_device(drive);
/* FIXME: This is killing the kernel with BUG 185 at asm/spinlocks.h
* horribly. Check whatever we did REGISTER the device properly
@@ -1471,8 +1471,8 @@ static void idedisk_attach(struct ata_device *drive)
if (req[0] != '\0' && strcmp(req, "ide-disk"))
return;
- if (ide_register_subdriver(drive, &idedisk_driver)) {
- printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
+ if (ata_register_device(drive, &idedisk_driver)) {
+ printk(KERN_ERR "%s: Failed to register the driver with ide.c\n", drive->name);
return;
}
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index e346d1d12b58..4651a5319935 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -94,9 +94,10 @@
#include <linux/genhd.h>
#include <linux/slab.h>
#include <linux/cdrom.h>
+#include <linux/buffer_head.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/atapi.h>
-#include <linux/buffer_head.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -1722,10 +1723,10 @@ static int idefloppy_cleanup(struct ata_device *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
- if (ide_unregister_subdriver (drive))
+ if (ata_unregister_device(drive))
return 1;
drive->driver_data = NULL;
- kfree (floppy);
+ kfree(floppy);
return 0;
}
@@ -1779,7 +1780,7 @@ static void idefloppy_attach(struct ata_device *drive)
drive->name);
return;
}
- if (ide_register_subdriver(drive, &idefloppy_driver)) {
+ if (ata_register_device(drive, &idefloppy_driver)) {
printk(KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);
kfree (floppy);
return;
diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c
index a9173ffad2dd..c3f821a4c17a 100644
--- a/drivers/ide/ide-pci.c
+++ b/drivers/ide/ide-pci.c
@@ -550,7 +550,8 @@ static void __init hpt374_device_order_fixup (struct pci_dev *dev, struct ata_pc
if (!dev2) {
return;
} else {
- byte irq = 0, irq2 = 0;
+ u8 irq = 0;
+ u8 irq2 = 0;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2);
if (irq != irq2) {
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 4dc463ba33fa..ab4ddba56fee 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -7,401 +7,18 @@
*
* It is hereby placed under the terms of the GNU general public license.
* (See linux/COPYING).
- */
-
-/*
- * BIG FAT FIXME: clean tape->spinlock locking --bzolnier
- */
-
-/*
- * IDE ATAPI streaming tape driver.
- *
- * This driver is a part of the Linux ide driver and works in co-operation
- * with linux/drivers/block/ide.c.
- *
- * The driver, in co-operation with ide.c, basically traverses the
- * request-list for the block device interface. The character device
- * interface, on the other hand, creates new requests, adds them
- * to the request-list of the block device, and waits for their completion.
- *
- * Pipelined operation mode is now supported on both reads and writes.
- *
- * The block device major and minor numbers are determined from the
- * tape's relative position in the ide interfaces, as explained in ide.c.
- *
- * The character device interface consists of the following devices:
- *
- * ht0 major 37, minor 0 first IDE tape, rewind on close.
- * ht1 major 37, minor 1 second IDE tape, rewind on close.
- * ...
- * nht0 major 37, minor 128 first IDE tape, no rewind on close.
- * nht1 major 37, minor 129 second IDE tape, no rewind on close.
- * ...
- *
- * Run linux/scripts/MAKEDEV.ide to create the above entries.
- *
- * The general magnetic tape commands compatible interface, as defined by
- * include/linux/mtio.h, is accessible through the character device.
- *
- * General ide driver configuration options, such as the interrupt-unmask
- * flag, can be configured by issuing an ioctl to the block device interface,
- * as any other ide device.
- *
- * Our own ide-tape ioctl's can be issued to either the block device or
- * the character device interface.
- *
- * Maximal throughput with minimal bus load will usually be achieved in the
- * following scenario:
- *
- * 1. ide-tape is operating in the pipelined operation mode.
- * 2. No buffering is performed by the user backup program.
- *
- * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
- *
- * Ver 0.1 Nov 1 95 Pre-working code :-)
- * Ver 0.2 Nov 23 95 A short backup (few megabytes) and restore procedure
- * was successful ! (Using tar cvf ... on the block
- * device interface).
- * A longer backup resulted in major swapping, bad
- * overall Linux performance and eventually failed as
- * we received non serial read-ahead requests from the
- * buffer cache.
- * Ver 0.3 Nov 28 95 Long backups are now possible, thanks to the
- * character device interface. Linux's responsiveness
- * and performance doesn't seem to be much affected
- * from the background backup procedure.
- * Some general mtio.h magnetic tape operations are
- * now supported by our character device. As a result,
- * popular tape utilities are starting to work with
- * ide tapes :-)
- * The following configurations were tested:
- * 1. An IDE ATAPI TAPE shares the same interface
- * and irq with an IDE ATAPI CDROM.
- * 2. An IDE ATAPI TAPE shares the same interface
- * and irq with a normal IDE disk.
- * Both configurations seemed to work just fine !
- * However, to be on the safe side, it is meanwhile
- * recommended to give the IDE TAPE its own interface
- * and irq.
- * The one thing which needs to be done here is to
- * add a "request postpone" feature to ide.c,
- * so that we won't have to wait for the tape to finish
- * performing a long media access (DSC) request (such
- * as a rewind) before we can access the other device
- * on the same interface. This effect doesn't disturb
- * normal operation most of the time because read/write
- * requests are relatively fast, and once we are
- * performing one tape r/w request, a lot of requests
- * from the other device can be queued and ide.c will
- * service all of them after this single tape request.
- * Ver 1.0 Dec 11 95 Integrated into Linux 1.3.46 development tree.
- * On each read / write request, we now ask the drive
- * if we can transfer a constant number of bytes
- * (a parameter of the drive) only to its buffers,
- * without causing actual media access. If we can't,
- * we just wait until we can by polling the DSC bit.
- * This ensures that while we are not transferring
- * more bytes than the constant referred to above, the
- * interrupt latency will not become too high and
- * we won't cause an interrupt timeout, as happened
- * occasionally in the previous version.
- * While polling for DSC, the current request is
- * postponed and ide.c is free to handle requests from
- * the other device. This is handled transparently to
- * ide.c. The hwgroup locking method which was used
- * in the previous version was removed.
- * Use of new general features which are provided by
- * ide.c for use with atapi devices.
- * (Programming done by Mark Lord)
- * Few potential bug fixes (Again, suggested by Mark)
- * Single character device data transfers are now
- * not limited in size, as they were before.
- * We are asking the tape about its recommended
- * transfer unit and send a larger data transfer
- * as several transfers of the above size.
- * For best results, use an integral number of this
- * basic unit (which is shown during driver
- * initialization). I will soon add an ioctl to get
- * this important parameter.
- * Our data transfer buffer is allocated on startup,
- * rather than before each data transfer. This should
- * ensure that we will indeed have a data buffer.
- * Ver 1.1 Dec 14 95 Fixed random problems which occurred when the tape
- * shared an interface with another device.
- * (poll_for_dsc was a complete mess).
- * Removed some old (non-active) code which had
- * to do with supporting buffer cache originated
- * requests.
- * The block device interface can now be opened, so
- * that general ide driver features like the unmask
- * interrupts flag can be selected with an ioctl.
- * This is the only use of the block device interface.
- * New fast pipelined operation mode (currently only on
- * writes). When using the pipelined mode, the
- * throughput can potentially reach the maximum
- * tape supported throughput, regardless of the
- * user backup program. On my tape drive, it sometimes
- * boosted performance by a factor of 2. Pipelined
- * mode is enabled by default, but since it has a few
- * downfalls as well, you may want to disable it.
- * A short explanation of the pipelined operation mode
- * is available below.
- * Ver 1.2 Jan 1 96 Eliminated pipelined mode race condition.
- * Added pipeline read mode. As a result, restores
- * are now as fast as backups.
- * Optimized shared interface behavior. The new behavior
- * typically results in better IDE bus efficiency and
- * higher tape throughput.
- * Pre-calculation of the expected read/write request
- * service time, based on the tape's parameters. In
- * the pipelined operation mode, this allows us to
- * adjust our polling frequency to a much lower value,
- * and thus to dramatically reduce our load on Linux,
- * without any decrease in performance.
- * Implemented additional mtio.h operations.
- * The recommended user block size is returned by
- * the MTIOCGET ioctl.
- * Additional minor changes.
- * Ver 1.3 Feb 9 96 Fixed pipelined read mode bug which prevented the
- * use of some block sizes during a restore procedure.
- * The character device interface will now present a
- * continuous view of the media - any mix of block sizes
- * during a backup/restore procedure is supported. The
- * driver will buffer the requests internally and
- * convert them to the tape's recommended transfer
- * unit, making performance almost independent of the
- * chosen user block size.
- * Some improvements in error recovery.
- * By cooperating with ide-dma.c, bus mastering DMA can
- * now sometimes be used with IDE tape drives as well.
- * Bus mastering DMA has the potential to dramatically
- * reduce the CPU's overhead when accessing the device,
- * and can be enabled by using hdparm -d1 on the tape's
- * block device interface. For more info, read the
- * comments in ide-dma.c.
- * Ver 1.4 Mar 13 96 Fixed serialize support.
- * Ver 1.5 Apr 12 96 Fixed shared interface operation, broken in 1.3.85.
- * Fixed pipelined read mode inefficiency.
- * Fixed nasty null dereferencing bug.
- * Ver 1.6 Aug 16 96 Fixed FPU usage in the driver.
- * Fixed end of media bug.
- * Ver 1.7 Sep 10 96 Minor changes for the CONNER CTT8000-A model.
- * Ver 1.8 Sep 26 96 Attempt to find a better balance between good
- * interactive response and high system throughput.
- * Ver 1.9 Nov 5 96 Automatically cross encountered filemarks rather
- * than requiring an explicit FSF command.
- * Abort pending requests at end of media.
- * MTTELL was sometimes returning incorrect results.
- * Return the real block size in the MTIOCGET ioctl.
- * Some error recovery bug fixes.
- * Ver 1.10 Nov 5 96 Major reorganization.
- * Reduced CPU overhead a bit by eliminating internal
- * bounce buffers.
- * Added module support.
- * Added multiple tape drives support.
- * Added partition support.
- * Rewrote DSC handling.
- * Some portability fixes.
- * Removed ide-tape.h.
- * Additional minor changes.
- * Ver 1.11 Dec 2 96 Bug fix in previous DSC timeout handling.
- * Use ide_stall_queue() for DSC overlap.
- * Use the maximum speed rather than the current speed
- * to compute the request service time.
- * Ver 1.12 Dec 7 97 Fix random memory overwriting and/or last block data
- * corruption, which could occur if the total number
- * of bytes written to the tape was not an integral
- * number of tape blocks.
- * Add support for INTERRUPT DRQ devices.
- * Ver 1.13 Jan 2 98 Add "speed == 0" work-around for HP COLORADO 5GB
- * Ver 1.14 Dec 30 98 Partial fixes for the Sony/AIWA tape drives.
- * Replace cli()/sti() with hwgroup spinlocks.
- * Ver 1.15 Mar 25 99 Fix SMP race condition by replacing hwgroup
- * spinlock with private per-tape spinlock.
- * Ver 1.16 Sep 1 99 Add OnStream tape support.
- * Abort read pipeline on EOD.
- * Wait for the tape to become ready in case it returns
- * "in the process of becoming ready" on open().
- * Fix zero padding of the last written block in
- * case the tape block size is larger than PAGE_SIZE.
- * Decrease the default disconnection time to tn.
- * Ver 1.16e Oct 3 99 Minor fixes.
- * Ver 1.16e1 Oct 13 99 Patches by Arnold Niessen,
- * niessen@iae.nl / arnold.niessen@philips.com
- * GO-1) Undefined code in idetape_read_position
- * according to Gadi's email
- * AJN-1) Minor fix asc == 11 should be asc == 0x11
- * in idetape_issue_packet_command (did effect
- * debugging output only)
- * AJN-2) Added more debugging output, and
- * added ide-tape: where missing. I would also
- * like to add tape->name where possible
- * AJN-3) Added different debug_level's
- * via /proc/ide/hdc/settings
- * "debug_level" determines amount of debugging output;
- * can be changed using /proc/ide/hdx/settings
- * 0 : almost no debugging output
- * 1 : 0+output errors only
- * 2 : 1+output all sensekey/asc
- * 3 : 2+follow all chrdev related procedures
- * 4 : 3+follow all procedures
- * 5 : 4+include pc_stack rq_stack info
- * 6 : 5+USE_COUNT updates
- * AJN-4) Fixed timeout for retension in idetape_queue_pc_tail
- * from 5 to 10 minutes
- * AJN-5) Changed maximum number of blocks to skip when
- * reading tapes with multiple consecutive write
- * errors from 100 to 1000 in idetape_get_logical_blk
- * Proposed changes to code:
- * 1) output "logical_blk_num" via /proc
- * 2) output "current_operation" via /proc
- * 3) Either solve or document the fact that `mt rewind' is
- * required after reading from /dev/nhtx to be
- * able to rmmod the idetape module;
- * Also, sometimes an application finishes but the
- * device remains `busy' for some time. Same cause ?
- * Proposed changes to release-notes:
- * 4) write a simple `quickstart' section in the
- * release notes; I volunteer if you don't want to
- * 5) include a pointer to video4linux in the doc
- * to stimulate video applications
- * 6) release notes lines 331 and 362: explain what happens
- * if the application data rate is higher than 1100 KB/s;
- * similar approach to lower-than-500 kB/s ?
- * 7) 6.6 Comparison; wouldn't it be better to allow different
- * strategies for read and write ?
- * Wouldn't it be better to control the tape buffer
- * contents instead of the bandwidth ?
- * 8) line 536: replace will by would (if I understand
- * this section correctly, a hypothetical and unwanted situation
- * is being described)
- * Ver 1.16f Dec 15 99 Change place of the secondary OnStream header frames.
- * Ver 1.17 Nov 2000 / Jan 2001 Marcel Mol, marcel@mesa.nl
- * - Add idetape_onstream_mode_sense_tape_parameter_page
- * function to get tape capacity in frames: tape->capacity.
- * - Add support for DI-50 drives( or any DI- drive).
- * - 'workaround' for read error/blank block arround block 3000.
- * - Implement Early warning for end of media for Onstream.
- * - Cosmetic code changes for readability.
- * - Idetape_position_tape should not use SKIP bit during
- * Onstream read recovery.
- * - Add capacity, logical_blk_num and first/last_frame_position
- * to /proc/ide/hd?/settings.
- * - Module use count was gone in the Linux 2.4 driver.
- * Ver 1.17a Apr 2001 Willem Riede osst@riede.org
- * - Get drive's actual block size from mode sense block descriptor
- * - Limit size of pipeline
- *
- * Here are some words from the first releases of hd.c, which are quoted
- * in ide.c and apply here as well:
- *
- * | Special care is recommended. Have Fun!
- *
- */
-
-/*
- * An overview of the pipelined operation mode.
- *
- * In the pipelined write mode, we will usually just add requests to our
- * pipeline and return immediately, before we even start to service them. The
- * user program will then have enough time to prepare the next request while
- * we are still busy servicing previous requests. In the pipelined read mode,
- * the situation is similar - we add read-ahead requests into the pipeline,
- * before the user even requested them.
- *
- * The pipeline can be viewed as a "safety net" which will be activated when
- * the system load is high and prevents the user backup program from keeping up
- * with the current tape speed. At this point, the pipeline will get
- * shorter and shorter but the tape will still be streaming at the same speed.
- * Assuming we have enough pipeline stages, the system load will hopefully
- * decrease before the pipeline is completely empty, and the backup program
- * will be able to "catch up" and refill the pipeline again.
- *
- * When using the pipelined mode, it would be best to disable any type of
- * buffering done by the user program, as ide-tape already provides all the
- * benefits in the kernel, where it can be done in a more efficient way.
- * As we will usually not block the user program on a request, the most
- * efficient user code will then be a simple read-write-read-... cycle.
- * Any additional logic will usually just slow down the backup process.
- *
- * Using the pipelined mode, I get a constant over 400 KBps throughput,
- * which seems to be the maximum throughput supported by my tape.
- *
- * However, there are some downfalls:
- *
- * 1. We use memory (for data buffers) in proportional to the number
- * of pipeline stages (each stage is about 26 KB with my tape).
- * 2. In the pipelined write mode, we cheat and postpone error codes
- * to the user task. In read mode, the actual tape position
- * will be a bit further than the last requested block.
- *
- * Concerning (1):
- *
- * 1. We allocate stages dynamically only when we need them. When
- * we don't need them, we don't consume additional memory. In
- * case we can't allocate stages, we just manage without them
- * (at the expense of decreased throughput) so when Linux is
- * tight in memory, we will not pose additional difficulties.
- *
- * 2. The maximum number of stages (which is, in fact, the maximum
- * amount of memory) which we allocate is limited by the compile
- * time parameter IDETAPE_MAX_PIPELINE_STAGES.
- *
- * 3. The maximum number of stages is a controlled parameter - We
- * don't start from the user defined maximum number of stages
- * but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we
- * will not even allocate this amount of stages if the user
- * program can't handle the speed). We then implement a feedback
- * loop which checks if the pipeline is empty, and if it is, we
- * increase the maximum number of stages as necessary until we
- * reach the optimum value which just manages to keep the tape
- * busy with minimum allocated memory or until we reach
- * IDETAPE_MAX_PIPELINE_STAGES.
- *
- * Concerning (2):
- *
- * In pipelined write mode, ide-tape can not return accurate error codes
- * to the user program since we usually just add the request to the
- * pipeline without waiting for it to be serviced. In case an error
- * occurs, I will report it on the next user request.
*
- * In the pipelined read mode, subsequent read requests or forward
- * filemark spacing will perform correctly, as we preserve all blocks
- * and filemarks which we encountered during our excess read-ahead.
- *
- * For accurate tape positioning and error reporting, disabling
- * pipelined mode might be the best option.
+ * Contributors:
*
- * You can enable/disable/tune the pipelined operation mode by adjusting
- * the compile time parameters below.
+ * Oct 1999 Arnold Niessen, <niessen@iae.nl>, <arnold.niessen@philips.com>
+ * Nov 2000, Jan 2001 Marcel Mol, <marcel@mesa.nl>
+ * Apr 2001 Willem Riede, <osst@riede.org>
*/
/*
- * Possible improvements.
- *
- * 1. Support for the ATAPI overlap protocol.
- *
- * In order to maximize bus throughput, we currently use the DSC
- * overlap method which enables ide.c to service requests from the
- * other device while the tape is busy executing a command. The
- * DSC overlap method involves polling the tape's status register
- * for the DSC bit, and servicing the other device while the tape
- * isn't ready.
- *
- * In the current QIC development standard (December 1995),
- * it is recommended that new tape drives will *in addition*
- * implement the ATAPI overlap protocol, which is used for the
- * same purpose - efficient use of the IDE bus, but is interrupt
- * driven and thus has much less CPU overhead.
- *
- * ATAPI overlap is likely to be supported in most new ATAPI
- * devices, including new ATAPI cdroms, and thus provides us
- * a method by which we can achieve higher throughput when
- * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
+ * FIXME: clean tape->spinlock locking --bzolnier
*/
-#define IDETAPE_VERSION "1.17a"
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -419,9 +36,10 @@
#include <linux/pci.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
+#include <linux/buffer_head.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/atapi.h>
-#include <linux/buffer_head.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -445,6 +63,7 @@
#define OS_DATA_STARTFRAME1 20
#define OS_DATA_ENDFRAME1 2980
+
/*
* partition
*/
@@ -1249,7 +868,7 @@ char *idetape_sense_key_verbose(u8 idetape_sense_key)
}
}
-char *idetape_command_key_verbose (byte idetape_command_key)
+char *idetape_command_key_verbose(u8 idetape_command_key)
{
switch (idetape_command_key) {
case IDETAPE_TEST_UNIT_READY_CMD: return("TEST_UNIT_READY_CMD");
@@ -1439,7 +1058,7 @@ static void idetape_analyze_error(struct ata_device *drive, atapi_request_sense_
# if IDETAPE_DEBUG_LOG_VERBOSE
if (tape->debug_level >= 1)
printk (KERN_INFO "ide-tape: pc = %s, sense key = %x, asc = %x, ascq = %x\n",
- idetape_command_key_verbose((byte) pc->c[0]),
+ idetape_command_key_verbose(pc->c[0]),
result->sense_key,
result->asc,
result->ascq);
@@ -2166,7 +1785,7 @@ static void idetape_pc_callback(struct ata_device *drive, struct request *rq)
/*
* A mode sense command is used to "sense" tape parameters.
*/
-static void idetape_create_mode_sense_cmd(struct atapi_packet_command *pc, byte page_code)
+static void idetape_create_mode_sense_cmd(struct atapi_packet_command *pc, u8 page_code)
{
atapi_init_pc(pc);
pc->c[0] = IDETAPE_MODE_SENSE_CMD;
@@ -3225,7 +2844,7 @@ static int __idetape_discard_read_pipeline(struct ata_device *drive)
* of the request queue and wait for their completion.
*
*/
-static int idetape_position_tape(struct ata_device *drive, unsigned int block, byte partition, int skip)
+static int idetape_position_tape(struct ata_device *drive, unsigned int block, u8 partition, int skip)
{
idetape_tape_t *tape = drive->driver_data;
int retval;
@@ -3981,7 +3600,7 @@ static int idetape_add_chrdev_read_request(struct ata_device *drive,int blocks)
printk (KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n");
bytes_read=blocks*tape->tape_block_size;
}
-#endif /* IDETAPE_DEBUG_BUGS */
+#endif
return (bytes_read);
}
@@ -5892,18 +5511,17 @@ static int idetape_cleanup(struct ata_device *drive)
int minor = tape->minor;
unsigned long flags;
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave (&tape->spinlock, flags); /* overkill? */
if (test_bit (IDETAPE_BUSY, &tape->flags) || tape->first_stage != NULL || tape->merge_stage_size || drive->usage) {
- restore_flags(flags); /* all CPUs (overkill?) */
+ spin_unlock_irqrestore(&tape->spinlock, flags);
return 1;
}
idetape_chrdevs[minor].drive = NULL;
- restore_flags (flags); /* all CPUs (overkill?) */
+ spin_unlock_irqrestore(&tape->spinlock, flags);
MOD_DEC_USE_COUNT;
- ide_unregister_subdriver (drive);
+ ata_unregister_device(drive);
drive->driver_data = NULL;
devfs_unregister (tape->de_r);
devfs_unregister (tape->de_n);
@@ -5992,11 +5610,11 @@ static void idetape_attach(struct ata_device *drive)
}
tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL);
if (!tape) {
- printk (KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
+ printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
return;
}
- if (ide_register_subdriver (drive, &idetape_driver)) {
- printk (KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name);
+ if (ata_register_device(drive, &idetape_driver)) {
+ printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name);
kfree (tape);
return;
}
diff --git a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c
index d1b5f6f8d4ad..5ab0adcdcac6 100644
--- a/drivers/ide/ioctl.c
+++ b/drivers/ide/ioctl.c
@@ -33,6 +33,15 @@
#include "ioctl.h"
+
+/* BIG GEOMETRY - dying, used only by HDIO_GETGEO_BIG_RAW */
+struct hd_big_geometry {
+ u8 heads;
+ u8 sectors;
+ u32 cylinders;
+ unsigned long start;
+};
+
/*
* Implement generic ioctls invoked from userspace to imlpement specific
* functionality.
diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c
index 838718764c4f..cc38ee5d8843 100644
--- a/drivers/ide/it8172.c
+++ b/drivers/ide/it8172.c
@@ -89,10 +89,7 @@ static void it8172_tune_drive (struct ata_device *drive, u8 pio)
drive_enables |= 0x0006;
}
- save_flags(flags);
- cli();
pci_write_config_word(dev, master_port, master_data);
- restore_flags(flags);
}
#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING)
diff --git a/drivers/ide/main.c b/drivers/ide/main.c
index 50bc8732e38b..5649e68fb97e 100644
--- a/drivers/ide/main.c
+++ b/drivers/ide/main.c
@@ -191,7 +191,11 @@ static void init_hwif_data(struct ata_channel *ch, unsigned int index)
ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET];
#ifdef CONFIG_BLK_DEV_HD
- if (ch->io_ports[IDE_DATA_OFFSET] == HD_DATA)
+
+ /* Ignore disks for which handling by the legacy driver was requested
+ * by the used.
+ */
+ if (ch->io_ports[IDE_DATA_OFFSET] == 0x1f0)
ch->noprobe = 1; /* may be overridden by ide_setup() */
#endif
@@ -361,7 +365,7 @@ void ide_unregister(struct ata_channel *ch)
if (ata_ops(drive)->cleanup(drive))
goto abort;
} else
- ide_unregister_subdriver(drive);
+ ata_unregister_device(drive);
}
}
ch->present = 0;
@@ -701,79 +705,46 @@ static void __init init_global_data(void)
/*
* This gets called VERY EARLY during initialization, to handle kernel "command
- * line" strings beginning with "hdx=" or "ide".It gets called even before the
- * actual module gets initialized.
+ * line" strings beginning with "hdx=". It gets called even before the actual
+ * module gets initialized.
*
* Please look at Documentation/ide.txt to see the complete list of supported
* options.
*/
-int __init ide_setup(char *s)
+static int __init ata_hd_setup(char *s)
{
- int i, vals[4];
- struct ata_channel *ch;
+ int vals[4];
+ struct ata_channel *ch; /* FIXME: Channel parms should not be accessed in ata_hd_setup */
struct ata_device *drive;
unsigned int hw, unit;
const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
- const char max_ch = '0' + (MAX_HWIFS - 1);
- if (!strncmp(s, "hd=", 3)) /* hd= is for hd.c driver and not us */
+ if (s[0] == '=') /* hd= is for hd.c driver and not us */
return 0;
- if (strncmp(s,"ide",3) &&
- strncmp(s,"hd",2)) /* hdx= & hdxlun= */
- return 0;
-
- printk(KERN_INFO "ide_setup: %s", s);
+ printk(KERN_INFO "hd%s", s);
init_global_data();
-#ifdef CONFIG_BLK_DEV_IDEDOUBLER
- if (!strcmp(s, "ide=doubler")) {
- extern int ide_doubler;
-
- printk(KERN_INFO" : Enabled support for IDE doublers\n");
- ide_doubler = 1;
-
- return 1;
- }
-#endif
-
- if (!strcmp(s, "ide=nodma")) {
- printk(KERN_INFO "ATA: Prevented DMA\n");
- noautodma = 1;
-
- return 1;
- }
-
-#ifdef CONFIG_PCI
- if (!strcmp(s, "ide=reverse")) {
- ide_scan_direction = 1;
- printk(" : Enabled support for IDE inverse scan order.\n");
-
- return 1;
- }
-#endif
-
- /*
- * Look for drive options: "hdx="
- */
- if (!strncmp(s, "hd", 2) && s[2] >= 'a' && s[2] <= max_drive) {
- const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom",
+ if (s[0] >= 'a' && s[0] <= max_drive) {
+ static const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom",
"serialize", "autotune", "noautotune",
"slow", "flash", "remap", "noremap", "scsi", NULL};
- unit = s[2] - 'a';
+ unit = s[0] - 'a';
hw = unit / MAX_DRIVES;
unit = unit % MAX_DRIVES;
ch = &ide_hwifs[hw];
drive = &ch->drives[unit];
- if (!strncmp(s+3, "=ide-", 5)) {
- strncpy(drive->driver_req, s + 4, 9);
+
+ /* Look for hdx=ide-* */
+ if (!strncmp(s+1, "=ide-", 5)) {
+ strncpy(drive->driver_req, s+2, 9);
goto done;
}
/*
* Look for last lun option: "hdxlun="
*/
- if (!strncmp(s+3, "lun=", 4)) {
- if (*get_options(s+7, 2, vals) || vals[0]!=1)
+ if (!strncmp(s+1, "lun=", 4)) {
+ if (*get_options(s+5, 2, vals) || vals[0]!=1)
goto bad_option;
if (vals[1] >= 0 && vals[1] <= 7) {
drive->last_lun = vals[1];
@@ -782,7 +753,7 @@ int __init ide_setup(char *s)
printk(" -- BAD LAST LUN! Expected value from 0 to 7");
goto done;
}
- switch (match_parm(s+3, hd_words, vals, 3)) {
+ switch (match_parm(s+1, hd_words, vals, 3)) {
case -1: /* "none" */
drive->nobios = 1; /* drop into "noprobe" */
case -2: /* "noprobe" */
@@ -790,16 +761,16 @@ int __init ide_setup(char *s)
goto done;
case -3: /* "nowerr" */
drive->bad_wstat = BAD_R_STAT;
- ch->noprobe = 0;
+ ch->noprobe = 0; /* FIXME: Channel parm */
goto done;
case -4: /* "cdrom" */
drive->present = 1;
drive->type = ATA_ROM;
- ch->noprobe = 0;
+ ch->noprobe = 0; /* FIXME: Channel parm */
goto done;
case -5: /* "serialize" */
printk(" -- USE \"ide%d=serialize\" INSTEAD", hw);
- goto do_serialize;
+ goto bad_option;
case -6: /* "autotune" */
drive->autotune = 1;
goto done;
@@ -807,7 +778,7 @@ int __init ide_setup(char *s)
drive->autotune = 2;
goto done;
case -8: /* "slow" */
- ch->slow = 1;
+ ch->slow = 1; /* FIXME: Channel parm */
goto done;
case -9: /* "flash" */
drive->ata_flash = 1;
@@ -840,11 +811,63 @@ int __init ide_setup(char *s)
}
}
+bad_option:
+ printk(" -- BAD OPTION\n");
+ return 1;
+
+done:
+ printk("\n");
+
+ return 1;
+}
+
+/*
+ * This gets called VERY EARLY during initialization, to handle kernel "command
+ * line" strings beginning with "ide". It gets called even before the actual
+ * module gets initialized.
+ *
+ * Please look at Documentation/ide.txt to see the complete list of supported
+ * options.
+ */
+int __init ide_setup(char *s)
+{
+ int i, vals[4];
+ struct ata_channel *ch;
+ unsigned int hw;
+ const char max_ch = '0' + (MAX_HWIFS - 1);
+
+ printk(KERN_INFO "ide_setup: ide%s", s);
+ init_global_data();
+
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+ if (!strcmp(s, "=doubler")) {
+ extern int ide_doubler;
+
+ printk(KERN_INFO" : Enabled support for IDE doublers\n");
+ ide_doubler = 1;
+ return 1;
+ }
+#endif
+
+ if (!strcmp(s, "=nodma")) {
+ printk(KERN_INFO "ATA: Prevented DMA\n");
+ noautodma = 1;
+ return 1;
+ }
+
+#ifdef CONFIG_PCI
+ if (!strcmp(s, "=reverse")) {
+ ide_scan_direction = 1;
+ printk(" : Enabled support for IDE inverse scan order.\n");
+ return 1;
+ }
+#endif
+
/*
* Look for bus speed option: "idebus="
*/
- if (!strncmp(s, "idebus=", 7)) {
- if (*get_options(s+7, 2, vals) || vals[0] != 1)
+ if (!strncmp(s, "bus=", 4)) {
+ if (*get_options(s+4, 2, vals) || vals[0] != 1)
goto bad_option;
idebus_parameter = vals[1];
goto done;
@@ -853,7 +876,7 @@ int __init ide_setup(char *s)
/*
* Look for interface options: "idex="
*/
- if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_ch) {
+ if (s[0] >= '0' && s[0] <= max_ch) {
/*
* Be VERY CAREFUL changing this: note hardcoded indexes below
*/
@@ -861,11 +884,11 @@ int __init ide_setup(char *s)
"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", NULL };
const char *ide_words[] = {
"qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
- hw = s[3] - '0';
+ hw = s[0] - '0';
ch = &ide_hwifs[hw];
- switch (match_parm(s+4, ide_options, vals, 1)) {
+ switch (match_parm(s+1, ide_options, vals, 1)) {
case -7: /* ata66 */
#ifdef CONFIG_PCI
ch->udma_four = 1;
@@ -889,7 +912,6 @@ int __init ide_setup(char *s)
ch->drives[1].autotune = 1;
goto done;
case -2: /* "serialize" */
- do_serialize:
{
struct ata_channel *mate;
@@ -904,7 +926,10 @@ int __init ide_setup(char *s)
goto done;
}
- i = match_parm(&s[4], ide_words, vals, 3);
+ /*
+ * Check for specific chipset name
+ */
+ i = match_parm(s+1, ide_words, vals, 3);
/*
* Cryptic check to ensure chipset not already set for a channel:
@@ -913,7 +938,7 @@ int __init ide_setup(char *s)
if (ide_hwifs[hw].chipset != ide_unknown)
goto bad_option; /* chipset already specified */
if (i != -7 && hw != 0)
- goto bad_channel; /* chipset drivers are for "ide0=" only */
+ goto bad_channel; /* chipset drivers are for "ide0=" only */
if (i != -7 && ide_hwifs[1].chipset != ide_unknown)
goto bad_option; /* chipset for 2nd port already specified */
printk("\n");
@@ -1012,10 +1037,7 @@ done:
/****************************************************************************/
-/*
- * This is in fact registering a device not a driver.
- */
-int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driver)
+int ata_register_device(struct ata_device *drive, struct ata_operations *driver)
{
unsigned long flags;
@@ -1027,12 +1049,9 @@ int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driv
return 1;
}
- /* FIXME: This will be pushed to the drivers! Thus allowing us to
- * save one parameter here and to separate this out.
- */
drive->driver = driver;
-
spin_unlock_irqrestore(&ide_lock, flags);
+
/* Default autotune or requested autotune */
if (drive->autotune != 2) {
struct ata_channel *ch = drive->channel;
@@ -1046,11 +1065,13 @@ int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driv
* PARANOIA!!!
*/
+ spin_lock_irqsave(ch->lock, flags);
udma_enable(drive, 0, 0);
ch->udma_setup(drive, ch->modes_map);
#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
udma_tcq_enable(drive, 1);
#endif
+ spin_unlock_irqrestore(ch->lock, flags);
}
/* Only CD-ROMs and tape drives support DSC overlap. But only
@@ -1078,13 +1099,8 @@ int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driv
*
* FIXME: Check whatever we maybe don't call it twice!.
*/
-int ide_unregister_subdriver(struct ata_device *drive)
+int ata_unregister_device(struct ata_device *drive)
{
-#if 0
- if (__MOD_IN_USE(ata_ops(drive)->owner))
- return 1;
-#endif
-
if (drive->usage || drive->busy || !ata_ops(drive))
return 1;
@@ -1156,8 +1172,8 @@ EXPORT_SYMBOL(ide_lock);
devfs_handle_t ide_devfs_handle;
-EXPORT_SYMBOL(ide_register_subdriver);
-EXPORT_SYMBOL(ide_unregister_subdriver);
+EXPORT_SYMBOL(ata_register_device);
+EXPORT_SYMBOL(ata_unregister_device);
EXPORT_SYMBOL(ata_revalidate);
EXPORT_SYMBOL(ide_register_hw);
EXPORT_SYMBOL(ide_unregister);
@@ -1432,8 +1448,14 @@ static int __init init_ata(void)
while ((options = next) != NULL) {
if ((next = strchr(options,' ')) != NULL)
*next++ = 0;
- if (!ide_setup(options))
- printk(KERN_ERR "Unknown option '%s'\n", options);
+ if (!strncmp(options,"hd",2)) {
+ if (!ata_hd_setup(options+2))
+ printk(KERN_ERR "Unknown option '%s'\n", options);
+ }
+ else if (!strncmp(options,"ide",3)) {
+ if (!ide_setup(options+3))
+ printk(KERN_ERR "Unknown option '%s'\n", options);
+ }
}
}
return ata_module_init();
@@ -1457,6 +1479,7 @@ module_exit(cleanup_ata);
#ifndef MODULE
/* command line option parser */
-__setup("", ide_setup);
+__setup("ide", ide_setup);
+__setup("hd", ata_hd_setup);
#endif
diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c
index c141def6663d..723695b953f3 100644
--- a/drivers/ide/opti621.c
+++ b/drivers/ide/opti621.c
@@ -244,13 +244,15 @@ static void compute_clocks(int pio, pio_clocks_t *clks)
}
-/* Main tune procedure, called from tuneproc. */
+/* Main tune procedure, called from tuneproc.
+ Assumes IRQ's are disabled or at least that no other process will
+ attempt to access the IDE registers concurrently.
+*/
static void opti621_tune_drive(struct ata_device *drive, u8 pio)
{
/* primary and secondary drives share some registers,
* so we have to program both drives
*/
- unsigned long flags;
u8 pio1, pio2;
pio_clocks_t first, second;
int ax, drdy;
@@ -281,9 +283,6 @@ static void opti621_tune_drive(struct ata_device *drive, u8 pio)
hwif->name, ax, second.data_time, second.recovery_time, drdy);
#endif
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
-
reg_base = hwif->io_ports[IDE_DATA_OFFSET];
outb(0xc0, reg_base+CNTRL_REG); /* allow Register-B */
outb(0xff, reg_base+5); /* hmm, setupvic.exe does this ;-) */
@@ -306,8 +305,6 @@ static void opti621_tune_drive(struct ata_device *drive, u8 pio)
write_reg(misc, MISC_REG); /* set address setup, DRDY timings, */
/* and read prefetch for both drives */
-
- restore_flags(flags); /* all CPUs */
}
/*
diff --git a/drivers/ide/probe.c b/drivers/ide/probe.c
index 3766b7531c78..f6adc59bb0b5 100644
--- a/drivers/ide/probe.c
+++ b/drivers/ide/probe.c
@@ -1082,7 +1082,12 @@ static void channel_init(struct ata_channel *ch)
}
}
#ifdef CONFIG_BLK_DEV_HD
- if (ch->irq == HD_IRQ && ch->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
+
+ /* The first "legacy" HD gets distinguished by the IRQ it is attached
+ * to and the IO port it takes.
+ */
+
+ if (ch->irq == 14 && ch->io_ports[IDE_DATA_OFFSET] != 0x1f0) {
printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", ch->name);
return;
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
index 633a75950d60..3ed266424233 100644
--- a/drivers/ide/qd65xx.c
+++ b/drivers/ide/qd65xx.c
@@ -1,8 +1,6 @@
/*
* Copyright (C) 1996-2001 Linus Torvalds & author (see below)
- */
-
-/*
+ *
* Version 0.03 Cleaned auto-tune, added probe
* Version 0.04 Added second channel tuning
* Version 0.05 Enhanced tuning ; added qd6500 support
@@ -81,36 +79,12 @@
* bit 5 : status, but of what ?
* bit 6 : always set 1 by dos driver
* bit 7 : set 1 for non-ATAPI devices on primary port
- * (maybe read-ahead and post-write buffer ?)
+ * (maybe read-ahead and post-write buffer ?)
*/
static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
-static void qd_write_reg(u8 content, unsigned int reg)
-{
- unsigned long flags;
-
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
- outb(content,reg);
- restore_flags(flags); /* all CPUs */
-}
-
-static u8 __init qd_read_reg(unsigned int reg)
-{
- unsigned long flags;
- u8 read;
-
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
- read = inb(reg);
- restore_flags(flags); /* all CPUs */
- return read;
-}
-
/*
- * qd_select:
- *
* This routine is invoked from ide.c to prepare for access to a given drive.
*/
@@ -120,12 +94,10 @@ static void qd_select(struct ata_device *drive)
(QD_TIMREG(drive) & 0x02);
if (timings[index] != QD_TIMING(drive))
- qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
+ outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
}
/*
- * qd6500_compute_timing
- *
* computes the timing value where
* lower nibble represents active time, in count of VLB clocks
* upper nibble represents recovery time, in count of VLB clocks
@@ -147,8 +119,6 @@ static u8 qd6500_compute_timing(struct ata_channel *hwif, int active_time, int r
}
/*
- * qd6580_compute_timing
- *
* idem for qd6580
*/
@@ -161,8 +131,6 @@ static u8 qd6580_compute_timing(int active_time, int recovery_time)
}
/*
- * qd_find_disk_type
- *
* tries to find timing from dos driver's table
*/
@@ -187,8 +155,6 @@ static int qd_find_disk_type(struct ata_device *drive,
}
/*
- * qd_timing_ok:
- *
* check whether timings don't conflict
*/
@@ -201,8 +167,6 @@ static int qd_timing_ok(struct ata_device drives[])
}
/*
- * qd_set_timing:
- *
* records the timing, and enables selectproc as needed
*/
@@ -221,10 +185,6 @@ static void qd_set_timing(struct ata_device *drive, u8 timing)
printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
}
-/*
- * qd6500_tune_drive
- */
-
static void qd6500_tune_drive(struct ata_device *drive, u8 pio)
{
int active_time = 175;
@@ -242,10 +202,6 @@ static void qd6500_tune_drive(struct ata_device *drive, u8 pio)
qd_set_timing(drive, qd6500_compute_timing(drive->channel, active_time, recovery_time));
}
-/*
- * qd6580_tune_drive
- */
-
static void qd6580_tune_drive(struct ata_device *drive, u8 pio)
{
struct ata_timing *t;
@@ -291,7 +247,7 @@ static void qd6580_tune_drive(struct ata_device *drive, u8 pio)
}
if (!drive->channel->unit && drive->type != ATA_DISK) {
- qd_write_reg(0x5f, QD_CONTROL_PORT);
+ outb(0x5f, QD_CONTROL_PORT);
printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n", drive->name, drive->channel->name);
}
@@ -299,8 +255,6 @@ static void qd6580_tune_drive(struct ata_device *drive, u8 pio)
}
/*
- * qd_testreg
- *
* tests if the given port is a register
*/
@@ -329,8 +283,6 @@ static int __init qd_testreg(int port)
}
/*
- * qd_setup:
- *
* called to setup an ata channel : adjusts attributes & links for tuning
*/
@@ -349,8 +301,6 @@ void __init qd_setup(int unit, int base, int config, unsigned int data0, unsigne
}
/*
- * qd_unsetup:
- *
* called to unsetup an ata channel : back to default values, unlinks tuning
*/
void __init qd_unsetup(int unit) {
@@ -368,13 +318,13 @@ void __init qd_unsetup(int unit) {
if (tuneproc == (void *) qd6500_tune_drive) {
// will do it for both
- qd_write_reg(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+ outb(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
} else if (tuneproc == (void *) qd6580_tune_drive) {
if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
- qd_write_reg(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
- qd_write_reg(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1]));
+ outb(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+ outb(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1]));
} else {
- qd_write_reg(unit?QD6580_DEF_DATA2:QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+ outb(unit ? QD6580_DEF_DATA2 : QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
}
} else {
printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n");
@@ -383,8 +333,6 @@ void __init qd_unsetup(int unit) {
}
/*
- * qd_probe:
- *
* looks at the specified baseport, and if qd found, registers & initialises it
* return 1 if another qd may be probed
*/
@@ -394,7 +342,7 @@ int __init qd_probe(int base)
u8 config;
int unit;
- config = qd_read_reg(QD_CONFIG_PORT);
+ config = inb(QD_CONFIG_PORT);
if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) return 1;
@@ -425,7 +373,7 @@ int __init qd_probe(int base)
/* qd6580 found */
- control = qd_read_reg(QD_CONTROL_PORT);
+ control = inb(QD_CONTROL_PORT);
printk(KERN_NOTICE "qd6580 at %#x\n", base);
printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", config, control, QD_ID3);
@@ -434,7 +382,7 @@ int __init qd_probe(int base)
/* secondary disabled */
printk(KERN_INFO "%s: qd6580: single IDE board\n", ide_hwifs[unit].name);
qd_setup(unit, base, config | (control << 8), QD6580_DEF_DATA, QD6580_DEF_DATA2, &qd6580_tune_drive);
- qd_write_reg(QD_DEF_CONTR, QD_CONTROL_PORT);
+ outb(QD_DEF_CONTR, QD_CONTROL_PORT);
return 1;
} else {
@@ -443,7 +391,7 @@ int __init qd_probe(int base)
qd_setup(ATA_PRIMARY, base, config | (control << 8), QD6580_DEF_DATA, QD6580_DEF_DATA, &qd6580_tune_drive);
qd_setup(ATA_SECONDARY, base, config | (control << 8), QD6580_DEF_DATA2, QD6580_DEF_DATA2, &qd6580_tune_drive);
- qd_write_reg(QD_DEF_CONTR, QD_CONTROL_PORT);
+ outb(QD_DEF_CONTR, QD_CONTROL_PORT);
return 0; /* no other qd65xx possible */
}
@@ -454,8 +402,6 @@ int __init qd_probe(int base)
#ifndef MODULE
/*
- * init_qd65xx:
- *
* called by ide.c when parsing command line
*/
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index f05c5f37b1ed..fac559f73abe 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -1,33 +1,12 @@
/*
* Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
- */
-/*
+ *
* Emulation of a SCSI host adapter for IDE ATAPI devices.
*
* With this driver, one can use the Linux SCSI drivers instead of the
* native IDE ATAPI drivers.
- *
- * Ver 0.1 Dec 3 96 Initial version.
- * Ver 0.2 Jan 26 97 Fixed bug in cleanup_module() and added emulation
- * of MODE_SENSE_6/MODE_SELECT_6 for cdroms. Thanks
- * to Janos Farkas for pointing this out.
- * Avoid using bitfields in structures for m68k.
- * Added Scatter/Gather and DMA support.
- * Ver 0.4 Dec 7 97 Add support for ATAPI PD/CD drives.
- * Use variable timeout for each command.
- * Ver 0.5 Jan 2 98 Fix previous PD/CD support.
- * Allow disabling of SCSI-6 to SCSI-10 transformation.
- * Ver 0.6 Jan 27 98 Allow disabling of SCSI command translation layer
- * for access through /dev/sg.
- * Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
- * Ver 0.7 Dec 04 98 Ignore commands where lun != 0 to avoid multiple
- * detection of devices with CONFIG_SCSI_MULTI_LUN
- * Ver 0.8 Feb 05 99 Optical media need translation too. Reverse 0.7.
- * Ver 0.9 Jul 04 99 Fix a bug in SG_SET_TRANSFORM.
*/
-#define IDESCSI_VERSION "0.9"
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
@@ -495,9 +474,8 @@ static void idescsi_release(struct inode *inode, struct file *filp, struct ata_d
static Scsi_Host_Template template;
static int idescsi_cleanup (struct ata_device *drive)
{
- if (ide_unregister_subdriver (drive)) {
+ if (ata_unregister_device(drive))
return 1;
- }
scsi_unregister_host(&template);
return 0;
@@ -762,7 +740,7 @@ static void idescsi_attach(struct ata_device *drive)
host = scsi_register(&template, sizeof(idescsi_scsi_t));
if (!host) {
- printk (KERN_ERR
+ printk(KERN_ERR
"ide-scsi: %s: Can't allocate a scsi host structure\n",
drive->name);
return;
@@ -771,8 +749,8 @@ static void idescsi_attach(struct ata_device *drive)
host->max_lun = drive->last_lun + 1;
host->max_id = 1;
- if (ide_register_subdriver(drive, &ata_ops)) {
- printk (KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name);
+ if (ata_register_device(drive, &ata_ops)) {
+ printk(KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name);
scsi_unregister(host);
return;
}
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index a5a2d59be9ca..c8d70991ae3a 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -40,43 +40,47 @@
static void pdump (void *, int);
#endif
+/* Bits of HD_STATUS */
+#define ERR_STAT 0x01
+#define DRQ_STAT 0x08
+
struct freecom_udata {
- __u8 buffer[64]; /* Common command block. */
+ u8 buffer[64]; /* Common command block. */
};
typedef struct freecom_udata *freecom_udata_t;
/* All of the outgoing packets are 64 bytes long. */
struct freecom_cb_wrap {
- __u8 Type; /* Command type. */
- __u8 Timeout; /* Timeout in seconds. */
- __u8 Atapi[12]; /* An ATAPI packet. */
- __u8 Filler[50]; /* Padding Data. */
+ u8 Type; /* Command type. */
+ u8 Timeout; /* Timeout in seconds. */
+ u8 Atapi[12]; /* An ATAPI packet. */
+ u8 Filler[50]; /* Padding Data. */
};
struct freecom_xfer_wrap {
- __u8 Type; /* Command type. */
- __u8 Timeout; /* Timeout in seconds. */
- __u32 Count; /* Number of bytes to transfer. */
- __u8 Pad[58];
+ u8 Type; /* Command type. */
+ u8 Timeout; /* Timeout in seconds. */
+ u32 Count; /* Number of bytes to transfer. */
+ u8 Pad[58];
} __attribute__ ((packed));
struct freecom_ide_out {
- __u8 Type; /* Type + IDE register. */
- __u8 Pad;
- __u16 Value; /* Value to write. */
- __u8 Pad2[60];
+ u8 Type; /* Type + IDE register. */
+ u8 Pad;
+ u16 Value; /* Value to write. */
+ u8 Pad2[60];
};
struct freecom_ide_in {
- __u8 Type; /* Type | IDE register. */
- __u8 Pad[63];
+ u8 Type; /* Type | IDE register. */
+ u8 Pad[63];
};
struct freecom_status {
- __u8 Status;
- __u8 Reason;
- __u16 Count;
- __u8 Pad[60];
+ u8 Status;
+ u8 Reason;
+ u16 Count;
+ u8 Pad[60];
};
/* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide
diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
index dcedacb849ea..5ed104e84e43 100644
--- a/include/linux/hdreg.h
+++ b/include/linux/hdreg.h
@@ -2,279 +2,18 @@
#define _LINUX_HDREG_H
/*
- * This file contains some defines for the AT-hd-controller.
- * Various sources.
- */
-
-#define HD_IRQ 14 /* the standard disk interrupt */
-
-/* ide.c has its own port definitions in "ide.h" */
-
-/* Hd controller regs. Ref: IBM AT Bios-listing */
-#define HD_DATA 0x1f0 /* _CTL when writing */
-#define HD_ERROR 0x1f1 /* see err-bits */
-#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
-#define HD_SECTOR 0x1f3 /* starting sector */
-#define HD_LCYL 0x1f4 /* starting cylinder */
-#define HD_HCYL 0x1f5 /* high byte of starting cyl */
-#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
-#define HD_STATUS 0x1f7 /* see status-bits */
-#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */
-#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */
-#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
-
-#define HD_CMD 0x3f6 /* used for resets */
-#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
-
-/* remainder is shared between hd.c, ide.c, ide-cd.c, and the hdparm utility */
-
-/* Bits of HD_STATUS */
-#define ERR_STAT 0x01
-#define INDEX_STAT 0x02
-#define ECC_STAT 0x04 /* Corrected error */
-#define DRQ_STAT 0x08
-#define SEEK_STAT 0x10
-#define SERVICE_STAT SEEK_STAT
-#define WRERR_STAT 0x20
-#define READY_STAT 0x40
-#define BUSY_STAT 0x80
-
-/* Bits for HD_ERROR */
-#define MARK_ERR 0x01 /* Bad address mark */
-#define TRK0_ERR 0x02 /* couldn't find track 0 */
-#define ABRT_ERR 0x04 /* Command aborted */
-#define MCR_ERR 0x08 /* media change request */
-#define ID_ERR 0x10 /* ID field not found */
-#define MC_ERR 0x20 /* media changed */
-#define ECC_ERR 0x40 /* Uncorrectable ECC error */
-#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
-#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
-
-/*
- * sector count bits
- */
-#define NSEC_CD 0x01
-#define NSEC_IO 0x02
-#define NSEC_REL 0x04
-
-/*
* Command Header sizes for IOCTL commands
*/
-
#define HDIO_DRIVE_CMD_HDR_SIZE (4 * sizeof(u8))
#define HDIO_DRIVE_HOB_HDR_SIZE (8 * sizeof(u8))
-#define IDE_DRIVE_TASK_INVALID -1
-#define IDE_DRIVE_TASK_NO_DATA 0
-#define IDE_DRIVE_TASK_SET_XFER 1
-
-#define IDE_DRIVE_TASK_IN 2
-
-#define IDE_DRIVE_TASK_OUT 3
-#define IDE_DRIVE_TASK_RAW_WRITE 4
-
-struct hd_drive_task_hdr {
- u8 feature;
- u8 sector_count;
- u8 sector_number;
- u8 low_cylinder;
- u8 high_cylinder;
- u8 device_head;
-} __attribute__((packed));
-
-/*
- * Define standard taskfile in/out register
- */
-#define IDE_TASKFILE_STD_OUT_FLAGS 0xFE
-#define IDE_TASKFILE_STD_IN_FLAGS 0xFE
-#define IDE_HOB_STD_OUT_FLAGS 0xC0
-#define IDE_HOB_STD_IN_FLAGS 0xC0
-
-#define TASKFILE_INVALID 0x7fff
-#define TASKFILE_48 0x8000
-
-#define TASKFILE_NO_DATA 0x0000
-
-#define TASKFILE_IN 0x0001
-#define TASKFILE_MULTI_IN 0x0002
-
-#define TASKFILE_OUT 0x0004
-#define TASKFILE_MULTI_OUT 0x0008
-#define TASKFILE_IN_OUT 0x0010
-
-#define TASKFILE_IN_DMA 0x0020
-#define TASKFILE_OUT_DMA 0x0040
-#define TASKFILE_IN_DMAQ 0x0080
-#define TASKFILE_OUT_DMAQ 0x0100
-
-#define TASKFILE_P_IN 0x0200
-#define TASKFILE_P_OUT 0x0400
-#define TASKFILE_P_IN_DMA 0x0800
-#define TASKFILE_P_OUT_DMA 0x1000
-#define TASKFILE_P_IN_DMAQ 0x2000
-#define TASKFILE_P_OUT_DMAQ 0x4000
-
-/* ATA/ATAPI Commands pre T13 Spec */
-#define WIN_NOP 0x00
-#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */
-#define WIN_SRST 0x08 /* ATAPI soft reset command */
-#define WIN_DEVICE_RESET 0x08
-#define WIN_RESTORE 0x10
-#define WIN_READ 0x20 /* 28-Bit */
-#define WIN_READ_EXT 0x24 /* 48-Bit */
-#define WIN_READDMA_EXT 0x25 /* 48-Bit */
-#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */
-#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */
-#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */
-#define WIN_WRITE 0x30 /* 28-Bit */
-#define WIN_WRITE_EXT 0x34 /* 48-Bit */
-#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */
-#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */
-#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */
-#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */
-#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */
-#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */
-#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */
-#define WIN_VERIFY_EXT 0x42 /* 48-Bit */
-#define WIN_FORMAT 0x50
-#define WIN_INIT 0x60
-#define WIN_SEEK 0x70
-#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */
-#define WIN_DIAGNOSE 0x90
-#define WIN_SPECIFY 0x91 /* set drive geometry translation */
-#define WIN_DOWNLOAD_MICROCODE 0x92
-#define WIN_STANDBYNOW2 0x94
-#define WIN_SETIDLE2 0x97
-#define WIN_CHECKPOWERMODE2 0x98
-#define WIN_SLEEPNOW2 0x99
-#define WIN_PACKETCMD 0xA0 /* Send a packet command. */
-#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */
-#define WIN_QUEUED_SERVICE 0xA2
-#define WIN_SMART 0xB0 /* self-monitoring and reporting */
-#define CFA_ERASE_SECTORS 0xC0
-#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/
-#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */
-#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */
-#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */
-#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */
-#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */
-#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */
-#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */
-#define WIN_GETMEDIASTATUS 0xDA
-#define WIN_DOORLOCK 0xDE /* lock door on removable drives */
-#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */
-#define WIN_STANDBYNOW1 0xE0
-#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */
-#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */
-#define WIN_SETIDLE1 0xE3
-#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */
-#define WIN_CHECKPOWERMODE1 0xE5
-#define WIN_SLEEPNOW1 0xE6
-#define WIN_FLUSH_CACHE 0xE7
-#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */
-#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */
-#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */
-#define WIN_MEDIAEJECT 0xED
-#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */
-#define WIN_SETFEATURES 0xEF /* set special drive features */
-#define EXABYTE_ENABLE_NEST 0xF0
-#define WIN_SECURITY_SET_PASS 0xF1
-#define WIN_SECURITY_UNLOCK 0xF2
-#define WIN_SECURITY_ERASE_PREPARE 0xF3
-#define WIN_SECURITY_ERASE_UNIT 0xF4
-#define WIN_SECURITY_FREEZE_LOCK 0xF5
-#define WIN_SECURITY_DISABLE 0xF6
-#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */
-#define WIN_SET_MAX 0xF9
-#define DISABLE_SEAGATE 0xFB
-
-/* WIN_SMART sub-commands */
-
-#define SMART_READ_VALUES 0xD0
-#define SMART_READ_THRESHOLDS 0xD1
-#define SMART_AUTOSAVE 0xD2
-#define SMART_SAVE 0xD3
-#define SMART_IMMEDIATE_OFFLINE 0xD4
-#define SMART_READ_LOG_SECTOR 0xD5
-#define SMART_WRITE_LOG_SECTOR 0xD6
-#define SMART_WRITE_THRESHOLDS 0xD7
-#define SMART_ENABLE 0xD8
-#define SMART_DISABLE 0xD9
-#define SMART_STATUS 0xDA
-#define SMART_AUTO_OFFLINE 0xDB
-
-/* Password used in TF4 & TF5 executing SMART commands */
-
-#define SMART_LCYL_PASS 0x4F
-#define SMART_HCYL_PASS 0xC2
-
-/* WIN_SETFEATURES sub-commands */
-
-#define SETFEATURES_EN_WCACHE 0x02 /* Enable write cache */
-#define SETFEATURES_XFER 0x03 /* Set transfer mode */
-# define XFER_UDMA_7 0x47 /* 0100|0111 */
-# define XFER_UDMA_6 0x46 /* 0100|0110 */
-# define XFER_UDMA_5 0x45 /* 0100|0101 */
-# define XFER_UDMA_4 0x44 /* 0100|0100 */
-# define XFER_UDMA_3 0x43 /* 0100|0011 */
-# define XFER_UDMA_2 0x42 /* 0100|0010 */
-# define XFER_UDMA_1 0x41 /* 0100|0001 */
-# define XFER_UDMA_0 0x40 /* 0100|0000 */
-# define XFER_MW_DMA_2 0x22 /* 0010|0010 */
-# define XFER_MW_DMA_1 0x21 /* 0010|0001 */
-# define XFER_MW_DMA_0 0x20 /* 0010|0000 */
-# define XFER_SW_DMA_2 0x12 /* 0001|0010 */
-# define XFER_SW_DMA_1 0x11 /* 0001|0001 */
-# define XFER_SW_DMA_0 0x10 /* 0001|0000 */
-# define XFER_PIO_4 0x0C /* 0000|1100 */
-# define XFER_PIO_3 0x0B /* 0000|1011 */
-# define XFER_PIO_2 0x0A /* 0000|1010 */
-# define XFER_PIO_1 0x09 /* 0000|1001 */
-# define XFER_PIO_0 0x08 /* 0000|1000 */
-# define XFER_PIO_SLOW 0x00 /* 0000|0000 */
-#define SETFEATURES_DIS_DEFECT 0x04 /* Disable Defect Management */
-#define SETFEATURES_EN_APM 0x05 /* Enable advanced power management */
-#define SETFEATURES_DIS_MSN 0x31 /* Disable Media Status Notification */
-#define SETFEATURES_EN_AAM 0x42 /* Enable Automatic Acoustic Management */
-#define SETFEATURES_DIS_RLA 0x55 /* Disable read look-ahead feature */
-#define SETFEATURES_EN_RI 0x5D /* Enable release interrupt */
-#define SETFEATURES_EN_SI 0x5E /* Enable SERVICE interrupt */
-#define SETFEATURES_DIS_RPOD 0x66 /* Disable reverting to power on defaults */
-#define SETFEATURES_DIS_WCACHE 0x82 /* Disable write cache */
-#define SETFEATURES_EN_DEFECT 0x84 /* Enable Defect Management */
-#define SETFEATURES_DIS_APM 0x85 /* Disable advanced power management */
-#define SETFEATURES_EN_MSN 0x95 /* Enable Media Status Notification */
-#define SETFEATURES_EN_RLA 0xAA /* Enable read look-ahead feature */
-#define SETFEATURES_PREFETCH 0xAB /* Sets drive prefetch value */
-#define SETFEATURES_DIS_AAM 0xC2 /* Disable Automatic Acoustic Management */
-#define SETFEATURES_EN_RPOD 0xCC /* Enable reverting to power on defaults */
-#define SETFEATURES_DIS_RI 0xDD /* Disable release interrupt */
-#define SETFEATURES_DIS_SI 0xDE /* Disable SERVICE interrupt */
-
-/* WIN_SECURITY sub-commands */
-
-#define SECURITY_SET_PASSWORD 0xBA
-#define SECURITY_UNLOCK 0xBB
-#define SECURITY_ERASE_PREPARE 0xBC
-#define SECURITY_ERASE_UNIT 0xBD
-#define SECURITY_FREEZE_LOCK 0xBE
-#define SECURITY_DISABLE_PASSWORD 0xBF
-
struct hd_geometry {
- u8 heads;
- u8 sectors;
- u16 cylinders;
+ __u8 heads;
+ __u8 sectors;
+ __u16 cylinders;
unsigned long start;
};
-/* BIG GEOMETRY - dying, used only by HDIO_GETGEO_BIG_RAW */
-struct hd_big_geometry {
- u8 heads;
- u8 sectors;
- u32 cylinders;
- unsigned long start;
-};
-
/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */
#define HDIO_GETGEO 0x0301 /* get device geometry */
#define HDIO_GET_UNMASKINTR 0x0302 /* get current unmask setting */
@@ -306,263 +45,8 @@ struct hd_big_geometry {
#define HDIO_SET_QDMA 0x032e /* change use-qdma flag */
#define HDIO_SET_ADDRESS 0x032f /* change lba addressing modes */
-/* bus states */
-enum {
- BUSSTATE_OFF = 0,
- BUSSTATE_ON,
- BUSSTATE_TRISTATE
-};
-
/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x033n/0x033n */
/* 0x330 is reserved - used to be HDIO_GETGEO_BIG */
#define HDIO_GETGEO_BIG_RAW 0x0331 /* */
-#define __NEW_HD_DRIVE_ID
-
-/*
- * Structure returned by HDIO_GET_IDENTITY, as per ANSI NCITS ATA6 rev.1b spec.
- *
- * If you change something here, please remember to update fix_driveid() in
- * ide/probe.c.
- */
-struct hd_driveid {
- u16 config; /* lots of obsolete bit flags */
- u16 cyls; /* Obsolete, "physical" cyls */
- u16 reserved2; /* reserved (word 2) */
- u16 heads; /* Obsolete, "physical" heads */
- u16 track_bytes; /* unformatted bytes per track */
- u16 sector_bytes; /* unformatted bytes per sector */
- u16 sectors; /* Obsolete, "physical" sectors per track */
- u16 vendor0; /* vendor unique */
- u16 vendor1; /* vendor unique */
- u16 vendor2; /* Retired vendor unique */
- u8 serial_no[20]; /* 0 = not_specified */
- u16 buf_type; /* Retired */
- u16 buf_size; /* Retired, 512 byte increments
- * 0 = not_specified
- */
- u16 ecc_bytes; /* for r/w long cmds; 0 = not_specified */
- u8 fw_rev[8]; /* 0 = not_specified */
- char model[40]; /* 0 = not_specified */
- u8 max_multsect; /* 0=not_implemented */
- u8 vendor3; /* vendor unique */
- u16 dword_io; /* 0=not_implemented; 1=implemented */
- u8 vendor4; /* vendor unique */
- u8 capability; /* (upper byte of word 49)
- * 3: IORDYsup
- * 2: IORDYsw
- * 1: LBA
- * 0: DMA
- */
- u16 reserved50; /* reserved (word 50) */
- u8 vendor5; /* Obsolete, vendor unique */
- u8 tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */
- u8 vendor6; /* Obsolete, vendor unique */
- u8 tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */
- u16 field_valid; /* (word 53)
- * 2: ultra_ok word 88
- * 1: eide_ok words 64-70
- * 0: cur_ok words 54-58
- */
- u16 cur_cyls; /* Obsolete, logical cylinders */
- u16 cur_heads; /* Obsolete, l heads */
- u16 cur_sectors; /* Obsolete, l sectors per track */
- u16 cur_capacity0; /* Obsolete, l total sectors on drive */
- u16 cur_capacity1; /* Obsolete, (2 words, misaligned int) */
- u8 multsect; /* current multiple sector count */
- u8 multsect_valid; /* when (bit0==1) multsect is ok */
- u32 lba_capacity; /* Obsolete, total number of sectors */
- u16 dma_1word; /* Obsolete, single-word dma info */
- u16 dma_mword; /* multiple-word dma info */
- u16 eide_pio_modes; /* bits 0:mode3 1:mode4 */
- u16 eide_dma_min; /* min mword dma cycle time (ns) */
- u16 eide_dma_time; /* recommended mword dma cycle time (ns) */
- u16 eide_pio; /* min cycle time (ns), no IORDY */
- u16 eide_pio_iordy; /* min cycle time (ns), with IORDY */
- u16 words69_70[2]; /* reserved words 69-70
- * future command overlap and queuing
- */
- /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
- u16 words71_74[4]; /* reserved words 71-74
- * for IDENTIFY PACKET DEVICE command
- */
- u16 queue_depth; /* (word 75)
- * 15:5 reserved
- * 4:0 Maximum queue depth -1
- */
- u16 words76_79[4]; /* reserved words 76-79 */
- u16 major_rev_num; /* (word 80) */
- u16 minor_rev_num; /* (word 81) */
- u16 command_set_1; /* (word 82) supported
- * 15: Obsolete
- * 14: NOP command
- * 13: READ_BUFFER
- * 12: WRITE_BUFFER
- * 11: Obsolete
- * 10: Host Protected Area
- * 9: DEVICE Reset
- * 8: SERVICE Interrupt
- * 7: Release Interrupt
- * 6: look-ahead
- * 5: write cache
- * 4: PACKET Command
- * 3: Power Management Feature Set
- * 2: Removable Feature Set
- * 1: Security Feature Set
- * 0: SMART Feature Set
- */
- u16 command_set_2; /* (word 83)
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13: FLUSH CACHE EXT
- * 12: FLUSH CACHE
- * 11: Device Configuration Overlay
- * 10: 48-bit Address Feature Set
- * 9: Automatic Acoustic Management
- * 8: SET MAX security
- * 7: reserved 1407DT PARTIES
- * 6: SetF sub-command Power-Up
- * 5: Power-Up in Standby Feature Set
- * 4: Removable Media Notification
- * 3: APM Feature Set
- * 2: CFA Feature Set
- * 1: READ/WRITE DMA QUEUED
- * 0: Download MicroCode
- */
- u16 cfsse; /* (word 84)
- * cmd set-feature supported extensions
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13:3 reserved
- * 2: Media Serial Number Valid
- * 1: SMART selt-test supported
- * 0: SMART error logging
- */
- u16 cfs_enable_1; /* (word 85)
- * command set-feature enabled
- * 15: Obsolete
- * 14: NOP command
- * 13: READ_BUFFER
- * 12: WRITE_BUFFER
- * 11: Obsolete
- * 10: Host Protected Area
- * 9: DEVICE Reset
- * 8: SERVICE Interrupt
- * 7: Release Interrupt
- * 6: look-ahead
- * 5: write cache
- * 4: PACKET Command
- * 3: Power Management Feature Set
- * 2: Removable Feature Set
- * 1: Security Feature Set
- * 0: SMART Feature Set
- */
- u16 cfs_enable_2; /* (word 86)
- * command set-feature enabled
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13: FLUSH CACHE EXT
- * 12: FLUSH CACHE
- * 11: Device Configuration Overlay
- * 10: 48-bit Address Feature Set
- * 9: Automatic Acoustic Management
- * 8: SET MAX security
- * 7: reserved 1407DT PARTIES
- * 6: SetF sub-command Power-Up
- * 5: Power-Up in Standby Feature Set
- * 4: Removable Media Notification
- * 3: APM Feature Set
- * 2: CFA Feature Set
- * 1: READ/WRITE DMA QUEUED
- * 0: Download MicroCode
- */
- u16 csf_default; /* (word 87)
- * command set-feature default
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13:3 reserved
- * 2: Media Serial Number Valid
- * 1: SMART selt-test supported
- * 0: SMART error logging
- */
- u16 dma_ultra; /* (word 88) */
- u16 word89; /* reserved (word 89) */
- u16 word90; /* reserved (word 90) */
- u16 CurAPMvalues; /* current APM values */
- u16 word92; /* reserved (word 92) */
- u16 hw_config; /* hardware config (word 93)
- * 15:
- * 14:
- * 13:
- * 12:
- * 11:
- * 10:
- * 9:
- * 8:
- * 7:
- * 6:
- * 5:
- * 4:
- * 3:
- * 2:
- * 1:
- * 0:
- */
- u16 acoustic; /* (word 94)
- * 15:8 Vendor's recommended value
- * 7:0 current value
- */
- u16 words95_99[5]; /* reserved words 95-99 */
- u64 lba_capacity_2; /* 48-bit total number of sectors */
- u16 words104_125[22];/* reserved words 104-125 */
- u16 last_lun; /* (word 126) */
- u16 word127; /* (word 127) Feature Set
- * Removable Media Notification
- * 15:2 reserved
- * 1:0 00 = not supported
- * 01 = supported
- * 10 = reserved
- * 11 = reserved
- */
- u16 dlf; /* (word 128)
- * device lock function
- * 15:9 reserved
- * 8 security level 1:max 0:high
- * 7:6 reserved
- * 5 enhanced erase
- * 4 expire
- * 3 frozen
- * 2 locked
- * 1 en/disabled
- * 0 capability
- */
- u16 csfo; /* (word 129)
- * current set features options
- * 15:4 reserved
- * 3: auto reassign
- * 2: reverting
- * 1: read-look-ahead
- * 0: write cache
- */
- u16 words130_155[26];/* reserved vendor words 130-155 */
- u16 word156; /* reserved vendor word 156 */
- u16 words157_159[3];/* reserved vendor words 157-159 */
- u16 cfa_power; /* (word 160) CFA Power Mode
- * 15 word 160 supported
- * 14 reserved
- * 13
- * 12
- * 11:0
- */
- u16 words161_175[14];/* Reserved for CFA */
- u16 words176_205[31];/* Current Media Serial Number */
- u16 words206_254[48];/* reserved words 206-254 */
- u16 integrity_word; /* (word 255)
- * 15:8 Checksum
- * 7:0 Signature
- */
-} __attribute__((packed));
-
-#define IDE_NICE_DSC_OVERLAP (0) /* per the DSC overlap protocol */
-
#endif
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 8a41b3b2e74a..4dd795f055e6 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -8,7 +8,6 @@
#include <linux/config.h>
#include <linux/init.h>
#include <linux/ioport.h>
-#include <linux/hdreg.h>
#include <linux/hdsmart.h>
#include <linux/blkdev.h>
#include <linux/proc_fs.h>
@@ -51,7 +50,460 @@
* "No user-serviceable parts" beyond this point
*****************************************************************************/
-typedef unsigned char byte; /* used everywhere */
+
+/* ATA/ATAPI Commands pre T13 Spec */
+#define WIN_NOP 0x00
+#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */
+#define WIN_SRST 0x08 /* ATAPI soft reset command */
+#define WIN_DEVICE_RESET 0x08
+#define WIN_RESTORE 0x10
+#define WIN_READ 0x20 /* 28-Bit */
+#define WIN_READ_EXT 0x24 /* 48-Bit */
+#define WIN_READDMA_EXT 0x25 /* 48-Bit */
+#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */
+#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */
+#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */
+#define WIN_WRITE 0x30 /* 28-Bit */
+#define WIN_WRITE_EXT 0x34 /* 48-Bit */
+#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */
+#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */
+#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */
+#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */
+#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */
+#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */
+#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */
+#define WIN_VERIFY_EXT 0x42 /* 48-Bit */
+#define WIN_FORMAT 0x50
+#define WIN_INIT 0x60
+#define WIN_SEEK 0x70
+#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */
+#define WIN_DIAGNOSE 0x90
+#define WIN_SPECIFY 0x91 /* set drive geometry translation */
+#define WIN_DOWNLOAD_MICROCODE 0x92
+#define WIN_STANDBYNOW2 0x94
+#define WIN_SETIDLE2 0x97
+#define WIN_CHECKPOWERMODE2 0x98
+#define WIN_SLEEPNOW2 0x99
+#define WIN_PACKETCMD 0xA0 /* Send a packet command. */
+#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */
+#define WIN_QUEUED_SERVICE 0xA2
+#define WIN_SMART 0xB0 /* self-monitoring and reporting */
+#define CFA_ERASE_SECTORS 0xC0
+#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/
+#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */
+#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */
+#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */
+#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */
+#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */
+#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */
+#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */
+#define WIN_GETMEDIASTATUS 0xDA
+#define WIN_DOORLOCK 0xDE /* lock door on removable drives */
+#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */
+#define WIN_STANDBYNOW1 0xE0
+#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */
+#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */
+#define WIN_SETIDLE1 0xE3
+#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */
+#define WIN_CHECKPOWERMODE1 0xE5
+#define WIN_SLEEPNOW1 0xE6
+#define WIN_FLUSH_CACHE 0xE7
+#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */
+#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */
+#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */
+#define WIN_MEDIAEJECT 0xED
+#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */
+#define WIN_SETFEATURES 0xEF /* set special drive features */
+#define EXABYTE_ENABLE_NEST 0xF0
+#define WIN_SECURITY_SET_PASS 0xF1
+#define WIN_SECURITY_UNLOCK 0xF2
+#define WIN_SECURITY_ERASE_PREPARE 0xF3
+#define WIN_SECURITY_ERASE_UNIT 0xF4
+#define WIN_SECURITY_FREEZE_LOCK 0xF5
+#define WIN_SECURITY_DISABLE 0xF6
+#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */
+#define WIN_SET_MAX 0xF9
+#define DISABLE_SEAGATE 0xFB
+
+/* WIN_SMART sub-commands */
+
+#define SMART_READ_VALUES 0xD0
+#define SMART_READ_THRESHOLDS 0xD1
+#define SMART_AUTOSAVE 0xD2
+#define SMART_SAVE 0xD3
+#define SMART_IMMEDIATE_OFFLINE 0xD4
+#define SMART_READ_LOG_SECTOR 0xD5
+#define SMART_WRITE_LOG_SECTOR 0xD6
+#define SMART_WRITE_THRESHOLDS 0xD7
+#define SMART_ENABLE 0xD8
+#define SMART_DISABLE 0xD9
+#define SMART_STATUS 0xDA
+#define SMART_AUTO_OFFLINE 0xDB
+
+/* Password used in TF4 & TF5 executing SMART commands */
+
+#define SMART_LCYL_PASS 0x4F
+#define SMART_HCYL_PASS 0xC2
+
+/* WIN_SETFEATURES sub-commands */
+
+#define SETFEATURES_EN_WCACHE 0x02 /* Enable write cache */
+
+#define SETFEATURES_XFER 0x03 /* Set transfer mode */
+# define XFER_UDMA_7 0x47 /* 0100|0111 */
+# define XFER_UDMA_6 0x46 /* 0100|0110 */
+# define XFER_UDMA_5 0x45 /* 0100|0101 */
+# define XFER_UDMA_4 0x44 /* 0100|0100 */
+# define XFER_UDMA_3 0x43 /* 0100|0011 */
+# define XFER_UDMA_2 0x42 /* 0100|0010 */
+# define XFER_UDMA_1 0x41 /* 0100|0001 */
+# define XFER_UDMA_0 0x40 /* 0100|0000 */
+# define XFER_MW_DMA_2 0x22 /* 0010|0010 */
+# define XFER_MW_DMA_1 0x21 /* 0010|0001 */
+# define XFER_MW_DMA_0 0x20 /* 0010|0000 */
+# define XFER_SW_DMA_2 0x12 /* 0001|0010 */
+# define XFER_SW_DMA_1 0x11 /* 0001|0001 */
+# define XFER_SW_DMA_0 0x10 /* 0001|0000 */
+# define XFER_PIO_4 0x0C /* 0000|1100 */
+# define XFER_PIO_3 0x0B /* 0000|1011 */
+# define XFER_PIO_2 0x0A /* 0000|1010 */
+# define XFER_PIO_1 0x09 /* 0000|1001 */
+# define XFER_PIO_0 0x08 /* 0000|1000 */
+# define XFER_PIO_SLOW 0x00 /* 0000|0000 */
+
+#define SETFEATURES_DIS_DEFECT 0x04 /* Disable Defect Management */
+#define SETFEATURES_EN_APM 0x05 /* Enable advanced power management */
+#define SETFEATURES_DIS_MSN 0x31 /* Disable Media Status Notification */
+#define SETFEATURES_EN_AAM 0x42 /* Enable Automatic Acoustic Management */
+#define SETFEATURES_DIS_RLA 0x55 /* Disable read look-ahead feature */
+#define SETFEATURES_EN_RI 0x5D /* Enable release interrupt */
+#define SETFEATURES_EN_SI 0x5E /* Enable SERVICE interrupt */
+#define SETFEATURES_DIS_RPOD 0x66 /* Disable reverting to power on defaults */
+#define SETFEATURES_DIS_WCACHE 0x82 /* Disable write cache */
+#define SETFEATURES_EN_DEFECT 0x84 /* Enable Defect Management */
+#define SETFEATURES_DIS_APM 0x85 /* Disable advanced power management */
+#define SETFEATURES_EN_MSN 0x95 /* Enable Media Status Notification */
+#define SETFEATURES_EN_RLA 0xAA /* Enable read look-ahead feature */
+#define SETFEATURES_PREFETCH 0xAB /* Sets drive prefetch value */
+#define SETFEATURES_DIS_AAM 0xC2 /* Disable Automatic Acoustic Management */
+#define SETFEATURES_EN_RPOD 0xCC /* Enable reverting to power on defaults */
+#define SETFEATURES_DIS_RI 0xDD /* Disable release interrupt */
+#define SETFEATURES_DIS_SI 0xDE /* Disable SERVICE interrupt */
+
+/* WIN_SECURITY sub-commands */
+
+#define SECURITY_SET_PASSWORD 0xBA
+#define SECURITY_UNLOCK 0xBB
+#define SECURITY_ERASE_PREPARE 0xBC
+#define SECURITY_ERASE_UNIT 0xBD
+#define SECURITY_FREEZE_LOCK 0xBE
+#define SECURITY_DISABLE_PASSWORD 0xBF
+
+
+/* Taskfile related constants.
+ */
+#define IDE_DRIVE_TASK_INVALID -1
+#define IDE_DRIVE_TASK_NO_DATA 0
+#define IDE_DRIVE_TASK_SET_XFER 1
+
+#define IDE_DRIVE_TASK_IN 2
+
+#define IDE_DRIVE_TASK_OUT 3
+#define IDE_DRIVE_TASK_RAW_WRITE 4
+
+struct hd_drive_task_hdr {
+ u8 feature;
+ u8 sector_count;
+ u8 sector_number;
+ u8 low_cylinder;
+ u8 high_cylinder;
+ u8 device_head;
+} __attribute__((packed));
+
+/*
+ * Define standard taskfile in/out register
+ */
+#define IDE_TASKFILE_STD_OUT_FLAGS 0xFE
+#define IDE_TASKFILE_STD_IN_FLAGS 0xFE
+#define IDE_HOB_STD_OUT_FLAGS 0xC0
+#define IDE_HOB_STD_IN_FLAGS 0xC0
+
+#define TASKFILE_INVALID 0x7fff
+#define TASKFILE_48 0x8000
+
+#define TASKFILE_NO_DATA 0x0000
+
+#define TASKFILE_IN 0x0001
+#define TASKFILE_MULTI_IN 0x0002
+
+#define TASKFILE_OUT 0x0004
+#define TASKFILE_MULTI_OUT 0x0008
+#define TASKFILE_IN_OUT 0x0010
+
+#define TASKFILE_IN_DMA 0x0020
+#define TASKFILE_OUT_DMA 0x0040
+#define TASKFILE_IN_DMAQ 0x0080
+#define TASKFILE_OUT_DMAQ 0x0100
+
+#define TASKFILE_P_IN 0x0200
+#define TASKFILE_P_OUT 0x0400
+#define TASKFILE_P_IN_DMA 0x0800
+#define TASKFILE_P_OUT_DMA 0x1000
+#define TASKFILE_P_IN_DMAQ 0x2000
+#define TASKFILE_P_OUT_DMAQ 0x4000
+
+/* bus states */
+enum {
+ BUSSTATE_OFF = 0,
+ BUSSTATE_ON,
+ BUSSTATE_TRISTATE
+};
+
+/*
+ * Structure returned by HDIO_GET_IDENTITY, as per ANSI NCITS ATA6 rev.1b spec.
+ *
+ * If you change something here, please remember to update fix_driveid() in
+ * ide/probe.c.
+ */
+struct hd_driveid {
+ u16 config; /* lots of obsolete bit flags */
+ u16 cyls; /* Obsolete, "physical" cyls */
+ u16 reserved2; /* reserved (word 2) */
+ u16 heads; /* Obsolete, "physical" heads */
+ u16 track_bytes; /* unformatted bytes per track */
+ u16 sector_bytes; /* unformatted bytes per sector */
+ u16 sectors; /* Obsolete, "physical" sectors per track */
+ u16 vendor0; /* vendor unique */
+ u16 vendor1; /* vendor unique */
+ u16 vendor2; /* Retired vendor unique */
+ u8 serial_no[20]; /* 0 = not_specified */
+ u16 buf_type; /* Retired */
+ u16 buf_size; /* Retired, 512 byte increments
+ * 0 = not_specified
+ */
+ u16 ecc_bytes; /* for r/w long cmds; 0 = not_specified */
+ u8 fw_rev[8]; /* 0 = not_specified */
+ char model[40]; /* 0 = not_specified */
+ u8 max_multsect; /* 0=not_implemented */
+ u8 vendor3; /* vendor unique */
+ u16 dword_io; /* 0=not_implemented; 1=implemented */
+ u8 vendor4; /* vendor unique */
+ u8 capability; /* (upper byte of word 49)
+ * 3: IORDYsup
+ * 2: IORDYsw
+ * 1: LBA
+ * 0: DMA
+ */
+ u16 reserved50; /* reserved (word 50) */
+ u8 vendor5; /* Obsolete, vendor unique */
+ u8 tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */
+ u8 vendor6; /* Obsolete, vendor unique */
+ u8 tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */
+ u16 field_valid; /* (word 53)
+ * 2: ultra_ok word 88
+ * 1: eide_ok words 64-70
+ * 0: cur_ok words 54-58
+ */
+ u16 cur_cyls; /* Obsolete, logical cylinders */
+ u16 cur_heads; /* Obsolete, l heads */
+ u16 cur_sectors; /* Obsolete, l sectors per track */
+ u16 cur_capacity0; /* Obsolete, l total sectors on drive */
+ u16 cur_capacity1; /* Obsolete, (2 words, misaligned int) */
+ u8 multsect; /* current multiple sector count */
+ u8 multsect_valid; /* when (bit0==1) multsect is ok */
+ u32 lba_capacity; /* Obsolete, total number of sectors */
+ u16 dma_1word; /* Obsolete, single-word dma info */
+ u16 dma_mword; /* multiple-word dma info */
+ u16 eide_pio_modes; /* bits 0:mode3 1:mode4 */
+ u16 eide_dma_min; /* min mword dma cycle time (ns) */
+ u16 eide_dma_time; /* recommended mword dma cycle time (ns) */
+ u16 eide_pio; /* min cycle time (ns), no IORDY */
+ u16 eide_pio_iordy; /* min cycle time (ns), with IORDY */
+ u16 words69_70[2]; /* reserved words 69-70
+ * future command overlap and queuing
+ */
+ /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
+ u16 words71_74[4]; /* reserved words 71-74
+ * for IDENTIFY PACKET DEVICE command
+ */
+ u16 queue_depth; /* (word 75)
+ * 15:5 reserved
+ * 4:0 Maximum queue depth -1
+ */
+ u16 words76_79[4]; /* reserved words 76-79 */
+ u16 major_rev_num; /* (word 80) */
+ u16 minor_rev_num; /* (word 81) */
+ u16 command_set_1; /* (word 82) supported
+ * 15: Obsolete
+ * 14: NOP command
+ * 13: READ_BUFFER
+ * 12: WRITE_BUFFER
+ * 11: Obsolete
+ * 10: Host Protected Area
+ * 9: DEVICE Reset
+ * 8: SERVICE Interrupt
+ * 7: Release Interrupt
+ * 6: look-ahead
+ * 5: write cache
+ * 4: PACKET Command
+ * 3: Power Management Feature Set
+ * 2: Removable Feature Set
+ * 1: Security Feature Set
+ * 0: SMART Feature Set
+ */
+ u16 command_set_2; /* (word 83)
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13: FLUSH CACHE EXT
+ * 12: FLUSH CACHE
+ * 11: Device Configuration Overlay
+ * 10: 48-bit Address Feature Set
+ * 9: Automatic Acoustic Management
+ * 8: SET MAX security
+ * 7: reserved 1407DT PARTIES
+ * 6: SetF sub-command Power-Up
+ * 5: Power-Up in Standby Feature Set
+ * 4: Removable Media Notification
+ * 3: APM Feature Set
+ * 2: CFA Feature Set
+ * 1: READ/WRITE DMA QUEUED
+ * 0: Download MicroCode
+ */
+ u16 cfsse; /* (word 84)
+ * cmd set-feature supported extensions
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13:3 reserved
+ * 2: Media Serial Number Valid
+ * 1: SMART selt-test supported
+ * 0: SMART error logging
+ */
+ u16 cfs_enable_1; /* (word 85)
+ * command set-feature enabled
+ * 15: Obsolete
+ * 14: NOP command
+ * 13: READ_BUFFER
+ * 12: WRITE_BUFFER
+ * 11: Obsolete
+ * 10: Host Protected Area
+ * 9: DEVICE Reset
+ * 8: SERVICE Interrupt
+ * 7: Release Interrupt
+ * 6: look-ahead
+ * 5: write cache
+ * 4: PACKET Command
+ * 3: Power Management Feature Set
+ * 2: Removable Feature Set
+ * 1: Security Feature Set
+ * 0: SMART Feature Set
+ */
+ u16 cfs_enable_2; /* (word 86)
+ * command set-feature enabled
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13: FLUSH CACHE EXT
+ * 12: FLUSH CACHE
+ * 11: Device Configuration Overlay
+ * 10: 48-bit Address Feature Set
+ * 9: Automatic Acoustic Management
+ * 8: SET MAX security
+ * 7: reserved 1407DT PARTIES
+ * 6: SetF sub-command Power-Up
+ * 5: Power-Up in Standby Feature Set
+ * 4: Removable Media Notification
+ * 3: APM Feature Set
+ * 2: CFA Feature Set
+ * 1: READ/WRITE DMA QUEUED
+ * 0: Download MicroCode
+ */
+ u16 csf_default; /* (word 87)
+ * command set-feature default
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13:3 reserved
+ * 2: Media Serial Number Valid
+ * 1: SMART selt-test supported
+ * 0: SMART error logging
+ */
+ u16 dma_ultra; /* (word 88) */
+ u16 word89; /* reserved (word 89) */
+ u16 word90; /* reserved (word 90) */
+ u16 CurAPMvalues; /* current APM values */
+ u16 word92; /* reserved (word 92) */
+ u16 hw_config; /* hardware config (word 93)
+ * 15:
+ * 14:
+ * 13:
+ * 12:
+ * 11:
+ * 10:
+ * 9:
+ * 8:
+ * 7:
+ * 6:
+ * 5:
+ * 4:
+ * 3:
+ * 2:
+ * 1:
+ * 0:
+ */
+ u16 acoustic; /* (word 94)
+ * 15:8 Vendor's recommended value
+ * 7:0 current value
+ */
+ u16 words95_99[5]; /* reserved words 95-99 */
+ u64 lba_capacity_2; /* 48-bit total number of sectors */
+ u16 words104_125[22];/* reserved words 104-125 */
+ u16 last_lun; /* (word 126) */
+ u16 word127; /* (word 127) Feature Set
+ * Removable Media Notification
+ * 15:2 reserved
+ * 1:0 00 = not supported
+ * 01 = supported
+ * 10 = reserved
+ * 11 = reserved
+ */
+ u16 dlf; /* (word 128)
+ * device lock function
+ * 15:9 reserved
+ * 8 security level 1:max 0:high
+ * 7:6 reserved
+ * 5 enhanced erase
+ * 4 expire
+ * 3 frozen
+ * 2 locked
+ * 1 en/disabled
+ * 0 capability
+ */
+ u16 csfo; /* (word 129)
+ * current set features options
+ * 15:4 reserved
+ * 3: auto reassign
+ * 2: reverting
+ * 1: read-look-ahead
+ * 0: write cache
+ */
+ u16 words130_155[26];/* reserved vendor words 130-155 */
+ u16 word156; /* reserved vendor word 156 */
+ u16 words157_159[3];/* reserved vendor words 157-159 */
+ u16 cfa_power; /* (word 160) CFA Power Mode
+ * 15 word 160 supported
+ * 14 reserved
+ * 13
+ * 12
+ * 11:0
+ */
+ u16 words161_175[14];/* Reserved for CFA */
+ u16 words176_205[31];/* Current Media Serial Number */
+ u16 words206_254[48];/* reserved words 206-254 */
+ u16 integrity_word; /* (word 255)
+ * 15:8 Checksum
+ * 7:0 Signature
+ */
+} __attribute__((packed));
+
+#define IDE_NICE_DSC_OVERLAP (0) /* per the DSC overlap protocol */
/*
* Probably not wise to fiddle with these
@@ -105,6 +557,35 @@ enum {
#define GET_ALTSTAT() IN_BYTE(drive->channel->io_ports[IDE_CONTROL_OFFSET])
#define GET_FEAT() IN_BYTE(IDE_NSECTOR_REG)
+/* Bits of HD_STATUS */
+#define ERR_STAT 0x01
+#define INDEX_STAT 0x02
+#define ECC_STAT 0x04 /* Corrected error */
+#define DRQ_STAT 0x08
+#define SEEK_STAT 0x10
+#define SERVICE_STAT SEEK_STAT
+#define WRERR_STAT 0x20
+#define READY_STAT 0x40
+#define BUSY_STAT 0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR 0x01 /* Bad address mark */
+#define TRK0_ERR 0x02 /* couldn't find track 0 */
+#define ABRT_ERR 0x04 /* Command aborted */
+#define MCR_ERR 0x08 /* media change request */
+#define ID_ERR 0x10 /* ID field not found */
+#define MC_ERR 0x20 /* media changed */
+#define ECC_ERR 0x40 /* Uncorrectable ECC error */
+#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
+#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
+
+/*
+ * sector count bits
+ */
+#define NSEC_CD 0x01
+#define NSEC_IO 0x02
+#define NSEC_REL 0x04
+
#define BAD_R_STAT (BUSY_STAT | ERR_STAT)
#define BAD_W_STAT (BAD_R_STAT | WRERR_STAT)
#define BAD_STAT (BAD_R_STAT | DRQ_STAT)
@@ -665,23 +1146,23 @@ extern struct block_device_operations ide_fops[];
*/
extern int ideprobe_init(void);
#ifdef CONFIG_BLK_DEV_IDEDISK
-extern int idedisk_init (void);
+extern int idedisk_init(void);
#endif
#ifdef CONFIG_BLK_DEV_IDECD
-extern int ide_cdrom_init (void);
+extern int ide_cdrom_init(void);
#endif
#ifdef CONFIG_BLK_DEV_IDETAPE
-extern int idetape_init (void);
+extern int idetape_init(void);
#endif
#ifdef CONFIG_BLK_DEV_IDEFLOPPY
-extern int idefloppy_init (void);
+extern int idefloppy_init(void);
#endif
#ifdef CONFIG_BLK_DEV_IDESCSI
-extern int idescsi_init (void);
+extern int idescsi_init(void);
#endif
-extern int ide_register_subdriver(struct ata_device *, struct ata_operations *);
-extern int ide_unregister_subdriver(struct ata_device *drive);
+extern int ata_register_device(struct ata_device *, struct ata_operations *);
+extern int ata_unregister_device(struct ata_device *drive);
extern int ata_revalidate(kdev_t i_rdev);
extern void ide_driver_module(void);
diff --git a/kernel/fork.c b/kernel/fork.c
index dee7097ba082..d40d246ec1df 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -608,22 +608,20 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
}
/*
- * Ok, this is the main fork-routine. It copies the system process
- * information (task[nr]) and sets up the necessary registers. It also
- * copies the data segment in its entirety. The "stack_start" and
- * "stack_top" arguments are simply passed along to the platform
- * specific copy_thread() routine. Most platforms ignore stack_top.
- * For an example that's using stack_top, see
- * arch/ia64/kernel/process.c.
+ * This creates a new process as a copy of the old one,
+ * but does not actually start it yet.
+ *
+ * It copies the registers, and all the appropriate
+ * parts of the process environment (as per the clone
+ * flags). The actual kick-off is left to the caller.
*/
-struct task_struct *do_fork(unsigned long clone_flags,
+static struct task_struct *copy_process(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size)
{
int retval;
struct task_struct *p = NULL;
- struct completion vfork;
if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
return ERR_PTR(-EINVAL);
@@ -680,10 +678,6 @@ struct task_struct *do_fork(unsigned long clone_flags,
INIT_LIST_HEAD(&p->sibling);
init_waitqueue_head(&p->wait_chldexit);
p->vfork_done = NULL;
- if (clone_flags & CLONE_VFORK) {
- p->vfork_done = &vfork;
- init_completion(&vfork);
- }
spin_lock_init(&p->alloc_lock);
spin_lock_init(&p->switch_lock);
@@ -803,20 +797,6 @@ struct task_struct *do_fork(unsigned long clone_flags,
hash_pid(p);
nr_threads++;
write_unlock_irq(&tasklist_lock);
-
- if (p->ptrace & PT_PTRACED)
- send_sig(SIGSTOP, p, 1);
-
- wake_up_forked_process(p); /* do this last */
- ++total_forks;
- if (clone_flags & CLONE_VFORK)
- wait_for_completion(&vfork);
- else
- /*
- * Let the child process run first, to avoid most of the
- * COW overhead when the child exec()s afterwards.
- */
- set_need_resched();
retval = 0;
fork_out:
@@ -850,6 +830,45 @@ bad_fork_free:
goto fork_out;
}
+/*
+ * Ok, this is the main fork-routine.
+ *
+ * It copies the process, and if successful kick-starts
+ * it and waits for it to finish using the VM if required.
+ */
+struct task_struct *do_fork(unsigned long clone_flags,
+ unsigned long stack_start,
+ struct pt_regs *regs,
+ unsigned long stack_size)
+{
+ struct task_struct *p;
+
+ p = copy_process(clone_flags, stack_start, regs, stack_size);
+ if (!IS_ERR(p)) {
+ struct completion vfork;
+
+ if (clone_flags & CLONE_VFORK) {
+ p->vfork_done = &vfork;
+ init_completion(&vfork);
+ }
+
+ if (p->ptrace & PT_PTRACED)
+ send_sig(SIGSTOP, p, 1);
+
+ wake_up_forked_process(p); /* do this last */
+ ++total_forks;
+ if (clone_flags & CLONE_VFORK)
+ wait_for_completion(&vfork);
+ else
+ /*
+ * Let the child process run first, to avoid most of the
+ * COW overhead when the child exec()s afterwards.
+ */
+ set_need_resched();
+ }
+ return p;
+}
+
/* SLAB cache for signal_struct structures (tsk->sig) */
kmem_cache_t *sigact_cachep;