Commit 4478f040 authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.18 IDE 71

 - Rewritten Artop host chip driver by Vojtech Pavlik. His log entries are:

   Cleanup whitespace.

   Remove superfluous chip entries in chip table.  Remove global variables to
   allow more than one controller.  Remove other forgotten stuff.

   This is a new driver for the Artop (Acard) controllers. It's completely
   untested, as I have never seen the hardware. However, I suspect it is much
   less broken than the previous one ...

   UDMA33 controller cannot detect 80-wire cable.

 - Separate ioctl handling out from ide.c. It's big enough.

 - Move atapi_read and atapi_write to the new atapi module.  Fix the declaration
   of those functions. The data buffer did have the void * type!

 - Separate module handling code out from actual transfer handling code in to a
   new module called main.c. Slowly we are at the stage where the code indeed
   has to be organized logically and not just "sporadically" as was the case
   before.

 - Apply patch by Adam Richter for the ide-scsi.c attach method implementation.
   This particular driver is still broken due to generic SCSI layer issues.

 - Apply true modularization patch for qd65xx.c by Samuel Thibault. Here
   are his notes about it:

   Then, patch-modularize-2.[45] is a proposal for modularizing qd65xx.o. As a
   single module, one can choose to insmod it before being able to do some
   hdparm -p /dev/hd[a-d]. But one can't remove it while tuned, since selectproc
   may be needed.

   I am sorry I wasn't able to test it under 2.5 series, lacking a functionning
   kernel for my test computer, but it seemed to work perfectly under 2.4
   series, and patches are almost the same.

 - Move PCI device id's to where they belong. Patch by Vojtech Pavlik.

 - Don't use BH_Lock in ide-tape.c - somehow this driver scares me sometimes.
parent cd556cb5
...@@ -295,28 +295,13 @@ CONFIG_IDEDMA_IVB ...@@ -295,28 +295,13 @@ CONFIG_IDEDMA_IVB
It is normally safe to answer Y; however, the default is N. It is normally safe to answer Y; however, the default is N.
CONFIG_BLK_DEV_AEC62XX CONFIG_BLK_DEV_AEC62XX
This driver adds up to 4 more EIDE devices sharing a single This driver adds explicit support for Acard AEC62xx (Artop ATP8xx)
interrupt. This add-on card is a bootable PCI UDMA controller. In IDE controllers. This allows the kernel to change PIO, DMA and UDMA
order to get this card to initialize correctly in some cases, you speeds and to configure the chip to optimum performance.
should say Y here, and preferably also to "Use DMA by default when
available".
The ATP850U/UF is an UltraDMA 33 chipset base.
The ATP860 is an UltraDMA 66 chipset base.
The ATP860M(acintosh) version is an UltraDMA 66 chipset base.
The ATP865 is an ATA100/133 chipset.
Please read the comments at the top of <file:drivers/ide/aec62xx.c>.
If you say Y here, then say Y to "Use DMA by default when available"
as well.
CONFIG_AEC62XX_TUNING
Please read the comments at the top of <file:drivers/ide/aec62xx.c>.
If unsure, say N.
CONFIG_AEC6280_BURST CONFIG_AEC6280_BURST
Use burst mode for DMA transfers. Higher speed, but causes more load Use burst mode for DMA transfers. This helps to achieve higher
on the bus. transfer rates, but causes more load on the PCI bus.
If unsure, say N. If unsure, say N.
......
...@@ -40,9 +40,8 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then ...@@ -40,9 +40,8 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
int ' Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32 int ' Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32
fi fi
dep_bool ' Good-Bad DMA Model-Firmware (EXPERIMENTAL)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_EXPERIMENTAL dep_bool ' Good-Bad DMA Model-Firmware (EXPERIMENTAL)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_EXPERIMENTAL
dep_bool ' AEC62XX chip set support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' Acard (Artop) chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI
dep_mbool ' AEC62XX Tuning support' CONFIG_AEC62XX_TUNING $CONFIG_BLK_DEV_AEC62XX dep_mbool ' ATP865 burst mode' CONFIG_AEC6280_BURST $CONFIG_BLK_DEV_AEC62XX
dep_mbool ' AEC6280 Burst mode' CONFIG_AEC6280_BURST $CONFIG_BLK_DEV_AEC62XX
dep_bool ' ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_mbool ' ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3 $CONFIG_EXPERIMENTAL dep_mbool ' ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3 $CONFIG_EXPERIMENTAL
dep_bool ' AMD and nVidia chipset support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' AMD and nVidia chipset support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI
...@@ -122,7 +121,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then ...@@ -122,7 +121,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030 bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030
fi fi
bool ' QDI QD65xx support' CONFIG_BLK_DEV_QD65XX dep_tristate ' QDI QD65xx support' CONFIG_BLK_DEV_QD65XX $CONFIG_BLK_DEV_IDE
bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672 bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672
fi fi
if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" -o \ if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" -o \
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
O_TARGET := idedriver.o O_TARGET := idedriver.o
export-objs := ide-taskfile.o ide.o ide-features.o ide-probe.o quirks.o pcidma.o tcq.o \ export-objs := ide-taskfile.o main.o ide.o ide-features.o ide-probe.o quirks.o pcidma.o tcq.o \
atapi.o ataraid.o atapi.o ataraid.o
obj-y := obj-y :=
...@@ -27,6 +27,7 @@ obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o ...@@ -27,6 +27,7 @@ obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o
obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o
obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o
obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o
ide-obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o ide-obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o
ide-obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o ide-obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o
...@@ -58,7 +59,6 @@ ide-obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o ...@@ -58,7 +59,6 @@ ide-obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o
ide-obj-$(CONFIG_BLK_DEV_PDC202XX) += pdc202xx.o ide-obj-$(CONFIG_BLK_DEV_PDC202XX) += pdc202xx.o
ide-obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o ide-obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o
ide-obj-$(CONFIG_BLK_DEV_PIIX) += piix.o ide-obj-$(CONFIG_BLK_DEV_PIIX) += piix.o
ide-obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o
ide-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o ide-obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
ide-obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o ide-obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o
ide-obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o ide-obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o
...@@ -74,6 +74,7 @@ obj-$(CONFIG_BLK_DEV_ATARAID) += ataraid.o ...@@ -74,6 +74,7 @@ obj-$(CONFIG_BLK_DEV_ATARAID) += ataraid.o
obj-$(CONFIG_BLK_DEV_ATARAID_PDC) += pdcraid.o obj-$(CONFIG_BLK_DEV_ATARAID_PDC) += pdcraid.o
obj-$(CONFIG_BLK_DEV_ATARAID_HPT) += hptraid.o obj-$(CONFIG_BLK_DEV_ATARAID_HPT) += hptraid.o
ide-mod-objs := ide-taskfile.o ide.o ide-probe.o ide-geometry.o ide-features.o ata-timing.o atapi.o $(ide-obj-y) ide-mod-objs := ide-taskfile.o main.o ide.o ide-probe.o ide-geometry.o ide-features.o \
ioctl.o atapi.o ata-timing.o$(ide-obj-y)
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
/**** vi:set ts=8 sts=8 sw=8:************************************************ /*
*
* $Id: aec62xx.c,v 1.0 2002/05/24 14:37:19 vojtech Exp $
*
* Copyright (c) 2002 Vojtech Pavlik
*
* Based on the work of:
* Andre Hedrick
*/
/*
* AEC 6210UF (ATP850UF), AEC6260 (ATP860) and AEC6280 (ATP865) IDE driver for Linux.
*
* UDMA66 and higher modes are autoenabled only in case the BIOS has detected a
* 80 wire cable. To ignore the BIOS data and assume the cable is present, use
* 'ide0=ata66' or 'ide1=ata66' on the kernel command line.
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* *
* Version 0.11 March 27, 2002 * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* Copyright (C) 1999-2000 Andre Hedrick (andre@linux-ide.org) * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* Should you need to contact me, the author, you can do so either by
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/interrupt.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h>
#include "ata-timing.h" #include "ata-timing.h"
#include "pcihost.h" #include "pcihost.h"
#undef DISPLAY_AEC62XX_TIMINGS #define AEC_DRIVE_TIMING 0x40
#define AEC_UDMA_NEW 0x44
#ifndef HIGH_4 #define AEC_MISC 0x49
#define HIGH_4(H) ((H)=(H>>4)) #define AEC_IDE_ENABLE 0x4a
#endif #define AEC_UDMA_OLD 0x54
#ifndef LOW_4
#define LOW_4(L) ((L)=(L-((L>>4)<<4)))
#endif
#ifndef SPLIT_BYTE
#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4)))
#endif
#ifndef MAKE_WORD
#define MAKE_WORD(W,HB,LB) ((W)=((HB<<8)+LB))
#endif
static unsigned char aec_cyc2udma[17] = { 0, 0, 7, 6, 5, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1 };
#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) /*
#include <linux/stat.h> * aec_set_speed_old() writes timing values to
#include <linux/proc_fs.h> * the chipset registers for ATP850UF
*/
static int aec62xx_get_info(char *, char **, off_t, int);
extern int (*aec62xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
static struct pci_dev *bmide_dev;
static const char *aec6280_get_speed(u8 speed)
{
switch(speed) {
case 7: return "6";
case 6: return "5";
case 5: return "4";
case 4: return "3";
case 3: return "2";
case 2: return "1";
case 1: return "0";
case 0: return "?";
}
return "?";
}
static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count) static void aec_set_speed_old(struct pci_dev *dev, unsigned char dn, struct ata_timing *timing)
{ {
char *p = buffer; unsigned char t;
u32 bibma = pci_resource_start(bmide_dev, 4); pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1), FIT(timing->active, 0, 15));
u8 c0 = 0, c1 = 0; pci_write_config_byte(dev, AEC_DRIVE_TIMING + (dn << 1) + 1, FIT(timing->recover, 0, 15));
u8 art = 0, uart = 0;
switch(bmide_dev->device) { pci_read_config_byte(dev, AEC_UDMA_OLD, &t);
case PCI_DEVICE_ID_ARTOP_ATP850UF: t &= ~(3 << (dn << 1));
p += sprintf(p, "\n AEC6210 Chipset.\n"); if (timing->udma)
break; t |= (5 - FIT(timing->udma, 2, 4)) << (dn << 1);
case PCI_DEVICE_ID_ARTOP_ATP860: pci_write_config_byte(dev, AEC_UDMA_OLD, t);
p += sprintf(p, "\n AEC6260 No Bios Chipset.\n");
break;
case PCI_DEVICE_ID_ARTOP_ATP860R:
p += sprintf(p, "\n AEC6260 Chipset.\n");
break;
case PCI_DEVICE_ID_ARTOP_ATP865:
p += sprintf(p, "\n AEC6280 Chipset without ROM.\n");
break;
case PCI_DEVICE_ID_ARTOP_ATP865R:
p += sprintf(p, "\n AEC6280 Chipset with ROM.\n");
break;
default:
p += sprintf(p, "\n AEC62?? Chipset.\n");
break;
}
/*
* at that point bibma+0x2 et bibma+0xa are byte registers
* to investigate:
*/
c0 = inb_p((unsigned short)bibma + 0x02);
c1 = inb_p((unsigned short)bibma + 0x0a);
p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
(void) pci_read_config_byte(bmide_dev, 0x4a, &art);
p += sprintf(p, " %sabled %sabled\n",
(art&0x02)?" en":"dis",(art&0x04)?" en":"dis");
p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
p += sprintf(p, "DMA enabled: %s %s %s %s\n",
(c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no ");
switch(bmide_dev->device) {
case PCI_DEVICE_ID_ARTOP_ATP850UF:
(void) pci_read_config_byte(bmide_dev, 0x54, &art);
p += sprintf(p, "DMA Mode: %s(%s) %s(%s) %s(%s) %s(%s)\n",
(c0&0x20)?((art&0x03)?"UDMA":" DMA"):" PIO",
(art&0x02)?"2":(art&0x01)?"1":"0",
(c0&0x40)?((art&0x0c)?"UDMA":" DMA"):" PIO",
(art&0x08)?"2":(art&0x04)?"1":"0",
(c1&0x20)?((art&0x30)?"UDMA":" DMA"):" PIO",
(art&0x20)?"2":(art&0x10)?"1":"0",
(c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO",
(art&0x80)?"2":(art&0x40)?"1":"0");
(void) pci_read_config_byte(bmide_dev, 0x40, &art);
p += sprintf(p, "Active: 0x%02x", art);
(void) pci_read_config_byte(bmide_dev, 0x42, &art);
p += sprintf(p, " 0x%02x", art);
(void) pci_read_config_byte(bmide_dev, 0x44, &art);
p += sprintf(p, " 0x%02x", art);
(void) pci_read_config_byte(bmide_dev, 0x46, &art);
p += sprintf(p, " 0x%02x\n", art);
(void) pci_read_config_byte(bmide_dev, 0x41, &art);
p += sprintf(p, "Recovery: 0x%02x", art);
(void) pci_read_config_byte(bmide_dev, 0x43, &art);
p += sprintf(p, " 0x%02x", art);
(void) pci_read_config_byte(bmide_dev, 0x45, &art);
p += sprintf(p, " 0x%02x", art);
(void) pci_read_config_byte(bmide_dev, 0x47, &art);
p += sprintf(p, " 0x%02x\n", art);
break;
case PCI_DEVICE_ID_ARTOP_ATP860:
case PCI_DEVICE_ID_ARTOP_ATP860R:
(void) pci_read_config_byte(bmide_dev, 0x44, &art);
p += sprintf(p, "DMA Mode: %s(%s) %s(%s)",
(c0&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO",
((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((art&0x01)==0x01)?"0":"?",
(c0&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO",
((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((art&0x10)==0x10)?"0":"?");
(void) pci_read_config_byte(bmide_dev, 0x45, &art);
p += sprintf(p, " %s(%s) %s(%s)\n",
(c1&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO",
((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((art&0x01)==0x01)?"0":"?",
(c1&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO",
((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((art&0x10)==0x10)?"0":"?");
(void) pci_read_config_byte(bmide_dev, 0x40, &art);
p += sprintf(p, "Active: 0x%02x", HIGH_4(art));
(void) pci_read_config_byte(bmide_dev, 0x41, &art);
p += sprintf(p, " 0x%02x", HIGH_4(art));
(void) pci_read_config_byte(bmide_dev, 0x42, &art);
p += sprintf(p, " 0x%02x", HIGH_4(art));
(void) pci_read_config_byte(bmide_dev, 0x43, &art);
p += sprintf(p, " 0x%02x\n", HIGH_4(art));
(void) pci_read_config_byte(bmide_dev, 0x40, &art);
p += sprintf(p, "Recovery: 0x%02x", LOW_4(art));
(void) pci_read_config_byte(bmide_dev, 0x41, &art);
p += sprintf(p, " 0x%02x", LOW_4(art));
(void) pci_read_config_byte(bmide_dev, 0x42, &art);
p += sprintf(p, " 0x%02x", LOW_4(art));
(void) pci_read_config_byte(bmide_dev, 0x43, &art);
p += sprintf(p, " 0x%02x\n", LOW_4(art));
(void) pci_read_config_byte(bmide_dev, 0x49, &uart);
p += sprintf(p, "reg49h = 0x%02x ", uart);
(void) pci_read_config_byte(bmide_dev, 0x4a, &uart);
p += sprintf(p, "reg4ah = 0x%02x\n", uart);
break;
case PCI_DEVICE_ID_ARTOP_ATP865:
case PCI_DEVICE_ID_ARTOP_ATP865R:
(void) pci_read_config_byte(bmide_dev, 0x44, &art);
p += sprintf(p, "DMA Mode: %s(%s) %s(%s)",
(c0&0x20)?((art&0x0f)?"UDMA":" DMA"):" PIO",
aec6280_get_speed(art&0x0f),
(c0&0x40)?((art&0xf0)?"UDMA":" DMA"):" PIO",
aec6280_get_speed(art>>4));
(void) pci_read_config_byte(bmide_dev, 0x45, &art);
p += sprintf(p, " %s(%s) %s(%s)\n",
(c0&0x20)?((art&0x0f)?"UDMA":" DMA"):" PIO",
aec6280_get_speed(art&0x0f),
(c0&0x40)?((art&0xf0)?"UDMA":" DMA"):" PIO",
aec6280_get_speed(art>>4));
(void) pci_read_config_byte(bmide_dev, 0x40, &art);
p += sprintf(p, "Active: 0x%02x", HIGH_4(art));
(void) pci_read_config_byte(bmide_dev, 0x41, &art);
p += sprintf(p, " 0x%02x", HIGH_4(art));
(void) pci_read_config_byte(bmide_dev, 0x42, &art);
p += sprintf(p, " 0x%02x", HIGH_4(art));
(void) pci_read_config_byte(bmide_dev, 0x43, &art);
p += sprintf(p, " 0x%02x\n", HIGH_4(art));
(void) pci_read_config_byte(bmide_dev, 0x40, &art);
p += sprintf(p, "Recovery: 0x%02x", LOW_4(art));
(void) pci_read_config_byte(bmide_dev, 0x41, &art);
p += sprintf(p, " 0x%02x", LOW_4(art));
(void) pci_read_config_byte(bmide_dev, 0x42, &art);
p += sprintf(p, " 0x%02x", LOW_4(art));
(void) pci_read_config_byte(bmide_dev, 0x43, &art);
p += sprintf(p, " 0x%02x\n", LOW_4(art));
(void) pci_read_config_byte(bmide_dev, 0x49, &uart);
p += sprintf(p, "reg49h = 0x%02x ", uart);
(void) pci_read_config_byte(bmide_dev, 0x4a, &uart);
p += sprintf(p, "reg4ah = 0x%02x\n", uart);
break;
default:
break;
}
return p-buffer;/* => must be less than 4k! */
} }
#endif /* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */
byte aec62xx_proc = 0; /*
* aec_set_speed_new() writes timing values to the chipset registers for all
struct chipset_bus_clock_list_entry { * other Artop chips
byte xfer_speed; */
byte chipset_settings_34; static void aec_set_speed_new(struct pci_dev *dev, unsigned char dn, struct ata_timing *timing)
byte ultra_settings_34; {
unsigned char t;
byte chipset_settings_33; pci_write_config_byte(dev, AEC_DRIVE_TIMING + dn,
byte ultra_settings_33; (FIT(timing->active, 0, 15) << 4) | FIT(timing->recover, 0, 15));
};
struct chipset_bus_clock_list_entry aec62xx_base [] = { pci_read_config_byte(dev, AEC_UDMA_NEW + (dn >> 1), &t);
#ifdef CONFIG_BLK_DEV_IDEDMA t &= ~(0xf << ((dn & 1) << 2));
{ XFER_UDMA_6, 0x41, 0x06, 0x31, 0x07 }, if (timing->udma)
{ XFER_UDMA_5, 0x41, 0x05, 0x31, 0x06 }, t |= aec_cyc2udma[FIT(timing->udma, 2, 16)] << ((dn & 1) << 2);
{ XFER_UDMA_4, 0x41, 0x04, 0x31, 0x05 }, pci_write_config_byte(dev, AEC_UDMA_NEW + (dn >> 1), t);
{ XFER_UDMA_3, 0x41, 0x03, 0x31, 0x04 }, }
{ XFER_UDMA_2, 0x41, 0x02, 0x31, 0x03 },
{ XFER_UDMA_1, 0x41, 0x01, 0x31, 0x02 },
{ XFER_UDMA_0, 0x41, 0x01, 0x31, 0x01 },
{ XFER_MW_DMA_2, 0x41, 0x00, 0x31, 0x00 },
{ XFER_MW_DMA_1, 0x42, 0x00, 0x31, 0x00 },
{ XFER_MW_DMA_0, 0x7a, 0x00, 0x0a, 0x00 },
#endif /* CONFIG_BLK_DEV_IDEDMA */
{ XFER_PIO_4, 0x41, 0x00, 0x31, 0x00 },
{ XFER_PIO_3, 0x43, 0x00, 0x33, 0x00 },
{ XFER_PIO_2, 0x78, 0x00, 0x08, 0x00 },
{ XFER_PIO_1, 0x7a, 0x00, 0x0a, 0x00 },
{ XFER_PIO_0, 0x70, 0x00, 0x00, 0x00 },
{ 0, 0x00, 0x00, 0x00, 0x00 }
};
/* /*
* TO DO: active tuning and correction of cards without a bios. * aec_set_drive() computes timing values configures the drive and
* the chipset to a desired transfer mode. It also can be called
* by upper layers.
*/ */
static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) static int aec_set_drive(struct ata_device *drive, unsigned char speed)
{
for ( ; chipset_table->xfer_speed ; chipset_table++)
if (chipset_table->xfer_speed == speed) {
return ((byte) ((system_bus_speed <= 33333) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34));
}
return 0x00;
}
static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
{ {
for ( ; chipset_table->xfer_speed ; chipset_table++) struct ata_timing t;
if (chipset_table->xfer_speed == speed) { int T, UT;
return ((byte) ((system_bus_speed <= 33333) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34)); int aec_old;
}
return 0x00;
}
static int aec62xx_ratemask(struct ata_device *drive) aec_old = (drive->channel->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF);
{
struct pci_dev *dev = drive->channel->pci_dev;
u32 bmide = pci_resource_start(dev, 4);
int map = 0;
if (!eighty_ninty_three(drive)) if (speed != XFER_PIO_SLOW && speed != drive->current_speed)
return XFER_UDMA; if (ide_config_drive_speed(drive, speed))
printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n",
drive->dn >> 1, drive->dn & 1);
switch(dev->device) { T = 1000000000 / system_bus_speed;
case PCI_DEVICE_ID_ARTOP_ATP865R: UT = T / (aec_old ? 1 : 4);
case PCI_DEVICE_ID_ARTOP_ATP865:
if (IN_BYTE(bmide+2) & 0x10)
map |= XFER_UDMA_133;
else
map |= XFER_UDMA_100;
case PCI_DEVICE_ID_ARTOP_ATP860R:
case PCI_DEVICE_ID_ARTOP_ATP860:
map |= XFER_UDMA_66;
case PCI_DEVICE_ID_ARTOP_ATP850UF:
map |= XFER_UDMA;
}
return map;
}
static int aec6210_tune_chipset(struct ata_device *drive, byte speed) ata_timing_compute(drive, speed, &t, T, UT);
{
struct pci_dev *dev = drive->channel->pci_dev;
unsigned short d_conf = 0x0000;
byte ultra = 0x00;
byte ultra_conf = 0x00;
byte tmp0 = 0x00;
byte tmp1 = 0x00;
byte tmp2 = 0x00;
unsigned long flags;
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */
pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
tmp0 = pci_bus_clock_list(speed, aec62xx_base);
SPLIT_BYTE(tmp0,tmp1,tmp2);
MAKE_WORD(d_conf,tmp1,tmp2);
pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf);
tmp1 = 0x00;
tmp2 = 0x00;
pci_read_config_byte(dev, 0x54, &ultra);
tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn))));
ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base);
tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
pci_write_config_byte(dev, 0x54, tmp2);
__restore_flags(flags); /* local CPU only */
return ide_config_drive_speed(drive, speed);
}
static int aec6260_tune_chipset(struct ata_device *drive, byte speed) if (aec_old)
{ aec_set_speed_old(drive->channel->pci_dev, drive->dn, &t);
struct pci_dev *dev = drive->channel->pci_dev; else
byte unit = (drive->select.b.unit & 0x01); aec_set_speed_new(drive->channel->pci_dev, drive->dn, &t);
u8 ultra_pci = drive->channel->unit ? 0x45 : 0x44;
byte drive_conf = 0x00;
byte ultra_conf = 0x00;
byte ultra = 0x00;
byte tmp1 = 0x00;
byte tmp2 = 0x00;
unsigned long flags;
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */
pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
drive_conf = pci_bus_clock_list(speed, aec62xx_base);
pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
pci_read_config_byte(dev, ultra_pci, &ultra);
tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base);
tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
pci_write_config_byte(dev, ultra_pci, tmp2);
__restore_flags(flags); /* local CPU only */
if (!drive->init_speed) if (!drive->init_speed)
drive->init_speed = speed; drive->init_speed = speed;
drive->current_speed = speed; drive->current_speed = speed;
return ide_config_drive_speed(drive, speed);
return 0;
} }
/*
* aec62xx_tune_drive() is a callback from upper layers for
* PIO-only tuning.
*/
static int aec62xx_tune_chipset(struct ata_device *drive, byte speed) static void aec62xx_tune_drive(struct ata_device *drive, unsigned char pio)
{ {
switch (drive->channel->pci_dev->device) { if (pio == 255) {
case PCI_DEVICE_ID_ARTOP_ATP865: aec_set_drive(drive, ata_timing_mode(drive, XFER_PIO | XFER_EPIO));
case PCI_DEVICE_ID_ARTOP_ATP865R: return;
case PCI_DEVICE_ID_ARTOP_ATP860:
case PCI_DEVICE_ID_ARTOP_ATP860R:
return aec6260_tune_chipset(drive, speed);
case PCI_DEVICE_ID_ARTOP_ATP850UF:
return aec6210_tune_chipset(drive, speed);
default:
return -1;
} }
aec_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
} }
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
static int config_chipset_for_dma(struct ata_device *drive, u8 udma) static int aec62xx_dmaproc(struct ata_device *drive)
{ {
short speed;
int map; int map;
u8 mode;
if (drive->type != ATA_DISK) map = XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA | XFER_SWDMA | XFER_UDMA;
return 0;
if (udma) if (drive->channel->udma_four)
map = aec62xx_ratemask(drive); switch (drive->channel->pci_dev->device) {
else case PCI_DEVICE_ID_ARTOP_ATP865R:
map = XFER_SWDMA | XFER_MWDMA; case PCI_DEVICE_ID_ARTOP_ATP865:
map |= XFER_UDMA_100 | XFER_UDMA_133;
case PCI_DEVICE_ID_ARTOP_ATP860R:
case PCI_DEVICE_ID_ARTOP_ATP860:
map |= XFER_UDMA_66;
}
mode = ata_timing_mode(drive, map); speed = ata_timing_mode(drive, map);
aec_set_drive(drive, speed);
udma_enable(drive, drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO, 0);
if (mode < XFER_SW_DMA_0)
return 0; return 0;
return !aec62xx_tune_chipset(drive, mode);
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif
static void aec62xx_tune_drive(struct ata_device *drive, byte pio)
{
byte speed;
if (pio == 255)
speed = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
else
speed = XFER_PIO_0 + min_t(byte, pio, 4);
(void) aec62xx_tune_chipset(drive, speed); /*
} * The initialization callback. Here we determine the IDE chip type
* and initialize its drive independent registers.
*/
#ifdef CONFIG_BLK_DEV_IDEDMA static unsigned int __init aec62xx_init_chipset(struct pci_dev *dev)
static int config_drive_xfer_rate(struct ata_device *drive)
{ {
struct hd_driveid *id = drive->id; unsigned char t;
int on = 1;
int verbose = 1;
if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */
if (udma_black_list(drive)) {
on = 0;
goto fast_ata_pio;
}
on = 0;
verbose = 0;
if (id->field_valid & 4) {
if (id->dma_ultra & 0x007F) {
/* Force if Capable UltraDMA */
on = config_chipset_for_dma(drive, 1);
if ((id->field_valid & 2) &&
(!on))
goto try_dma_modes;
}
} else if (id->field_valid & 2) {
try_dma_modes:
if ((id->dma_mword & 0x0007) ||
(id->dma_1word & 0x0007)) {
/* Force if Capable regular DMA modes */
on = config_chipset_for_dma(drive, 0);
if (!on)
goto no_dma_set;
}
} else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) {
goto no_dma_set;
}
/* Consult the list of known "good" drives */
on = config_chipset_for_dma(drive, 0);
if (!on)
goto no_dma_set;
} else {
goto fast_ata_pio;
}
} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
on = 0;
verbose = 0;
no_dma_set:
aec62xx_tune_drive(drive, 5);
}
udma_enable(drive, on, verbose);
return 0;
}
int aec62xx_dmaproc(struct ata_device *drive) /*
{ * Initialize if needed.
return config_drive_xfer_rate(drive); */
}
#endif
static unsigned int __init aec62xx_init_chipset(struct pci_dev *dev) switch (dev->device) {
{
u8 reg49h = 0;
u8 reg4ah = 0;
switch(dev->device) {
case PCI_DEVICE_ID_ARTOP_ATP865:
case PCI_DEVICE_ID_ARTOP_ATP865R: case PCI_DEVICE_ID_ARTOP_ATP865R:
case PCI_DEVICE_ID_ARTOP_ATP865:
/* Clear reset and test bits. */ /* Clear reset and test bits. */
pci_read_config_byte(dev, 0x49, &reg49h); pci_read_config_byte(dev, AEC_MISC, &t);
pci_write_config_byte(dev, 0x49, reg49h & ~0x30); pci_write_config_byte(dev, AEC_MISC, t & ~0x30);
/* Enable chip interrupt output. */ /* Enable chip interrupt output. */
pci_read_config_byte(dev, 0x4a, &reg4ah); pci_read_config_byte(dev, AEC_IDE_ENABLE, &t);
pci_write_config_byte(dev, 0x4a, reg4ah & ~0x01); pci_write_config_byte(dev, AEC_IDE_ENABLE, t & ~0x01);
#ifdef CONFIG_AEC6280_BURST #ifdef CONFIG_AEC6280_BURST
/* Must be greater than 0x80 for burst mode. */ /* Must be greater than 0x80 for burst mode. */
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x90); pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x90);
/* Enable burst mode. */ /* Enable burst mode. */
pci_read_config_byte(dev, 0x4a, &reg4ah); pci_read_config_byte(dev, AEC_IDE_ENABLE, &t);
pci_write_config_byte(dev, 0x4a, reg4ah | 0x80); pci_write_config_byte(dev, AEC_IDE_ENABLE, t | 0x80);
#endif #endif
break;
default:
break;
} }
if (dev->resource[PCI_ROM_RESOURCE].start) { /*
pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); * Print the boot message.
printk("%s: ROM enabled at 0x%08lx\n", dev->name, dev->resource[PCI_ROM_RESOURCE].start); */
}
#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) pci_read_config_byte(dev, PCI_REVISION_ID, &t);
if (!aec62xx_proc) { printk(KERN_INFO "AEC_IDE: %s (rev %02x) controller on pci%s\n",
aec62xx_proc = 1; dev->name, t, dev->slot_name);
bmide_dev = dev;
aec62xx_display_info = &aec62xx_get_info;
}
#endif
return dev->irq; return 0;
} }
static unsigned int __init aec62xx_ata66_check(struct ata_channel *ch) static unsigned int __init aec62xx_ata66_check(struct ata_channel *ch)
{ {
u8 mask = ch->unit ? 0x02 : 0x01; unsigned char t;
u8 ata66 = 0;
pci_read_config_byte(ch->pci_dev, 0x49, &ata66); if (ch->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
return 0;
return ((ata66 & mask) ? 0 : 1); pci_read_config_byte(ch->pci_dev, AEC_MISC, &t);
return ((t & (1 << ch->unit)) ? 0 : 1);
} }
static void __init aec62xx_init_channel(struct ata_channel *hwif) static void __init aec62xx_init_channel(struct ata_channel *ch)
{ {
hwif->tuneproc = aec62xx_tune_drive; int i;
hwif->speedproc = aec62xx_tune_chipset;
hwif->drives[0].autotune = 1; ch->tuneproc = &aec62xx_tune_drive;
hwif->drives[1].autotune = 1; ch->speedproc = &aec_set_drive;
ch->autodma = 0;
ch->io_32bit = 1;
ch->unmask = 1;
for (i = 0; i < 2; i++) {
ch->drives[i].autotune = 1;
ch->drives[i].dn = ch->unit * 2 + i;
}
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) { if (ch->dma_base) {
hwif->XXX_udma = aec62xx_dmaproc; ch->highmem = 1;
hwif->highmem = 1; ch->XXX_udma = aec62xx_dmaproc;
# ifdef CONFIG_IDEDMA_AUTO #ifdef CONFIG_IDEDMA_AUTO
if (!noautodma) if (!noautodma)
hwif->autodma = 1; ch->autodma = 1;
# endif #endif
} }
#endif #endif
} }
static void __init aec62xx_init_dma(struct ata_channel *hwif, unsigned long dmabase) /*
* We allow the BM-DMA driver only work on enabled interfaces.
*/
static void __init aec62xx_init_dma(struct ata_channel *ch, unsigned long dmabase)
{ {
u8 reg54h = 0; unsigned char t;
/* FIXME: we need some locking here */ pci_read_config_byte(ch->pci_dev, AEC_IDE_ENABLE, &t);
pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h); if (t & (1 << ((ch->unit << 1) + 2)))
pci_write_config_byte(hwif->pci_dev, 0x54, reg54h & ~(hwif->unit ? 0xF0 : 0x0F)); ata_init_dma(ch, dmabase);
ata_init_dma(hwif, dmabase);
} }
/* module data table */ /* module data table */
...@@ -574,7 +288,7 @@ static struct ata_pci_device chipsets[] __initdata = { ...@@ -574,7 +288,7 @@ static struct ata_pci_device chipsets[] __initdata = {
init_chipset: aec62xx_init_chipset, init_chipset: aec62xx_init_chipset,
ata66_check: aec62xx_ata66_check, ata66_check: aec62xx_ata66_check,
init_channel: aec62xx_init_channel, init_channel: aec62xx_init_channel,
enablebits: { {0x00,0x00,0x00}, {0x00,0x00,0x00} }, enablebits: { {0x4a,0x02,0x02}, {0x4a,0x04,0x04} },
bootable: NEVER_BOARD, bootable: NEVER_BOARD,
flags: ATA_F_IRQ | ATA_F_NOADMA | ATA_F_DMA flags: ATA_F_IRQ | ATA_F_NOADMA | ATA_F_DMA
}, },
...@@ -594,7 +308,7 @@ static struct ata_pci_device chipsets[] __initdata = { ...@@ -594,7 +308,7 @@ static struct ata_pci_device chipsets[] __initdata = {
init_chipset: aec62xx_init_chipset, init_chipset: aec62xx_init_chipset,
ata66_check: aec62xx_ata66_check, ata66_check: aec62xx_ata66_check,
init_channel: aec62xx_init_channel, init_channel: aec62xx_init_channel,
enablebits: { {0x00,0x00,0x00}, {0x00,0x00,0x00} }, enablebits: { {0x4a,0x02,0x02}, {0x4a,0x04,0x04} },
bootable: NEVER_BOARD, bootable: NEVER_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA flags: ATA_F_IRQ | ATA_F_DMA
}, },
...@@ -604,7 +318,7 @@ static struct ata_pci_device chipsets[] __initdata = { ...@@ -604,7 +318,7 @@ static struct ata_pci_device chipsets[] __initdata = {
init_chipset: aec62xx_init_chipset, init_chipset: aec62xx_init_chipset,
ata66_check: aec62xx_ata66_check, ata66_check: aec62xx_ata66_check,
init_channel: aec62xx_init_channel, init_channel: aec62xx_init_channel,
enablebits: { {0x00,0x00,0x00}, {0x00,0x00,0x00} }, enablebits: { {0x4a,0x02,0x02}, {0x4a,0x04,0x04} },
bootable: OFF_BOARD, bootable: OFF_BOARD,
flags: ATA_F_IRQ | ATA_F_DMA flags: ATA_F_IRQ | ATA_F_DMA
} }
...@@ -614,9 +328,8 @@ int __init init_aec62xx(void) ...@@ -614,9 +328,8 @@ int __init init_aec62xx(void)
{ {
int i; int i;
for (i = 0; i < ARRAY_SIZE(chipsets); ++i) { for (i = 0; i < ARRAY_SIZE(chipsets); i++)
ata_register_chipset(&chipsets[i]); ata_register_chipset(chipsets + i);
}
return 0; return 0;
} }
...@@ -37,6 +37,21 @@ ...@@ -37,6 +37,21 @@
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
/*
* Initializes a packet command. Used by tape and floppy driver.
*/
void atapi_init_pc(struct atapi_packet_command *pc)
{
memset(pc->c, 0, 12);
pc->retries = 0;
pc->flags = 0;
pc->request_transfer = 0;
pc->buffer = pc->pc_buffer;
pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE;
pc->b_data = NULL;
pc->bio = NULL;
}
/* /*
* Too bad. The drive wants to send us data which we are not ready to accept. * Too bad. The drive wants to send us data which we are not ready to accept.
* Just throw it away. * Just throw it away.
...@@ -54,22 +69,57 @@ void atapi_write_zeros(struct ata_device *drive, unsigned int bcount) ...@@ -54,22 +69,57 @@ void atapi_write_zeros(struct ata_device *drive, unsigned int bcount)
} }
/* /*
* Initializes a packet command. Used by tape and floppy driver. * The following routines are mainly used by the ATAPI drivers.
*
* These routines will round up any request for an odd number of bytes, so if
* an odd n is specified, be sure that there's at least one extra byte
* allocated for the buffer.
*/ */
void atapi_init_pc(struct atapi_packet_command *pc) void atapi_read(struct ata_device *drive, u8 *buf, unsigned int n)
{ {
memset(pc->c, 0, 12); if (drive->channel->atapi_read) {
pc->retries = 0; drive->channel->atapi_read(drive, buf, n);
pc->flags = 0; return;
pc->request_transfer = 0; }
pc->buffer = pc->pc_buffer;
pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE; ++n;
pc->b_data = NULL; #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
pc->bio = NULL; if (MACH_IS_ATARI || MACH_IS_Q40) {
/* Atari has a byte-swapped IDE interface */
insw_swapw(IDE_DATA_REG, buf, n / 2);
return;
}
#endif
ata_read(drive, buf, n / 4);
if ((n & 0x03) >= 2)
insw(IDE_DATA_REG, buf + (n & ~0x03), 1);
}
void atapi_write(struct ata_device *drive, u8 *buf, unsigned int n)
{
if (drive->channel->atapi_write) {
drive->channel->atapi_write(drive, buf, n);
return;
}
++n;
#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
if (MACH_IS_ATARI || MACH_IS_Q40) {
/* Atari has a byte-swapped IDE interface */
outsw_swapw(IDE_DATA_REG, buf, n / 2);
return;
}
#endif
ata_write(drive, buf, n / 4);
if ((n & 0x03) >= 2)
outsw(IDE_DATA_REG, buf + (n & ~0x03), 1);
} }
EXPORT_SYMBOL(atapi_discard_data); EXPORT_SYMBOL(atapi_discard_data);
EXPORT_SYMBOL(atapi_write_zeros); EXPORT_SYMBOL(atapi_write_zeros);
EXPORT_SYMBOL(atapi_init_pc); EXPORT_SYMBOL(atapi_init_pc);
EXPORT_SYMBOL(atapi_read);
EXPORT_SYMBOL(atapi_write);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -314,6 +314,7 @@ ...@@ -314,6 +314,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/atapi.h>
#include "ide-cd.h" #include "ide-cd.h"
/**************************************************************************** /****************************************************************************
...@@ -2988,7 +2989,7 @@ static void ide_cdrom_attach(struct ata_device *drive) ...@@ -2988,7 +2989,7 @@ static void ide_cdrom_attach(struct ata_device *drive)
channel = drive->channel; channel = drive->channel;
unit = drive - channel->drives; unit = drive - channel->drives;
ide_revalidate_disk(mk_kdev(channel->major, unit << PARTN_BITS)); ata_revalidate(mk_kdev(channel->major, unit << PARTN_BITS));
} }
MODULE_PARM(ignore, "s"); MODULE_PARM(ignore, "s");
......
...@@ -361,8 +361,8 @@ static int idedisk_open (struct inode *inode, struct file *filp, struct ata_devi ...@@ -361,8 +361,8 @@ static int idedisk_open (struct inode *inode, struct file *filp, struct ata_devi
/* /*
* Ignore the return code from door_lock, since the open() has * Ignore the return code from door_lock, since the open() has
* already succeeded, and the door_lock is irrelevant at this * already succeeded once, and the door_lock is irrelevant at this
* point. * time.
*/ */
if (drive->doorlocking && ide_raw_taskfile(drive, &args)) if (drive->doorlocking && ide_raw_taskfile(drive, &args))
...@@ -1196,7 +1196,7 @@ static void idedisk_attach(struct ata_device *drive) ...@@ -1196,7 +1196,7 @@ static void idedisk_attach(struct ata_device *drive)
channel = drive->channel; channel = drive->channel;
unit = drive - channel->drives; unit = drive - channel->drives;
ide_revalidate_disk(mk_kdev(channel->major, unit << PARTN_BITS)); ata_revalidate(mk_kdev(channel->major, unit << PARTN_BITS));
} }
static void __exit idedisk_exit(void) static void __exit idedisk_exit(void)
......
...@@ -2036,7 +2036,7 @@ static void idefloppy_attach(struct ata_device *drive) ...@@ -2036,7 +2036,7 @@ static void idefloppy_attach(struct ata_device *drive)
channel = drive->channel; channel = drive->channel;
unit = drive - channel->drives; unit = drive - channel->drives;
ide_revalidate_disk(mk_kdev(channel->major, unit << PARTN_BITS)); ata_revalidate(mk_kdev(channel->major, unit << PARTN_BITS));
} }
MODULE_DESCRIPTION("ATAPI FLOPPY Driver"); MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
......
...@@ -27,10 +27,6 @@ ...@@ -27,10 +27,6 @@
#include "pcihost.h" #include "pcihost.h"
/* Missing PCI device IDs: */
#define PCI_VENDOR_ID_HINT 0x3388
#define PCI_DEVICE_ID_HINT 0x8013
/* /*
* This is the list of registered PCI chipset driver data structures. * This is the list of registered PCI chipset driver data structures.
*/ */
...@@ -756,7 +752,7 @@ static struct ata_pci_device chipsets[] __initdata = { ...@@ -756,7 +752,7 @@ static struct ata_pci_device chipsets[] __initdata = {
}, },
{ {
vendor: PCI_VENDOR_ID_HINT, vendor: PCI_VENDOR_ID_HINT,
device: PCI_DEVICE_ID_HINT, device: PCI_DEVICE_ID_HINT_VXPROII_IDE,
bootable: ON_BOARD bootable: ON_BOARD
}, },
{ {
......
/* /**** vi:set ts=8 sts=8 sw=8:************************************************
* linux/drivers/ide/ide-pnp.c
* *
* This file provides autodetection for ISA PnP IDE interfaces. * This file provides autodetection for ISA PnP IDE interfaces.
* It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface. * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface.
...@@ -33,19 +32,27 @@ ...@@ -33,19 +32,27 @@
#define DEV_NAME(dev) (dev->bus->name ? dev->bus->name : "ISA PnP") #define DEV_NAME(dev) (dev->bus->name ? dev->bus->name : "ISA PnP")
#define GENERIC_HD_DATA 0 enum {
#define GENERIC_HD_ERROR 1 GENERIC_HD_DATA,
#define GENERIC_HD_NSECTOR 2 GENERIC_HD_ERROR,
#define GENERIC_HD_SECTOR 3 GENERIC_HD_NSECTOR,
#define GENERIC_HD_LCYL 4 GENERIC_HD_SECTOR,
#define GENERIC_HD_HCYL 5 GENERIC_HD_LCYL,
#define GENERIC_HD_SELECT 6 GENERIC_HD_HCYL,
#define GENERIC_HD_STATUS 7 GENERIC_HD_SELECT,
GENERIC_HD_STATUS
};
static int generic_ide_offsets[IDE_NR_PORTS] __initdata = { static int generic_ide_offsets[IDE_NR_PORTS] __initdata = {
GENERIC_HD_DATA, GENERIC_HD_ERROR, GENERIC_HD_NSECTOR, GENERIC_HD_DATA,
GENERIC_HD_SECTOR, GENERIC_HD_LCYL, GENERIC_HD_HCYL, GENERIC_HD_ERROR,
GENERIC_HD_SELECT, GENERIC_HD_STATUS, -1, -1 GENERIC_HD_NSECTOR,
GENERIC_HD_SECTOR,
GENERIC_HD_LCYL,
GENERIC_HD_HCYL,
GENERIC_HD_SELECT,
GENERIC_HD_STATUS,
-1, -1
}; };
/* ISA PnP device table entry */ /* ISA PnP device table entry */
...@@ -83,11 +90,13 @@ static int __init pnpide_generic_init(struct pci_dev *dev, int enable) ...@@ -83,11 +90,13 @@ static int __init pnpide_generic_init(struct pci_dev *dev, int enable)
} }
/* Add your devices here :)) */ /* Add your devices here :)) */
struct pnp_dev_t idepnp_devices[] __initdata = { static struct pnp_dev_t pnp_devices[] __initdata = {
/* Generic ESDI/IDE/ATA compatible hard disk controller */ /* Generic ESDI/IDE/ATA compatible hard disk controller */
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, {
ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0600), ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0600),
pnpide_generic_init }, pnpide_generic_init
},
{ 0 } { 0 }
}; };
...@@ -125,7 +134,7 @@ void __init pnpide_init(int enable) ...@@ -125,7 +134,7 @@ void __init pnpide_init(int enable)
return; return;
} }
#endif #endif
for (dev_type = idepnp_devices; dev_type->vendor; dev_type++) { for (dev_type = pnp_devices; dev_type->vendor; dev_type++) {
while ((dev = isapnp_find_dev(NULL, dev_type->vendor, while ((dev = isapnp_find_dev(NULL, dev_type->vendor,
dev_type->device, dev))) { dev_type->device, dev))) {
......
...@@ -2806,9 +2806,14 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, ...@@ -2806,9 +2806,14 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full,
if (clear) if (clear)
memset(bio_data(bio), 0, PAGE_SIZE); memset(bio_data(bio), 0, PAGE_SIZE);
bio->bi_size = PAGE_SIZE; bio->bi_size = PAGE_SIZE;
if(bv->bv_len == full) bv->bv_len = bio->bi_size; if(bv->bv_len == full)
set_bit (BH_Lock, &bio->bi_flags); bv->bv_len = bio->bi_size;
#if 0
/* FIXME: What what this supposed to achieve? */
set_bit (BH_Lock, &bio->bi_flags);
#endif
while (--pages) { while (--pages) {
if ((bio->bi_io_vec[pages].bv_page = alloc_page(GFP_KERNEL)) == NULL) if ((bio->bi_io_vec[pages].bv_page = alloc_page(GFP_KERNEL)) == NULL)
goto abort; goto abort;
...@@ -2837,7 +2842,11 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, ...@@ -2837,7 +2842,11 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full,
//bio->bi_io_vec[0].bv_offset = b_data; //bio->bi_io_vec[0].bv_offset = b_data;
bio->bi_size = PAGE_SIZE; bio->bi_size = PAGE_SIZE;
atomic_set(&bio->bi_cnt, full ? bio->bi_size : 0); atomic_set(&bio->bi_cnt, full ? bio->bi_size : 0);
#if 0
/* FIXME: What what this supposed to achieve? */
set_bit (BH_Lock, &bio->bi_flags); set_bit (BH_Lock, &bio->bi_flags);
#endif
prev_bio->bi_next = bio; prev_bio->bi_next = bio;
} }
bio->bi_size -= tape->excess_bh_size; bio->bi_size -= tape->excess_bh_size;
...@@ -6153,7 +6162,7 @@ static void idetape_attach(struct ata_device *drive) ...@@ -6153,7 +6162,7 @@ static void idetape_attach(struct ata_device *drive)
channel = drive->channel; channel = drive->channel;
unit = drive - channel->drives; unit = drive - channel->drives;
ide_revalidate_disk(mk_kdev(channel->major, unit << PARTN_BITS)); ata_revalidate(mk_kdev(channel->major, unit << PARTN_BITS));
} }
MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver"); MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
......
...@@ -160,53 +160,6 @@ void ata_write(struct ata_device *drive, void *buffer, unsigned int wcount) ...@@ -160,53 +160,6 @@ void ata_write(struct ata_device *drive, void *buffer, unsigned int wcount)
} }
} }
/*
* The following routines are mainly used by the ATAPI drivers.
*
* These routines will round up any request for an odd number of bytes,
* so if an odd bytecount is specified, be sure that there's at least one
* extra byte allocated for the buffer.
*/
void atapi_read(struct ata_device *drive, void *buffer, unsigned int bytecount)
{
if (drive->channel->atapi_read) {
drive->channel->atapi_read(drive, buffer, bytecount);
return;
}
++bytecount;
#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
if (MACH_IS_ATARI || MACH_IS_Q40) {
/* Atari has a byte-swapped IDE interface */
insw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
return;
}
#endif
ata_read(drive, buffer, bytecount / 4);
if ((bytecount & 0x03) >= 2)
insw(IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
}
void atapi_write(struct ata_device *drive, void *buffer, unsigned int bytecount)
{
if (drive->channel->atapi_write) {
drive->channel->atapi_write(drive, buffer, bytecount);
return;
}
++bytecount;
#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
if (MACH_IS_ATARI || MACH_IS_Q40) {
/* Atari has a byte-swapped IDE interface */
outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
return;
}
#endif
ata_write(drive, buffer, bytecount / 4);
if ((bytecount & 0x03) >= 2)
outsw(IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
}
/* /*
* Needed for PCI irq sharing * Needed for PCI irq sharing
*/ */
...@@ -1032,8 +985,6 @@ int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg) ...@@ -1032,8 +985,6 @@ int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg)
EXPORT_SYMBOL(drive_is_ready); EXPORT_SYMBOL(drive_is_ready);
EXPORT_SYMBOL(ata_read); EXPORT_SYMBOL(ata_read);
EXPORT_SYMBOL(ata_write); EXPORT_SYMBOL(ata_write);
EXPORT_SYMBOL(atapi_read);
EXPORT_SYMBOL(atapi_write);
EXPORT_SYMBOL(ata_taskfile); EXPORT_SYMBOL(ata_taskfile);
EXPORT_SYMBOL(recal_intr); EXPORT_SYMBOL(recal_intr);
EXPORT_SYMBOL(task_no_data_intr); EXPORT_SYMBOL(task_no_data_intr);
......
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
* Some additional driver compile-time options are in <linux/ide.h> * Some additional driver compile-time options are in <linux/ide.h>
*/ */
#define VERSION "7.0.0"
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -67,163 +65,11 @@ ...@@ -67,163 +65,11 @@
#include "ata-timing.h" #include "ata-timing.h"
#include "pcihost.h" #include "pcihost.h"
#include "ioctl.h"
MODULE_DESCRIPTION("ATA/ATAPI driver infrastructure");
MODULE_PARM(options,"s");
MODULE_LICENSE("GPL");
/*
* Those will be moved into separate header files eventually.
*/
#ifdef CONFIG_ETRAX_IDE
extern void init_e100_ide(void);
#endif
#ifdef CONFIG_BLK_DEV_CMD640
extern void ide_probe_for_cmd640x(void);
#endif
#ifdef CONFIG_BLK_DEV_PDC4030
extern int ide_probe_for_pdc4030(void);
#endif
#ifdef CONFIG_BLK_DEV_IDE_PMAC
extern void pmac_ide_probe(void);
#endif
#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
extern void icside_init(void);
#endif
#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
extern void rapide_init(void);
#endif
#ifdef CONFIG_BLK_DEV_GAYLE
extern void gayle_init(void);
#endif
#ifdef CONFIG_BLK_DEV_FALCON_IDE
extern void falconide_init(void);
#endif
#ifdef CONFIG_BLK_DEV_MAC_IDE
extern void macide_init(void);
#endif
#ifdef CONFIG_BLK_DEV_Q40IDE
extern void q40ide_init(void);
#endif
#ifdef CONFIG_BLK_DEV_BUDDHA
extern void buddha_init(void);
#endif
#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP)
extern void pnpide_init(int);
#endif
/* default maximum number of failures */ /* default maximum number of failures */
#define IDE_DEFAULT_MAX_FAILURES 1 #define IDE_DEFAULT_MAX_FAILURES 1
static int idebus_parameter; /* holds the "idebus=" parameter */
int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
static int initializing; /* set while initializing built-in drivers */
/*
* Protects access to global structures etc.
*/
spinlock_t ide_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
#ifdef CONFIG_PCI
static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
#endif
#if defined(__mc68000__) || defined(CONFIG_APUS)
/*
* This is used by the Atari code to obtain access to the IDE interrupt,
* which is shared between several drivers.
*/
static int irq_lock;
#endif
int noautodma = 0;
/* Single linked list of sub device type drivers */
static struct ata_operations *ata_drivers; /* = NULL */
static spinlock_t ata_drivers_lock = SPIN_LOCK_UNLOCKED;
/*
* This is declared extern in ide.h, for access by other IDE modules:
*/
struct ata_channel ide_hwifs[MAX_HWIFS]; /* master data repository */
static void init_hwif_data(struct ata_channel *ch, unsigned int index)
{
static const byte ide_major[] = {
IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR,
IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR
};
unsigned int unit;
hw_regs_t hw;
/* bulk initialize channel & drive info with zeros */
memset(ch, 0, sizeof(struct ata_channel));
memset(&hw, 0, sizeof(hw_regs_t));
/* fill in any non-zero initial values */
ch->index = index;
ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &ch->irq);
memcpy(&ch->hw, &hw, sizeof(hw));
memcpy(ch->io_ports, hw.io_ports, sizeof(hw.io_ports));
ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET];
#ifdef CONFIG_BLK_DEV_HD
if (ch->io_ports[IDE_DATA_OFFSET] == HD_DATA)
ch->noprobe = 1; /* may be overridden by ide_setup() */
#endif
ch->major = ide_major[index];
sprintf(ch->name, "ide%d", index);
ch->bus_state = BUSSTATE_ON;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &ch->drives[unit];
drive->type = ATA_DISK;
drive->select.all = (unit<<4)|0xa0;
drive->channel = ch;
drive->ctl = 0x08;
drive->ready_stat = READY_STAT;
drive->bad_wstat = BAD_W_STAT;
sprintf(drive->name, "hd%c", 'a' + (index * MAX_DRIVES) + unit);
drive->max_failures = IDE_DEFAULT_MAX_FAILURES;
init_waitqueue_head(&drive->wqueue);
}
}
/*
* init_ide_data() sets reasonable default values into all fields
* of all instances of the hwifs and drives, but only on the first call.
* Subsequent calls have no effect (they don't wipe out anything).
*
* This routine is normally called at driver initialization time,
* but may also be called MUCH earlier during kernel "command-line"
* parameter processing. As such, we cannot depend on any other parts
* of the kernel (such as memory allocation) to be functioning yet.
*
* This is too bad, as otherwise we could dynamically allocate the
* ata_device structs as needed, rather than always consuming memory
* for the max possible number (MAX_HWIFS * MAX_DRIVES) of them.
*/
#define MAGIC_COOKIE 0x12345678
static void __init init_ide_data (void)
{
unsigned int h;
static unsigned long magic_cookie = MAGIC_COOKIE;
if (magic_cookie != MAGIC_COOKIE)
return; /* already initialized */
magic_cookie = 0;
/* Initialize all interface structures */
for (h = 0; h < MAX_HWIFS; ++h)
init_hwif_data(&ide_hwifs[h], h);
/* Add default hw interfaces */
ide_init_default_hwifs();
}
/* /*
* CompactFlash cards and their relatives pretend to be removable hard disks, except: * CompactFlash cards and their relatives pretend to be removable hard disks, except:
* (1) they never have a slave unit, and * (1) they never have a slave unit, and
...@@ -396,31 +242,6 @@ sector_t ata_capacity(struct ata_device *drive) ...@@ -396,31 +242,6 @@ sector_t ata_capacity(struct ata_device *drive)
extern struct block_device_operations ide_fops[]; extern struct block_device_operations ide_fops[];
/*
* This is called exactly *once* for each channel.
*/
void ide_geninit(struct ata_channel *ch)
{
unsigned int unit;
struct gendisk *gd = ch->gd;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &ch->drives[unit];
if (!drive->present)
continue;
if (drive->type != ATA_DISK && drive->type != ATA_FLOPPY)
continue;
register_disk(gd,mk_kdev(ch->major,unit<<PARTN_BITS),
#ifdef CONFIG_BLK_DEV_ISAPNP
(drive->forced_geom && drive->noprobe) ? 1 :
#endif
1 << PARTN_BITS, ide_fops, ata_capacity(drive));
}
}
static ide_startstop_t do_reset1(struct ata_device *, int); /* needed below */ static ide_startstop_t do_reset1(struct ata_device *, int); /* needed below */
/* /*
...@@ -1617,136 +1438,18 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs) ...@@ -1617,136 +1438,18 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs)
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
} }
/*
* get_info_ptr() returns the (struct ata_device *) for a given device number.
* It returns NULL if the given device number does not match any present drives.
*/
struct ata_device *get_info_ptr(kdev_t i_rdev)
{
unsigned int major = major(i_rdev);
int h;
for (h = 0; h < MAX_HWIFS; ++h) {
struct ata_channel *ch = &ide_hwifs[h];
if (ch->present && major == ch->major) {
int unit = DEVICE_NR(i_rdev);
if (unit < MAX_DRIVES) {
struct ata_device *drive = &ch->drives[unit];
if (drive->present)
return drive;
}
break;
}
}
return NULL;
}
/*
* FIXME: rename to ata_wipe_partitions.
*
* This routine is called to flush all partitions and partition tables
* for a changed disk, and then re-read the new partition table.
* If we are revalidating a disk because of a media change, then we
* enter with usage == 0. If we are using an ioctl, we automatically have
* usage == 1 (we need an open channel to use an ioctl :-), so this
* is our limit.
*/
int ide_revalidate_disk(kdev_t i_rdev)
{
struct ata_device *drive;
unsigned long flags;
int res;
if ((drive = get_info_ptr(i_rdev)) == NULL)
return -ENODEV;
/* FIXME: The locking here doesn't make the slightest sense! */
spin_lock_irqsave(&ide_lock, flags);
if (drive->busy || (drive->usage > 1)) {
spin_unlock_irqrestore(&ide_lock, flags);
return -EBUSY;
}
drive->busy = 1;
MOD_INC_USE_COUNT;
spin_unlock_irqrestore(&ide_lock, flags);
res = wipe_partitions(i_rdev);
if (!res) {
if (ata_ops(drive) && ata_ops(drive)->revalidate) {
ata_get(ata_ops(drive));
/* this is a no-op for tapes and SCSI based access */
ata_ops(drive)->revalidate(drive);
ata_put(ata_ops(drive));
} else
grok_partitions(i_rdev, ata_capacity(drive));
}
drive->busy = 0;
wake_up(&drive->wqueue);
MOD_DEC_USE_COUNT;
return res;
}
/*
* Look again for all drives in the system on all interfaces.
*/
static void revalidate_drives(void)
{
int i;
for (i = 0; i < MAX_HWIFS; ++i) {
int unit;
struct ata_channel *ch = &ide_hwifs[i];
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &ch->drives[unit];
if (drive->revalidate) {
drive->revalidate = 0;
if (!initializing)
ide_revalidate_disk(mk_kdev(ch->major, unit<<PARTN_BITS));
}
}
}
}
static void ide_driver_module(void)
{
int i;
/* Don't reinit the probe if there is already one channel detected. */
for (i = 0; i < MAX_HWIFS; ++i) {
if (ide_hwifs[i].present)
goto revalidate;
}
ideprobe_init();
revalidate:
revalidate_drives();
}
static int ide_open(struct inode * inode, struct file * filp) static int ide_open(struct inode * inode, struct file * filp)
{ {
struct ata_device *drive; struct ata_device *drive;
if ((drive = get_info_ptr(inode->i_rdev)) == NULL) if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
return -ENXIO; return -ENXIO;
if (drive->driver == NULL)
ide_driver_module();
/* Request a particular device type module. /* Request a particular device type module.
* *
* FIXME: The function which should rather requests the drivers in * FIXME: The function which should rather requests the drivers is
* ide_driver_module(), since it seems illogical and even a bit * ide_driver_module(), since it seems illogical and even a bit
* dangerous to delay this until open time! * dangerous to postpone this until open time!
*/ */
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
...@@ -1776,8 +1479,13 @@ static int ide_open(struct inode * inode, struct file * filp) ...@@ -1776,8 +1479,13 @@ static int ide_open(struct inode * inode, struct file * filp)
request_module(module); request_module(module);
} }
#endif #endif
if (drive->driver == NULL)
ide_driver_module();
while (drive->busy) while (drive->busy)
sleep_on(&drive->wqueue); sleep_on(&drive->wqueue);
++drive->usage; ++drive->usage;
if (ata_ops(drive) && ata_ops(drive)->open) if (ata_ops(drive) && ata_ops(drive)->open)
return ata_ops(drive)->open(inode, filp, drive); return ata_ops(drive)->open(inode, filp, drive);
...@@ -1787,7 +1495,8 @@ static int ide_open(struct inode * inode, struct file * filp) ...@@ -1787,7 +1495,8 @@ static int ide_open(struct inode * inode, struct file * filp)
} }
printk(KERN_INFO "%s: driver not present\n", drive->name); printk(KERN_INFO "%s: driver not present\n", drive->name);
drive->usage--; --drive->usage;
return -ENXIO; return -ENXIO;
} }
...@@ -1808,219 +1517,6 @@ static int ide_release(struct inode * inode, struct file * file) ...@@ -1808,219 +1517,6 @@ static int ide_release(struct inode * inode, struct file * file)
return 0; return 0;
} }
void ide_unregister(struct ata_channel *ch)
{
struct gendisk *gd;
struct ata_device *d;
spinlock_t *lock;
int unit;
int i;
unsigned long flags;
unsigned int p, minor;
struct ata_channel old;
int n_irq;
int n_ch;
spin_lock_irqsave(&ide_lock, flags);
if (!ch->present)
goto abort;
put_device(&ch->dev);
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device * drive = &ch->drives[unit];
if (!drive->present)
continue;
if (drive->busy || drive->usage)
goto abort;
if (ata_ops(drive)) {
if (ata_ops(drive)->cleanup) {
if (ata_ops(drive)->cleanup(drive))
goto abort;
} else
ide_unregister_subdriver(drive);
}
}
ch->present = 0;
/*
* All clear? Then blow away the buffer cache
*/
spin_unlock_irqrestore(&ide_lock, flags);
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device * drive = &ch->drives[unit];
if (!drive->present)
continue;
minor = drive->select.b.unit << PARTN_BITS;
for (p = 0; p < (1<<PARTN_BITS); ++p) {
if (drive->part[p].nr_sects > 0) {
kdev_t devp = mk_kdev(ch->major, minor+p);
invalidate_device(devp, 0);
}
}
}
spin_lock_irqsave(&ide_lock, flags);
/*
* Note that we only release the standard ports, and do not even try to
* handle any extra ports allocated for weird IDE interface chipsets.
*/
if (ch->straight8) {
release_region(ch->io_ports[IDE_DATA_OFFSET], 8);
} else {
for (i = 0; i < 8; i++)
if (ch->io_ports[i])
release_region(ch->io_ports[i], 1);
}
if (ch->io_ports[IDE_CONTROL_OFFSET])
release_region(ch->io_ports[IDE_CONTROL_OFFSET], 1);
/* FIXME: check if we can remove this ifdef */
#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
if (ch->io_ports[IDE_IRQ_OFFSET])
release_region(ch->io_ports[IDE_IRQ_OFFSET], 1);
#endif
/*
* Remove us from the lock group.
*/
lock = ch->lock;
d = ch->drive;
for (i = 0; i < MAX_DRIVES; ++i) {
struct ata_device *drive = &ch->drives[i];
if (drive->de) {
devfs_unregister (drive->de);
drive->de = NULL;
}
if (!drive->present)
continue;
/* FIXME: possibly unneccessary */
if (ch->drive == drive)
ch->drive = NULL;
if (drive->id != NULL) {
kfree(drive->id);
drive->id = NULL;
}
drive->present = 0;
blk_cleanup_queue(&drive->queue);
}
if (d->present)
ch->drive = d;
/*
* Free the irq if we were the only channel using it.
*
* Free the lock group if we were the only member.
*/
n_irq = n_ch = 0;
for (i = 0; i < MAX_HWIFS; ++i) {
struct ata_channel *tmp = &ide_hwifs[i];
if (!tmp->present)
continue;
if (tmp->irq == ch->irq)
++n_irq;
if (tmp->lock == ch->lock)
++n_ch;
}
if (n_irq == 1)
free_irq(ch->irq, ch);
if (n_ch == 1) {
kfree(ch->lock);
kfree(ch->active);
ch->lock = NULL;
ch->active = NULL;
}
#ifdef CONFIG_BLK_DEV_IDEDMA
ide_release_dma(ch);
#endif
/*
* Remove us from the kernel's knowledge.
*/
unregister_blkdev(ch->major, ch->name);
blk_dev[ch->major].data = NULL;
blk_dev[ch->major].queue = NULL;
blk_clear(ch->major);
gd = ch->gd;
if (gd) {
del_gendisk(gd);
kfree(gd->sizes);
kfree(gd->part);
if (gd->de_arr)
kfree (gd->de_arr);
if (gd->flags)
kfree (gd->flags);
kfree(gd);
ch->gd = NULL;
}
/*
* Reinitialize the channel handler, but preserve any special methods for
* it.
*/
old = *ch;
init_hwif_data(ch, ch->index);
ch->lock = old.lock;
ch->tuneproc = old.tuneproc;
ch->speedproc = old.speedproc;
ch->selectproc = old.selectproc;
ch->resetproc = old.resetproc;
ch->intrproc = old.intrproc;
ch->maskproc = old.maskproc;
ch->quirkproc = old.quirkproc;
ch->ata_read = old.ata_read;
ch->ata_write = old.ata_write;
ch->atapi_read = old.atapi_read;
ch->atapi_write = old.atapi_write;
ch->XXX_udma = old.XXX_udma;
ch->udma_enable = old.udma_enable;
ch->udma_start = old.udma_start;
ch->udma_stop = old.udma_stop;
ch->udma_read = old.udma_read;
ch->udma_write = old.udma_write;
ch->udma_irq_status = old.udma_irq_status;
ch->udma_timeout = old.udma_timeout;
ch->udma_irq_lost = old.udma_irq_lost;
ch->busproc = old.busproc;
ch->bus_state = old.bus_state;
ch->dma_base = old.dma_base;
ch->dma_extra = old.dma_extra;
ch->config_data = old.config_data;
ch->select_data = old.select_data;
ch->proc = old.proc;
/* FIXME: most propably this is always right:! */
#ifndef CONFIG_BLK_DEV_IDECS
ch->irq = old.irq;
#endif
ch->major = old.major;
ch->chipset = old.chipset;
ch->autodma = old.autodma;
ch->udma_four = old.udma_four;
#ifdef CONFIG_PCI
ch->pci_dev = old.pci_dev;
#endif
ch->straight8 = old.straight8;
abort:
spin_unlock_irqrestore(&ide_lock, flags);
}
/* /*
* Setup hw_regs_t structure described by parameters. You * Setup hw_regs_t structure described by parameters. You
* may set up the hw structure yourself OR use this routine to * may set up the hw structure yourself OR use this routine to
...@@ -2051,176 +1547,29 @@ void ide_setup_ports(hw_regs_t *hw, ...@@ -2051,176 +1547,29 @@ void ide_setup_ports(hw_regs_t *hw,
hw->ack_intr = ack_intr; hw->ack_intr = ack_intr;
} }
static int subdriver_match(struct ata_channel *channel, struct ata_operations *ops) int ide_spin_wait_hwgroup(struct ata_device *drive)
{
int count, unit;
if (!channel->present)
return 0;
count = 0;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &channel->drives[unit];
if (drive->present && !drive->driver) {
(*ops->attach)(drive);
if (drive->driver != NULL)
count++;
}
}
return count;
}
static struct ata_operations * subdriver_interator(struct ata_operations *prev)
{ {
struct ata_operations *tmp; /* FIXME: Wait on a proper timer. Instead of playing games on the
unsigned long flags; * spin_lock().
*/
spin_lock_irqsave(&ata_drivers_lock, flags);
/* Restart from beginning if current ata_operations was deallocated, unsigned long timeout = jiffies + (10 * HZ);
or if prev is NULL. */
for(tmp = ata_drivers; tmp != prev && tmp; tmp = tmp->next);
if (!tmp)
tmp = ata_drivers;
else
tmp = tmp->next;
spin_unlock_irqrestore(&ata_drivers_lock, flags); spin_lock_irq(drive->channel->lock);
return tmp; while (test_bit(IDE_BUSY, drive->channel->active)) {
} spin_unlock_irq(drive->channel->lock);
/* if (time_after(jiffies, timeout)) {
* Register an IDE interface, specifing exactly the registers etc printk("%s: channel busy\n", drive->name);
* Set init=1 iff calling before probes have taken place. return -EBUSY;
*/
int ide_register_hw(hw_regs_t *hw, struct ata_channel **hwifp)
{
int h;
int retry = 1;
struct ata_channel *ch;
struct ata_operations *subdriver;
do {
for (h = 0; h < MAX_HWIFS; ++h) {
ch = &ide_hwifs[h];
if (ch->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
goto found;
}
for (h = 0; h < MAX_HWIFS; ++h) {
ch = &ide_hwifs[h];
if ((!ch->present && (ch->unit == ATA_PRIMARY) && !initializing) ||
(!ch->hw.io_ports[IDE_DATA_OFFSET] && initializing))
goto found;
}
for (h = 0; h < MAX_HWIFS; ++h)
ide_unregister(&ide_hwifs[h]);
} while (retry--);
return -1;
found:
ide_unregister(ch);
if (ch->present)
return -1;
memcpy(&ch->hw, hw, sizeof(*hw));
memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->hw.io_ports));
ch->irq = hw->irq;
ch->noprobe = 0;
ch->chipset = hw->chipset;
if (!initializing) {
ideprobe_init();
revalidate_drives();
/* FIXME: Do we really have to call it second time here?! */
ide_driver_module();
} }
/* Look up whatever there is a subdriver, which will serve this spin_lock_irq(drive->channel->lock);
* device.
*/
subdriver = NULL;
while ((subdriver = subdriver_interator(subdriver))) {
if (subdriver_match(ch, subdriver) > 0)
break;
} }
if (hwifp) return 0;
*hwifp = ch;
return (initializing || ch->present) ? h : -1;
}
/*
* Compatability function for existing drivers. If you want
* something different, use the function above.
*/
int ide_register(int arg1, int arg2, int irq)
{
hw_regs_t hw;
ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL);
hw.irq = irq;
return ide_register_hw(&hw, NULL);
}
int ide_spin_wait_hwgroup(struct ata_device *drive)
{
/* FIXME: Wait on a proper timer. Instead of playing games on the
* spin_lock().
*/
unsigned long timeout = jiffies + (10 * HZ);
spin_lock_irq(drive->channel->lock);
while (test_bit(IDE_BUSY, drive->channel->active)) {
spin_unlock_irq(drive->channel->lock);
if (time_after(jiffies, timeout)) {
printk("%s: channel busy\n", drive->name);
return -EBUSY;
}
spin_lock_irq(drive->channel->lock);
}
return 0;
}
static int set_io_32bit(struct ata_device *drive, int arg)
{
if (drive->channel->no_io_32bit)
return -EIO;
drive->channel->io_32bit = arg;
return 0;
}
static int set_using_dma(struct ata_device *drive, int arg)
{
if (!drive->driver)
return -EPERM;
if (!drive->id || !(drive->id->capability & 1) || !drive->channel->XXX_udma)
return -EPERM;
udma_enable(drive, arg, 1);
return 0;
}
static int set_pio_mode(struct ata_device *drive, int arg)
{
if (!drive->channel->tuneproc)
return -ENOSYS;
if (drive->channel->tuneproc != NULL)
drive->channel->tuneproc(drive, (u8) arg);
return 0;
} }
/* /*
...@@ -2241,254 +1590,6 @@ void ide_delay_50ms (void) ...@@ -2241,254 +1590,6 @@ void ide_delay_50ms (void)
#endif #endif
} }
/*
* Handle ioctls.
*
* NOTE: Due to ridiculous coding habbits in the hdparm utility we have to
* always return unsigned long in case we are returning simple values.
*/
static int ide_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned int major, minor;
struct ata_device *drive;
struct request rq;
kdev_t dev;
dev = inode->i_rdev;
major = major(dev);
minor = minor(dev);
if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
return -ENODEV;
/* Contrary to popular beleve we disallow even the reading of the ioctl
* values for users which don't have permission too. We do this becouse
* such information could be used by an attacker to deply a simple-user
* attack, which triggers bugs present only on a particular
* configuration.
*/
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
ide_init_drive_cmd(&rq);
switch (cmd) {
case HDIO_GET_32BIT: {
unsigned long val = drive->channel->io_32bit;
if (put_user(val, (unsigned long *) arg))
return -EFAULT;
return 0;
}
case HDIO_SET_32BIT: {
int val;
if (arg < 0 || arg > 1)
return -EINVAL;
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
val = set_io_32bit(drive, arg);
spin_unlock_irq(drive->channel->lock);
return val;
}
case HDIO_SET_PIO_MODE: {
int val;
if (arg < 0 || arg > 255)
return -EINVAL;
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
val = set_pio_mode(drive, arg);
spin_unlock_irq(drive->channel->lock);
return val;
}
case HDIO_GET_UNMASKINTR: {
unsigned long val = drive->channel->unmask;
if (put_user(val, (unsigned long *) arg))
return -EFAULT;
return 0;
}
case HDIO_SET_UNMASKINTR: {
if (arg < 0 || arg > 1)
return -EINVAL;
if (drive->channel->no_unmask)
return -EIO;
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
drive->channel->unmask = arg;
spin_unlock_irq(drive->channel->lock);
return 0;
}
case HDIO_GET_DMA: {
unsigned long val = drive->using_dma;
if (put_user(val, (unsigned long *) arg))
return -EFAULT;
return 0;
}
case HDIO_SET_DMA: {
int val;
if (arg < 0 || arg > 1)
return -EINVAL;
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
val = set_using_dma(drive, arg);
spin_unlock_irq(drive->channel->lock);
return val;
}
case HDIO_GETGEO: {
struct hd_geometry *loc = (struct hd_geometry *) arg;
unsigned short bios_cyl = drive->bios_cyl; /* truncate */
if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY))
return -EINVAL;
if (put_user(drive->bios_head, (byte *) &loc->heads))
return -EFAULT;
if (put_user(drive->bios_sect, (byte *) &loc->sectors))
return -EFAULT;
if (put_user(bios_cyl, (unsigned short *) &loc->cylinders))
return -EFAULT;
if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect,
(unsigned long *) &loc->start))
return -EFAULT;
return 0;
}
case HDIO_GETGEO_BIG_RAW: {
struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;
if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY))
return -EINVAL;
if (put_user(drive->head, (u8 *) &loc->heads))
return -EFAULT;
if (put_user(drive->sect, (u8 *) &loc->sectors))
return -EFAULT;
if (put_user(drive->cyl, (unsigned int *) &loc->cylinders))
return -EFAULT;
if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect,
(unsigned long *) &loc->start))
return -EFAULT;
return 0;
}
case BLKRRPART: /* Re-read partition tables */
return ide_revalidate_disk(inode->i_rdev);
case HDIO_GET_IDENTITY:
if (minor(inode->i_rdev) & PARTN_MASK)
return -EINVAL;
if (drive->id == NULL)
return -ENOMSG;
if (copy_to_user((char *)arg, (char *)drive->id, sizeof(*drive->id)))
return -EFAULT;
return 0;
case HDIO_GET_NICE:
return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP |
drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP,
(long *) arg);
case HDIO_DRIVE_CMD:
if (!capable(CAP_SYS_RAWIO))
return -EACCES;
return ide_cmd_ioctl(drive, arg);
case HDIO_SET_NICE:
if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP))))
return -EPERM;
drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
/* Only CD-ROM's and tapes support DSC overlap. */
if (drive->dsc_overlap && !(drive->type == ATA_ROM || drive->type == ATA_TAPE)) {
drive->dsc_overlap = 0;
return -EPERM;
}
return 0;
case BLKGETSIZE:
case BLKGETSIZE64:
case BLKROSET:
case BLKROGET:
case BLKFLSBUF:
case BLKSSZGET:
case BLKPG:
case BLKELVGET:
case BLKELVSET:
case BLKBSZGET:
case BLKBSZSET:
return blk_ioctl(inode->i_bdev, cmd, arg);
/*
* uniform packet command handling
*/
case CDROMEJECT:
case CDROMCLOSETRAY:
return block_ioctl(inode->i_bdev, cmd, arg);
case HDIO_GET_BUSSTATE:
if (put_user(drive->channel->bus_state, (long *)arg))
return -EFAULT;
return 0;
case HDIO_SET_BUSSTATE:
if (drive->channel->busproc)
drive->channel->busproc(drive, (int)arg);
return 0;
/* Now check whatever this particular ioctl has a device type
* specific implementation.
*/
default:
if (ata_ops(drive) && ata_ops(drive)->ioctl)
return ata_ops(drive)->ioctl(drive, inode, file, cmd, arg);
return -EINVAL;
}
}
static int ide_check_media_change(kdev_t i_rdev) static int ide_check_media_change(kdev_t i_rdev)
{ {
struct ata_device *drive; struct ata_device *drive;
...@@ -2537,642 +1638,28 @@ void ide_fixstring (byte *s, const int bytecount, const int byteswap) ...@@ -2537,642 +1638,28 @@ void ide_fixstring (byte *s, const int bytecount, const int byteswap)
*p++ = '\0'; *p++ = '\0';
} }
/****************************************************************************
* FIXME: rewrite the following crap:
*/
/*
* stridx() returns the offset of c within s,
* or -1 if c is '\0' or not found within s.
*/
static int __init stridx (const char *s, char c)
{
char *i = strchr(s, c);
return (i && c) ? i - s : -1;
}
/*
* Parsing for ide_setup():
*
* 1. the first char of s must be '='.
* 2. if the remainder matches one of the supplied keywords,
* the index (1 based) of the keyword is negated and returned.
* 3. if the remainder is a series of no more than max_vals numbers
* separated by commas, the numbers are saved in vals[] and a
* count of how many were saved is returned. Base10 is assumed,
* and base16 is allowed when prefixed with "0x".
* 4. otherwise, zero is returned.
*/
static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals)
{
static const char *decimal = "0123456789";
static const char *hex = "0123456789abcdef";
int i, n;
if (*s++ == '=') {
/*
* Try matching against the supplied keywords,
* and return -(index+1) if we match one
*/
if (keywords != NULL) {
for (i = 0; *keywords != NULL; ++i) {
if (!strcmp(s, *keywords++))
return -(i+1);
}
}
/*
* Look for a series of no more than "max_vals"
* numeric values separated by commas, in base10,
* or base16 when prefixed with "0x".
* Return a count of how many were found.
*/
for (n = 0; (i = stridx(decimal, *s)) >= 0;) {
vals[n] = i;
while ((i = stridx(decimal, *++s)) >= 0)
vals[n] = (vals[n] * 10) + i;
if (*s == 'x' && !vals[n]) {
while ((i = stridx(hex, *++s)) >= 0)
vals[n] = (vals[n] * 0x10) + i;
}
if (++n == max_vals)
break;
if (*s == ',' || *s == ';')
++s;
}
if (!*s)
return n;
}
return 0; /* zero = nothing matched */
}
/*
* 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.
*
* Here is the complete set currently supported comand line options:
*
* "hdx=" is recognized for all "x" from "a" to "h", such as "hdc".
* "idex=" is recognized for all "x" from "0" to "3", such as "ide1".
*
* "hdx=noprobe" : drive may be present, but do not probe for it
* "hdx=none" : drive is NOT present, ignore cmos and do not probe
* "hdx=nowerr" : ignore the WRERR_STAT bit on this drive
* "hdx=cdrom" : drive is present, and is a cdrom drive
* "hdx=cyl,head,sect" : disk drive is present, with specified geometry
* "hdx=noremap" : do not remap 0->1 even though EZD was detected
* "hdx=autotune" : driver will attempt to tune interface speed
* to the fastest PIO mode supported,
* if possible for this drive only.
* Not fully supported by all chipset types,
* and quite likely to cause trouble with
* older/odd IDE drives.
*
* "hdx=slow" : insert a huge pause after each access to the data
* port. Should be used only as a last resort.
*
* "hdxlun=xx" : set the drive last logical unit.
* "hdx=flash" : allows for more than one ata_flash disk to be
* registered. In most cases, only one device
* will be present.
* "hdx=ide-scsi" : the return of the ide-scsi flag, this is useful for
* allowwing ide-floppy, ide-tape, and ide-cdrom|writers
* to use ide-scsi emulation on a device specific option.
* "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz,
* where "xx" is between 20 and 66 inclusive,
* used when tuning chipset PIO modes.
* For PCI bus, 25 is correct for a P75 system,
* 30 is correct for P90,P120,P180 systems,
* and 33 is used for P100,P133,P166 systems.
* If in doubt, use idebus=33 for PCI.
* As for VLB, it is safest to not specify it.
*
* "idex=noprobe" : do not attempt to access/use this interface
* "idex=base" : probe for an interface at the address specified,
* where "base" is usually 0x1f0 or 0x170
* and "ctl" is assumed to be "base"+0x206
* "idex=base,ctl" : specify both base and ctl
* "idex=base,ctl,irq" : specify base, ctl, and irq number
* "idex=autotune" : driver will attempt to tune interface speed
* to the fastest PIO mode supported,
* for all drives on this interface.
* Not fully supported by all chipset types,
* and quite likely to cause trouble with
* older/odd IDE drives.
* "idex=noautotune" : driver will NOT attempt to tune interface speed
* This is the default for most chipsets,
* except the cmd640.
* "idex=serialize" : do not overlap operations on idex and ide(x^1)
* "idex=four" : four drives on idex and ide(x^1) share same ports
* "idex=reset" : reset interface before first use
* "idex=dma" : enable DMA by default on both drives if possible
* "idex=ata66" : informs the interface that it has an 80c cable
* for chipsets that are ATA-66 capable, but
* the ablity to bit test for detection is
* currently unknown.
* "ide=reverse" : Formerly called to pci sub-system, but now local.
*
* The following are valid ONLY on ide0, (except dc4030)
* and the defaults for the base,ctl ports must not be altered.
*
* "ide0=dtc2278" : probe/support DTC2278 interface
* "ide0=ht6560b" : probe/support HT6560B interface
* "ide0=cmd640_vlb" : *REQUIRED* for VLB cards with the CMD640 chip
* (not for PCI -- automatically detected)
* "ide0=qd65xx" : probe/support qd65xx interface
* "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445)
* "ide0=umc8672" : probe/support umc8672 chipsets
* "idex=dc4030" : probe/support Promise DC4030VL interface
* "ide=doubler" : probe/support IDE doublers on Amiga
*/
int __init ide_setup (char *s)
{
int i, vals[3];
struct ata_channel *hwif;
struct ata_device *drive;
unsigned int hw, unit;
const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
const char max_hwif = '0' + (MAX_HWIFS - 1);
if (!strncmp(s, "hd=", 3)) /* hd= is for hd.c driver and not us */
return 0;
if (strncmp(s,"ide",3) &&
strncmp(s,"idebus",6) &&
strncmp(s,"hd",2)) /* hdx= & hdxlun= */
return 0;
printk(KERN_INFO "ide_setup: %s", s);
init_ide_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",
"serialize", "autotune", "noautotune",
"slow", "flash", "remap", "noremap", "scsi", NULL};
unit = s[2] - 'a';
hw = unit / MAX_DRIVES;
unit = unit % MAX_DRIVES;
hwif = &ide_hwifs[hw];
drive = &hwif->drives[unit];
if (!strncmp(s + 4, "ide-", 4)) {
strncpy(drive->driver_req, s + 4, 9);
goto done;
}
/*
* Look for last lun option: "hdxlun="
*/
if (!strncmp(&s[3], "lun", 3)) {
if (match_parm(&s[6], NULL, vals, 1) != 1)
goto bad_option;
if (vals[0] >= 0 && vals[0] <= 7) {
drive->last_lun = vals[0];
drive->forced_lun = 1;
} else
printk(" -- BAD LAST LUN! Expected value from 0 to 7");
goto done;
}
switch (match_parm(&s[3], hd_words, vals, 3)) {
case -1: /* "none" */
drive->nobios = 1; /* drop into "noprobe" */
case -2: /* "noprobe" */
drive->noprobe = 1;
goto done;
case -3: /* "nowerr" */
drive->bad_wstat = BAD_R_STAT;
hwif->noprobe = 0;
goto done;
case -4: /* "cdrom" */
drive->present = 1;
drive->type = ATA_ROM;
hwif->noprobe = 0;
goto done;
case -5: /* "serialize" */
printk(" -- USE \"ide%d=serialize\" INSTEAD", hw);
goto do_serialize;
case -6: /* "autotune" */
drive->autotune = 1;
goto done;
case -7: /* "noautotune" */
drive->autotune = 2;
goto done;
case -8: /* "slow" */
hwif->slow = 1;
goto done;
case -9: /* "flash" */
drive->ata_flash = 1;
goto done;
case -10: /* "remap" */
drive->remap_0_to_1 = 1;
goto done;
case -11: /* "noremap" */
drive->remap_0_to_1 = 2;
goto done;
case -12: /* "scsi" */
#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI)
drive->scsi = 1;
goto done;
#else
drive->scsi = 0;
goto bad_option;
#endif
case 3: /* cyl,head,sect */
drive->type = ATA_DISK;
drive->cyl = drive->bios_cyl = vals[0];
drive->head = drive->bios_head = vals[1];
drive->sect = drive->bios_sect = vals[2];
drive->present = 1;
drive->forced_geom = 1;
hwif->noprobe = 0;
goto done;
default:
goto bad_option;
}
}
/*
* Look for bus speed option: "idebus="
*/
if (!strncmp(s, "idebus", 6)) {
if (match_parm(&s[6], NULL, vals, 1) != 1)
goto bad_option;
idebus_parameter = vals[0];
goto done;
}
/*
* Look for interface options: "idex="
*/
if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_hwif) {
/*
* Be VERY CAREFUL changing this: note hardcoded indexes below
* -8,-9,-10. -11 : are reserved for future idex calls to ease the hardcoding.
*/
const char *ide_words[] = {
"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66",
"minus8", "minus9", "minus10", "minus11",
"qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
hw = s[3] - '0';
hwif = &ide_hwifs[hw];
i = match_parm(&s[4], ide_words, vals, 3);
/*
* Cryptic check to ensure chipset not already set for hwif:
*/
if (i > 0 || i <= -11) { /* is parameter a chipset name? */
if (hwif->chipset != ide_unknown)
goto bad_option; /* chipset already specified */
if (i <= -11 && i != -18 && hw != 0)
goto bad_hwif; /* chipset drivers are for "ide0=" only */
if (i <= -11 && i != -18 && ide_hwifs[hw+1].chipset != ide_unknown)
goto bad_option; /* chipset for 2nd port already specified */
printk("\n");
}
switch (i) {
#ifdef CONFIG_BLK_DEV_PDC4030
case -18: /* "dc4030" */
{
extern void init_pdc4030(void);
init_pdc4030();
goto done;
}
#endif
#ifdef CONFIG_BLK_DEV_ALI14XX
case -17: /* "ali14xx" */
{
extern void init_ali14xx (void);
init_ali14xx();
goto done;
}
#endif
#ifdef CONFIG_BLK_DEV_UMC8672
case -16: /* "umc8672" */
{
extern void init_umc8672 (void);
init_umc8672();
goto done;
}
#endif
#ifdef CONFIG_BLK_DEV_DTC2278
case -15: /* "dtc2278" */
{
extern void init_dtc2278 (void);
init_dtc2278();
goto done;
}
#endif
#ifdef CONFIG_BLK_DEV_CMD640
case -14: /* "cmd640_vlb" */
{
extern int cmd640_vlb; /* flag for cmd640.c */
cmd640_vlb = 1;
goto done;
}
#endif
#ifdef CONFIG_BLK_DEV_HT6560B
case -13: /* "ht6560b" */
{
extern void init_ht6560b (void);
init_ht6560b();
goto done;
}
#endif
#if CONFIG_BLK_DEV_QD65XX
case -12: /* "qd65xx" */
{
extern void init_qd65xx (void);
init_qd65xx();
goto done;
}
#endif
case -11: /* minus11 */
case -10: /* minus10 */
case -9: /* minus9 */
case -8: /* minus8 */
goto bad_option;
case -7: /* ata66 */
#ifdef CONFIG_PCI
hwif->udma_four = 1;
goto done;
#else
hwif->udma_four = 0;
goto bad_hwif;
#endif
case -6: /* dma */
hwif->autodma = 1;
goto done;
case -5: /* "reset" */
hwif->reset = 1;
goto done;
case -4: /* "noautotune" */
hwif->drives[0].autotune = 2;
hwif->drives[1].autotune = 2;
goto done;
case -3: /* "autotune" */
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
goto done;
case -2: /* "serialize" */
do_serialize:
{
struct ata_channel *mate;
mate = &ide_hwifs[hw ^ 1];
hwif->serialized = 1;
mate->serialized = 1;
}
goto done;
case -1: /* "noprobe" */
hwif->noprobe = 1;
goto done;
case 1: /* base */
vals[1] = vals[0] + 0x206; /* default ctl */
case 2: /* base,ctl */
vals[2] = 0; /* default irq = probe for it */
case 3: /* base,ctl,irq */
hwif->hw.irq = vals[2];
ide_init_hwif_ports(&hwif->hw, (ide_ioreg_t) vals[0], (ide_ioreg_t) vals[1], &hwif->irq);
memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
hwif->irq = vals[2];
hwif->noprobe = 0;
hwif->chipset = ide_generic;
goto done;
case 0: goto bad_option;
default:
printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n");
return 1;
}
}
bad_option:
printk(" -- BAD OPTION\n");
return 1;
bad_hwif:
printk("-- NOT SUPPORTED ON ide%d", hw);
done:
printk("\n");
return 1;
}
/****************************************************************************/
/* This is the default end request function as well */ /* This is the default end request function as well */
int ide_end_request(struct ata_device *drive, struct request *rq, int uptodate) int ide_end_request(struct ata_device *drive, struct request *rq, int uptodate)
{ {
return __ide_end_request(drive, rq, uptodate, 0); return __ide_end_request(drive, rq, uptodate, 0);
} }
/*
* This is in fact registering a device not a driver.
*/
int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driver)
{
unsigned long flags;
save_flags(flags); /* all CPUs */
cli(); /* all CPUs */
if (!drive->present || drive->driver != NULL || drive->busy || drive->usage) {
restore_flags(flags); /* all CPUs */
return 1;
}
/* FIXME: This will be pushed to the drivers! Thus allowing us to
* save one parameter here separate this out.
*/
drive->driver = driver;
restore_flags(flags); /* all CPUs */
/* FIXME: Check what this magic number is supposed to be about? */
if (drive->autotune != 2) {
if (drive->channel->XXX_udma) {
/*
* Force DMAing for the beginning of the check. Some
* chipsets appear to do interesting things, if not
* checked and cleared.
*
* PARANOIA!!!
*/
udma_enable(drive, 0, 0);
drive->channel->XXX_udma(drive);
#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
udma_tcq_enable(drive, 1);
#endif
}
/* Only CD-ROMs and tape drives support DSC overlap. But only
* if they are alone on a channel. */
if (drive->type == ATA_ROM || drive->type == ATA_TAPE) {
int single = 0;
int unit;
for (unit = 0; unit < MAX_DRIVES; ++unit)
if (drive->channel->drives[unit].present)
++single;
drive->dsc_overlap = (single == 1);
} else
drive->dsc_overlap = 0;
}
drive->revalidate = 1;
drive->suspend_reset = 0;
return 0;
}
/*
* This is in fact the default cleanup routine.
*
* FIXME: Check whatever we maybe don't call it twice!.
*/
int ide_unregister_subdriver(struct ata_device *drive)
{
unsigned long flags;
save_flags(flags); /* all CPUs */
cli(); /* all CPUs */
#if 0
if (__MOD_IN_USE(ata_ops(drive)->owner)) {
restore_flags(flags);
return 1;
}
#endif
if (drive->usage || drive->busy || !ata_ops(drive)) {
restore_flags(flags); /* all CPUs */
return 1;
}
#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE)
pnpide_init(0);
#endif
drive->driver = NULL;
restore_flags(flags); /* all CPUs */
return 0;
}
/*
* Register an ATA subdriver for a particular device type.
*/
int register_ata_driver(struct ata_operations *driver)
{
unsigned long flags;
int index;
int count = 0;
spin_lock_irqsave(&ata_drivers_lock, flags);
driver->next = ata_drivers;
ata_drivers = driver;
spin_unlock_irqrestore(&ata_drivers_lock, flags);
for (index = 0; index < MAX_HWIFS; ++index)
count += subdriver_match(&ide_hwifs[index], driver);
return count;
}
EXPORT_SYMBOL(register_ata_driver);
/*
* Unregister an ATA subdriver for a particular device type.
*/
void unregister_ata_driver(struct ata_operations *driver)
{
struct ata_operations **tmp;
unsigned long flags;
int index;
int unit;
spin_lock_irqsave(&ata_drivers_lock, flags);
for (tmp = &ata_drivers; *tmp != NULL; tmp = &(*tmp)->next) {
if (*tmp == driver) {
*tmp = driver->next;
break;
}
}
spin_unlock_irqrestore(&ata_drivers_lock, flags);
for (index = 0; index < MAX_HWIFS; ++index) {
struct ata_channel *ch = &ide_hwifs[index];
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &ch->drives[unit];
if (drive->driver == driver)
(*ata_ops(drive)->cleanup)(drive);
}
}
}
EXPORT_SYMBOL(unregister_ata_driver);
struct block_device_operations ide_fops[] = {{ struct block_device_operations ide_fops[] = {{
owner: THIS_MODULE, owner: THIS_MODULE,
open: ide_open, open: ide_open,
release: ide_release, release: ide_release,
ioctl: ide_ioctl, ioctl: ata_ioctl,
check_media_change: ide_check_media_change, check_media_change: ide_check_media_change,
revalidate: ide_revalidate_disk revalidate: ata_revalidate
}}; }};
EXPORT_SYMBOL(ide_fops); EXPORT_SYMBOL(ide_fops);
EXPORT_SYMBOL(ide_hwifs);
EXPORT_SYMBOL(ide_spin_wait_hwgroup); EXPORT_SYMBOL(ide_spin_wait_hwgroup);
devfs_handle_t ide_devfs_handle;
EXPORT_SYMBOL(ide_lock);
EXPORT_SYMBOL(drive_is_flashcard); EXPORT_SYMBOL(drive_is_flashcard);
EXPORT_SYMBOL(ide_timer_expiry); EXPORT_SYMBOL(ide_timer_expiry);
EXPORT_SYMBOL(do_ide_request); EXPORT_SYMBOL(do_ide_request);
EXPORT_SYMBOL(ide_register_subdriver);
EXPORT_SYMBOL(ide_unregister_subdriver);
EXPORT_SYMBOL(ide_set_handler); EXPORT_SYMBOL(ide_set_handler);
EXPORT_SYMBOL(ide_dump_status); EXPORT_SYMBOL(ide_dump_status);
EXPORT_SYMBOL(ide_error); EXPORT_SYMBOL(ide_error);
...@@ -3182,324 +1669,7 @@ EXPORT_SYMBOL(restart_request); ...@@ -3182,324 +1669,7 @@ EXPORT_SYMBOL(restart_request);
EXPORT_SYMBOL(ide_end_drive_cmd); EXPORT_SYMBOL(ide_end_drive_cmd);
EXPORT_SYMBOL(__ide_end_request); EXPORT_SYMBOL(__ide_end_request);
EXPORT_SYMBOL(ide_end_request); EXPORT_SYMBOL(ide_end_request);
EXPORT_SYMBOL(ide_revalidate_disk);
EXPORT_SYMBOL(ide_delay_50ms); EXPORT_SYMBOL(ide_delay_50ms);
EXPORT_SYMBOL(ide_stall_queue); EXPORT_SYMBOL(ide_stall_queue);
EXPORT_SYMBOL(ide_register_hw);
EXPORT_SYMBOL(ide_register);
EXPORT_SYMBOL(ide_unregister);
EXPORT_SYMBOL(ide_setup_ports); EXPORT_SYMBOL(ide_setup_ports);
EXPORT_SYMBOL(get_info_ptr);
/*
* Handle power handling related events ths system informs us about.
*/
static int ata_sys_notify(struct notifier_block *this, unsigned long event, void *x)
{
int i;
switch (event) {
case SYS_HALT:
case SYS_POWER_OFF:
case SYS_RESTART:
break;
default:
return NOTIFY_DONE;
}
printk("flushing ide devices: ");
for (i = 0; i < MAX_HWIFS; i++) {
int unit;
struct ata_channel *ch = &ide_hwifs[i];
if (!ch->present)
continue;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &ch->drives[unit];
if (!drive->present)
continue;
/* set the drive to standby */
printk("%s ", drive->name);
if (ata_ops(drive)) {
if (event != SYS_RESTART)
if (ata_ops(drive)->standby && ata_ops(drive)->standby(drive))
continue;
if (ata_ops(drive)->cleanup)
ata_ops(drive)->cleanup(drive);
}
}
}
printk("\n");
return NOTIFY_DONE;
}
static struct notifier_block ata_notifier = {
ata_sys_notify,
NULL,
5
};
/*
* This is the global initialization entry point.
*/
static int __init ata_module_init(void)
{
int h;
printk(KERN_INFO "ATA/ATAPI device driver v" VERSION "\n");
ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL);
/*
* Because most of the ATA adapters represent the timings in unit of
* bus clocks, and there is no known reliable way to detect the bus
* clock frequency, we assume 50 MHz for non-PCI (VLB, EISA) and 33 MHz
* for PCI based systems. Since assuming only hurts performance and not
* stability, this is OK. The user can change this on the command line
* by using the "idebus=XX" parameter. While the system_bus_speed
* variable is in kHz units, we accept both MHz and kHz entry on the
* command line for backward compatibility.
*/
system_bus_speed = 50000;
if (pci_present())
system_bus_speed = 33333;
if (idebus_parameter >= 20 && idebus_parameter <= 80) {
system_bus_speed = idebus_parameter * 1000;
switch (system_bus_speed) {
case 33000: system_bus_speed = 33333; break;
case 37000: system_bus_speed = 37500; break;
case 41000: system_bus_speed = 41666; break;
case 66000: system_bus_speed = 66666; break;
}
}
if (idebus_parameter >= 20000 && idebus_parameter <= 80000)
system_bus_speed = idebus_parameter;
printk(KERN_INFO "ATA: %s bus speed %d.%dMHz\n",
pci_present() ? "PCI" : "System", system_bus_speed / 1000, system_bus_speed / 100 % 10);
init_ide_data();
initializing = 1;
#ifdef CONFIG_PCI
/*
* Register the host chip drivers.
*/
# ifdef CONFIG_BLK_DEV_PIIX
init_piix();
# endif
# ifdef CONFIG_BLK_DEV_VIA82CXXX
init_via82cxxx();
# endif
# ifdef CONFIG_BLK_DEV_PDC202XX
init_pdc202xx();
# endif
# ifdef CONFIG_BLK_DEV_RZ1000
init_rz1000();
# endif
# ifdef CONFIG_BLK_DEV_SIS5513
init_sis5513();
# endif
# ifdef CONFIG_BLK_DEV_CMD64X
init_cmd64x();
# endif
# ifdef CONFIG_BLK_DEV_OPTI621
init_opti621();
# endif
# ifdef CONFIG_BLK_DEV_TRM290
init_trm290();
# endif
# ifdef CONFIG_BLK_DEV_NS87415
init_ns87415();
# endif
# ifdef CONFIG_BLK_DEV_AEC62XX
init_aec62xx();
# endif
# ifdef CONFIG_BLK_DEV_SL82C105
init_sl82c105();
# endif
# ifdef CONFIG_BLK_DEV_HPT34X
init_hpt34x();
# endif
# ifdef CONFIG_BLK_DEV_HPT366
init_hpt366();
# endif
# ifdef CONFIG_BLK_DEV_ALI15X3
init_ali15x3();
# endif
# ifdef CONFIG_BLK_DEV_CY82C693
init_cy82c693();
# endif
# ifdef CONFIG_BLK_DEV_CS5530
init_cs5530();
# endif
# ifdef CONFIG_BLK_DEV_AMD74XX
init_amd74xx();
# endif
# ifdef CONFIG_BLK_DEV_SVWKS
init_svwks();
# endif
# ifdef CONFIG_BLK_DEV_IT8172
init_it8172();
# endif
init_ata_pci_misc();
/*
* Detect and initialize "known" IDE host chip types.
*/
if (pci_present()) {
# ifdef CONFIG_PCI
ide_scan_pcibus(ide_scan_direction);
# else
# ifdef CONFIG_BLK_DEV_RZ1000
ide_probe_for_rz100x();
# endif
# endif
}
#endif
#ifdef CONFIG_ETRAX_IDE
init_e100_ide();
#endif
#ifdef CONFIG_BLK_DEV_CMD640
ide_probe_for_cmd640x();
#endif
#ifdef CONFIG_BLK_DEV_PDC4030
ide_probe_for_pdc4030();
#endif
#ifdef CONFIG_BLK_DEV_IDE_PMAC
pmac_ide_probe();
#endif
#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
icside_init();
#endif
#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
rapide_init();
#endif
#ifdef CONFIG_BLK_DEV_GAYLE
gayle_init();
#endif
#ifdef CONFIG_BLK_DEV_FALCON_IDE
falconide_init();
#endif
#ifdef CONFIG_BLK_DEV_MAC_IDE
macide_init();
#endif
#ifdef CONFIG_BLK_DEV_Q40IDE
q40ide_init();
#endif
#ifdef CONFIG_BLK_DEV_BUDDHA
buddha_init();
#endif
#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP)
pnpide_init(1);
#endif
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
# if defined(__mc68000__) || defined(CONFIG_APUS)
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
// ide_get_lock(&irq_lock, NULL, NULL);/* for atari only */
disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */
// disable_irq_nosync(ide_hwifs[0].irq);
}
# endif
ideprobe_init();
# if defined(__mc68000__) || defined(CONFIG_APUS)
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
enable_irq(ide_hwifs[0].irq);
ide_release_lock(&irq_lock);/* for atari only */
}
# endif
#endif
/*
* Initialize all device type driver modules.
*/
#ifdef CONFIG_BLK_DEV_IDEDISK
idedisk_init();
#endif
#ifdef CONFIG_BLK_DEV_IDECD
ide_cdrom_init();
#endif
#ifdef CONFIG_BLK_DEV_IDETAPE
idetape_init();
#endif
#ifdef CONFIG_BLK_DEV_IDEFLOPPY
idefloppy_init();
#endif
#ifdef CONFIG_BLK_DEV_IDESCSI
# ifdef CONFIG_SCSI
idescsi_init();
# else
#error ATA SCSI emulation selected but no SCSI-subsystem in kernel
# endif
#endif
initializing = 0;
for (h = 0; h < MAX_HWIFS; ++h) {
struct ata_channel *channel = &ide_hwifs[h];
if (channel->present)
ide_geninit(channel);
}
register_reboot_notifier(&ata_notifier);
return 0;
}
static char *options = NULL;
static int __init init_ata(void)
{
if (options != NULL && *options) {
char *next = options;
while ((options = next) != NULL) {
if ((next = strchr(options,' ')) != NULL)
*next++ = 0;
if (!ide_setup(options))
printk(KERN_ERR "Unknown option '%s'\n", options);
}
}
return ata_module_init();
}
static void __exit cleanup_ata(void)
{
int h;
unregister_reboot_notifier(&ata_notifier);
for (h = 0; h < MAX_HWIFS; ++h) {
ide_unregister(&ide_hwifs[h]);
}
devfs_unregister(ide_devfs_handle);
}
module_init(init_ata);
module_exit(cleanup_ata);
#ifndef MODULE
/* command line option parser */
__setup("", ide_setup);
#endif
/**** vi:set ts=8 sts=8 sw=8:************************************************
*
* Copyright (C) 2002 Marcin Dalecki <martin@dalecki.de>
*
* 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.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
/*
* Generic ioctl handling for all ATA/ATAPI device drivers.
*/
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/blkpg.h>
#include <linux/pci.h>
#include <linux/cdrom.h>
#include <linux/device.h>
#include <linux/ide.h>
#include <asm/uaccess.h>
#include "ioctl.h"
/*
* NOTE: Due to ridiculous coding habbits in the hdparm utility we have to
* always return unsigned long in case we are returning simple values.
*/
int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned int major, minor;
struct ata_device *drive;
struct request rq;
kdev_t dev;
dev = inode->i_rdev;
major = major(dev);
minor = minor(dev);
if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
return -ENODEV;
/* Contrary to popular beleve we disallow even the reading of the ioctl
* values for users which don't have permission too. We do this becouse
* such information could be used by an attacker to deply a simple-user
* attack, which triggers bugs present only on a particular
* configuration.
*/
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
ide_init_drive_cmd(&rq);
switch (cmd) {
case HDIO_GET_32BIT: {
unsigned long val = drive->channel->io_32bit;
if (put_user(val, (unsigned long *) arg))
return -EFAULT;
return 0;
}
case HDIO_SET_32BIT:
if (arg < 0 || arg > 1)
return -EINVAL;
if (drive->channel->no_io_32bit)
return -EIO;
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
drive->channel->io_32bit = arg;
spin_unlock_irq(drive->channel->lock);
return 0;
case HDIO_SET_PIO_MODE:
if (arg < 0 || arg > 255)
return -EINVAL;
if (!drive->channel->tuneproc)
return -ENOSYS;
/* FIXME: we can see that tuneproc whould do the
* locking!.
*/
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
drive->channel->tuneproc(drive, (u8) arg);
spin_unlock_irq(drive->channel->lock);
return 0;
case HDIO_GET_UNMASKINTR: {
unsigned long val = drive->channel->unmask;
if (put_user(val, (unsigned long *) arg))
return -EFAULT;
return 0;
}
case HDIO_SET_UNMASKINTR:
if (arg < 0 || arg > 1)
return -EINVAL;
if (drive->channel->no_unmask)
return -EIO;
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
drive->channel->unmask = arg;
spin_unlock_irq(drive->channel->lock);
return 0;
case HDIO_GET_DMA: {
unsigned long val = drive->using_dma;
if (put_user(val, (unsigned long *) arg))
return -EFAULT;
return 0;
}
case HDIO_SET_DMA:
if (arg < 0 || arg > 1)
return -EINVAL;
if (!drive->driver)
return -EPERM;
if (!drive->id || !(drive->id->capability & 1) || !drive->channel->XXX_udma)
return -EPERM;
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
udma_enable(drive, arg, 1);
spin_unlock_irq(drive->channel->lock);
return 0;
case HDIO_GETGEO: {
struct hd_geometry *loc = (struct hd_geometry *) arg;
unsigned short bios_cyl = drive->bios_cyl; /* truncate */
if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY))
return -EINVAL;
if (put_user(drive->bios_head, (byte *) &loc->heads))
return -EFAULT;
if (put_user(drive->bios_sect, (byte *) &loc->sectors))
return -EFAULT;
if (put_user(bios_cyl, (unsigned short *) &loc->cylinders))
return -EFAULT;
if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect,
(unsigned long *) &loc->start))
return -EFAULT;
return 0;
}
case HDIO_GETGEO_BIG_RAW: {
struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;
if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY))
return -EINVAL;
if (put_user(drive->head, (u8 *) &loc->heads))
return -EFAULT;
if (put_user(drive->sect, (u8 *) &loc->sectors))
return -EFAULT;
if (put_user(drive->cyl, (unsigned int *) &loc->cylinders))
return -EFAULT;
if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect,
(unsigned long *) &loc->start))
return -EFAULT;
return 0;
}
case BLKRRPART: /* Re-read partition tables */
return ata_revalidate(inode->i_rdev);
case HDIO_GET_IDENTITY:
if (minor(inode->i_rdev) & PARTN_MASK)
return -EINVAL;
if (drive->id == NULL)
return -ENOMSG;
if (copy_to_user((char *)arg, (char *)drive->id, sizeof(*drive->id)))
return -EFAULT;
return 0;
case HDIO_GET_NICE:
return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP |
drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP,
(long *) arg);
case HDIO_DRIVE_CMD:
if (!capable(CAP_SYS_RAWIO))
return -EACCES;
return ide_cmd_ioctl(drive, arg);
case HDIO_SET_NICE:
if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP))))
return -EPERM;
drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
/* Only CD-ROM's and tapes support DSC overlap. */
if (drive->dsc_overlap && !(drive->type == ATA_ROM || drive->type == ATA_TAPE)) {
drive->dsc_overlap = 0;
return -EPERM;
}
return 0;
case BLKGETSIZE:
case BLKGETSIZE64:
case BLKROSET:
case BLKROGET:
case BLKFLSBUF:
case BLKSSZGET:
case BLKPG:
case BLKELVGET:
case BLKELVSET:
case BLKBSZGET:
case BLKBSZSET:
return blk_ioctl(inode->i_bdev, cmd, arg);
/*
* uniform packet command handling
*/
case CDROMEJECT:
case CDROMCLOSETRAY:
return block_ioctl(inode->i_bdev, cmd, arg);
case HDIO_GET_BUSSTATE:
if (put_user(drive->channel->bus_state, (long *)arg))
return -EFAULT;
return 0;
case HDIO_SET_BUSSTATE:
if (drive->channel->busproc)
drive->channel->busproc(drive, (int)arg);
return 0;
/* Now check whatever this particular ioctl has a device type
* specific implementation.
*/
default:
if (ata_ops(drive) && ata_ops(drive)->ioctl)
return ata_ops(drive)->ioctl(drive, inode, file, cmd, arg);
return -EINVAL;
}
}
/**** vi:set ts=8 sts=8 sw=8:************************************************
*
* Copyright (C) 2002 Marcin Dalecki <martin@dalecki.de>
*
* 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.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
extern int ata_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
/**** vi:set ts=8 sts=8 sw=8:************************************************
*
* Copyright (C) 1994-1998,2002 Linus Torvalds and authors:
*
* Mark Lord <mlord@pobox.com>
* Gadi Oxman <gadio@netvision.net.il>
* Andre Hedrick <andre@linux-ide.org>
* Jens Axboe <axboe@suse.de>
* Marcin Dalecki <martin@dalecki.de>
*
* See linux/MAINTAINERS for address of current maintainer.
*/
/*
* Handle overall infrastructure of the driver
*/
#define VERSION "7.0.0"
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/blkpg.h>
#include <linux/slab.h>
#ifndef MODULE
# include <linux/init.h>
#endif
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/reboot.h>
#include <linux/cdrom.h>
#include <linux/device.h>
#include <linux/kmod.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include "ata-timing.h"
#include "pcihost.h"
#include "ioctl.h"
MODULE_DESCRIPTION("ATA/ATAPI driver infrastructure");
MODULE_PARM(options,"s");
MODULE_LICENSE("GPL");
/*
* Those will be moved into separate header files eventually.
*/
#ifdef CONFIG_ETRAX_IDE
extern void init_e100_ide(void);
#endif
#ifdef CONFIG_BLK_DEV_CMD640
extern void ide_probe_for_cmd640x(void);
#endif
#ifdef CONFIG_BLK_DEV_PDC4030
extern int ide_probe_for_pdc4030(void);
#endif
#ifdef CONFIG_BLK_DEV_IDE_PMAC
extern void pmac_ide_probe(void);
#endif
#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
extern void icside_init(void);
#endif
#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
extern void rapide_init(void);
#endif
#ifdef CONFIG_BLK_DEV_GAYLE
extern void gayle_init(void);
#endif
#ifdef CONFIG_BLK_DEV_FALCON_IDE
extern void falconide_init(void);
#endif
#ifdef CONFIG_BLK_DEV_MAC_IDE
extern void macide_init(void);
#endif
#ifdef CONFIG_BLK_DEV_Q40IDE
extern void q40ide_init(void);
#endif
#ifdef CONFIG_BLK_DEV_BUDDHA
extern void buddha_init(void);
#endif
#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP)
extern void pnpide_init(int);
#endif
/* default maximum number of failures */
#define IDE_DEFAULT_MAX_FAILURES 1
int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
static int initializing; /* set while initializing built-in drivers */
static int idebus_parameter; /* the "idebus=" parameter */
/*
* Protects access to global structures etc.
*/
spinlock_t ide_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
#ifdef CONFIG_PCI
static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
#endif
#if defined(__mc68000__) || defined(CONFIG_APUS)
/*
* This is used by the Atari code to obtain access to the IDE interrupt,
* which is shared between several drivers.
*/
static int irq_lock;
#endif
int noautodma = 0;
/* Single linked list of sub device type drivers */
static struct ata_operations *ata_drivers; /* = NULL */
static spinlock_t ata_drivers_lock = SPIN_LOCK_UNLOCKED;
/*
* This is declared extern in ide.h, for access by other IDE modules:
*/
struct ata_channel ide_hwifs[MAX_HWIFS]; /* master data repository */
static void init_hwif_data(struct ata_channel *ch, unsigned int index)
{
static const unsigned int majors[] = {
IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR,
IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR
};
unsigned int unit;
hw_regs_t hw;
/* bulk initialize channel & drive info with zeros */
memset(ch, 0, sizeof(struct ata_channel));
memset(&hw, 0, sizeof(hw_regs_t));
/* fill in any non-zero initial values */
ch->index = index;
ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &ch->irq);
memcpy(&ch->hw, &hw, sizeof(hw));
memcpy(ch->io_ports, hw.io_ports, sizeof(hw.io_ports));
ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET];
#ifdef CONFIG_BLK_DEV_HD
if (ch->io_ports[IDE_DATA_OFFSET] == HD_DATA)
ch->noprobe = 1; /* may be overridden by ide_setup() */
#endif
ch->major = majors[index];
sprintf(ch->name, "ide%d", index);
ch->bus_state = BUSSTATE_ON;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &ch->drives[unit];
drive->type = ATA_DISK;
drive->select.all = (unit<<4)|0xa0;
drive->channel = ch;
drive->ctl = 0x08;
drive->ready_stat = READY_STAT;
drive->bad_wstat = BAD_W_STAT;
sprintf(drive->name, "hd%c", 'a' + (index * MAX_DRIVES) + unit);
drive->max_failures = IDE_DEFAULT_MAX_FAILURES;
init_waitqueue_head(&drive->wqueue);
}
}
extern struct block_device_operations ide_fops[];
/*
* This is called exactly *once* for each channel.
*/
void ide_geninit(struct ata_channel *ch)
{
unsigned int unit;
struct gendisk *gd = ch->gd;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &ch->drives[unit];
if (!drive->present)
continue;
if (drive->type != ATA_DISK && drive->type != ATA_FLOPPY)
continue;
register_disk(gd,mk_kdev(ch->major,unit<<PARTN_BITS),
#ifdef CONFIG_BLK_DEV_ISAPNP
(drive->forced_geom && drive->noprobe) ? 1 :
#endif
1 << PARTN_BITS, ide_fops, ata_capacity(drive));
}
}
/*
* Returns the (struct ata_device *) for a given device number. Return
* NULL if the given device number does not match any present drives.
*/
struct ata_device *get_info_ptr(kdev_t i_rdev)
{
unsigned int major = major(i_rdev);
int h;
for (h = 0; h < MAX_HWIFS; ++h) {
struct ata_channel *ch = &ide_hwifs[h];
if (ch->present && major == ch->major) {
int unit = DEVICE_NR(i_rdev);
if (unit < MAX_DRIVES) {
struct ata_device *drive = &ch->drives[unit];
if (drive->present)
return drive;
}
break;
}
}
return NULL;
}
/*
* This routine is called to flush all partitions and partition tables
* for a changed disk, and then re-read the new partition table.
* If we are revalidating a disk because of a media change, then we
* enter with usage == 0. If we are using an ioctl, we automatically have
* usage == 1 (we need an open channel to use an ioctl :-), so this
* is our limit.
*/
int ata_revalidate(kdev_t i_rdev)
{
struct ata_device *drive;
unsigned long flags;
int res;
if ((drive = get_info_ptr(i_rdev)) == NULL)
return -ENODEV;
/* FIXME: The locking here doesn't make the slightest sense! */
spin_lock_irqsave(&ide_lock, flags);
if (drive->busy || (drive->usage > 1)) {
spin_unlock_irqrestore(&ide_lock, flags);
return -EBUSY;
}
drive->busy = 1;
MOD_INC_USE_COUNT;
spin_unlock_irqrestore(&ide_lock, flags);
res = wipe_partitions(i_rdev);
if (!res) {
if (ata_ops(drive) && ata_ops(drive)->revalidate) {
ata_get(ata_ops(drive));
/* this is a no-op for tapes and SCSI based access */
ata_ops(drive)->revalidate(drive);
ata_put(ata_ops(drive));
} else
grok_partitions(i_rdev, ata_capacity(drive));
}
drive->busy = 0;
wake_up(&drive->wqueue);
MOD_DEC_USE_COUNT;
return res;
}
/*
* FIXME: this is most propably just totally unnecessary.
*
* Look again for all drives in the system on all interfaces.
*/
static void revalidate_drives(void)
{
int i;
for (i = 0; i < MAX_HWIFS; ++i) {
int unit;
struct ata_channel *ch = &ide_hwifs[i];
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &ch->drives[unit];
if (drive->revalidate) {
drive->revalidate = 0;
if (!initializing)
ata_revalidate(mk_kdev(ch->major, unit<<PARTN_BITS));
}
}
}
}
void ide_driver_module(void)
{
int i;
/* Don't reinit the probe if there is already one channel detected. */
for (i = 0; i < MAX_HWIFS; ++i) {
if (ide_hwifs[i].present)
goto revalidate;
}
ideprobe_init();
revalidate:
revalidate_drives();
}
void ide_unregister(struct ata_channel *ch)
{
struct gendisk *gd;
struct ata_device *d;
spinlock_t *lock;
int unit;
int i;
unsigned long flags;
unsigned int p, minor;
struct ata_channel old;
int n_irq;
int n_ch;
spin_lock_irqsave(&ide_lock, flags);
if (!ch->present)
goto abort;
put_device(&ch->dev);
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device * drive = &ch->drives[unit];
if (!drive->present)
continue;
if (drive->busy || drive->usage)
goto abort;
if (ata_ops(drive)) {
if (ata_ops(drive)->cleanup) {
if (ata_ops(drive)->cleanup(drive))
goto abort;
} else
ide_unregister_subdriver(drive);
}
}
ch->present = 0;
/*
* All clear? Then blow away the buffer cache
*/
spin_unlock_irqrestore(&ide_lock, flags);
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device * drive = &ch->drives[unit];
if (!drive->present)
continue;
minor = drive->select.b.unit << PARTN_BITS;
for (p = 0; p < (1<<PARTN_BITS); ++p) {
if (drive->part[p].nr_sects > 0) {
kdev_t devp = mk_kdev(ch->major, minor+p);
invalidate_device(devp, 0);
}
}
}
spin_lock_irqsave(&ide_lock, flags);
/*
* Note that we only release the standard ports, and do not even try to
* handle any extra ports allocated for weird IDE interface chipsets.
*/
if (ch->straight8) {
release_region(ch->io_ports[IDE_DATA_OFFSET], 8);
} else {
for (i = 0; i < 8; i++)
if (ch->io_ports[i])
release_region(ch->io_ports[i], 1);
}
if (ch->io_ports[IDE_CONTROL_OFFSET])
release_region(ch->io_ports[IDE_CONTROL_OFFSET], 1);
/* FIXME: check if we can remove this ifdef */
#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
if (ch->io_ports[IDE_IRQ_OFFSET])
release_region(ch->io_ports[IDE_IRQ_OFFSET], 1);
#endif
/*
* Remove us from the lock group.
*/
lock = ch->lock;
d = ch->drive;
for (i = 0; i < MAX_DRIVES; ++i) {
struct ata_device *drive = &ch->drives[i];
if (drive->de) {
devfs_unregister (drive->de);
drive->de = NULL;
}
if (!drive->present)
continue;
/* FIXME: possibly unneccessary */
if (ch->drive == drive)
ch->drive = NULL;
if (drive->id != NULL) {
kfree(drive->id);
drive->id = NULL;
}
drive->present = 0;
blk_cleanup_queue(&drive->queue);
}
if (d->present)
ch->drive = d;
/*
* Free the irq if we were the only channel using it.
*
* Free the lock group if we were the only member.
*/
n_irq = n_ch = 0;
for (i = 0; i < MAX_HWIFS; ++i) {
struct ata_channel *tmp = &ide_hwifs[i];
if (!tmp->present)
continue;
if (tmp->irq == ch->irq)
++n_irq;
if (tmp->lock == ch->lock)
++n_ch;
}
if (n_irq == 1)
free_irq(ch->irq, ch);
if (n_ch == 1) {
kfree(ch->lock);
kfree(ch->active);
ch->lock = NULL;
ch->active = NULL;
}
#ifdef CONFIG_BLK_DEV_IDEDMA
ide_release_dma(ch);
#endif
/*
* Remove us from the kernel's knowledge.
*/
unregister_blkdev(ch->major, ch->name);
blk_dev[ch->major].data = NULL;
blk_dev[ch->major].queue = NULL;
blk_clear(ch->major);
gd = ch->gd;
if (gd) {
del_gendisk(gd);
kfree(gd->sizes);
kfree(gd->part);
if (gd->de_arr)
kfree (gd->de_arr);
if (gd->flags)
kfree (gd->flags);
kfree(gd);
ch->gd = NULL;
}
/*
* Reinitialize the channel handler, but preserve any special methods for
* it.
*/
old = *ch;
init_hwif_data(ch, ch->index);
ch->lock = old.lock;
ch->tuneproc = old.tuneproc;
ch->speedproc = old.speedproc;
ch->selectproc = old.selectproc;
ch->resetproc = old.resetproc;
ch->intrproc = old.intrproc;
ch->maskproc = old.maskproc;
ch->quirkproc = old.quirkproc;
ch->ata_read = old.ata_read;
ch->ata_write = old.ata_write;
ch->atapi_read = old.atapi_read;
ch->atapi_write = old.atapi_write;
ch->XXX_udma = old.XXX_udma;
ch->udma_enable = old.udma_enable;
ch->udma_start = old.udma_start;
ch->udma_stop = old.udma_stop;
ch->udma_read = old.udma_read;
ch->udma_write = old.udma_write;
ch->udma_irq_status = old.udma_irq_status;
ch->udma_timeout = old.udma_timeout;
ch->udma_irq_lost = old.udma_irq_lost;
ch->busproc = old.busproc;
ch->bus_state = old.bus_state;
ch->dma_base = old.dma_base;
ch->dma_extra = old.dma_extra;
ch->config_data = old.config_data;
ch->select_data = old.select_data;
ch->proc = old.proc;
/* FIXME: most propably this is always right:! */
#ifndef CONFIG_BLK_DEV_IDECS
ch->irq = old.irq;
#endif
ch->major = old.major;
ch->chipset = old.chipset;
ch->autodma = old.autodma;
ch->udma_four = old.udma_four;
#ifdef CONFIG_PCI
ch->pci_dev = old.pci_dev;
#endif
ch->straight8 = old.straight8;
abort:
spin_unlock_irqrestore(&ide_lock, flags);
}
static int subdriver_match(struct ata_channel *channel, struct ata_operations *ops)
{
int count, unit;
if (!channel->present)
return 0;
count = 0;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &channel->drives[unit];
if (drive->present && !drive->driver) {
(*ops->attach)(drive);
if (drive->driver != NULL)
count++;
}
}
return count;
}
static struct ata_operations * subdriver_iterator(struct ata_operations *prev)
{
struct ata_operations *tmp;
unsigned long flags;
spin_lock_irqsave(&ata_drivers_lock, flags);
/* Restart from beginning if current ata_operations was deallocated,
or if prev is NULL. */
for(tmp = ata_drivers; tmp != prev && tmp; tmp = tmp->next);
if (!tmp)
tmp = ata_drivers;
else
tmp = tmp->next;
spin_unlock_irqrestore(&ata_drivers_lock, flags);
return tmp;
}
/*
* Register an IDE interface, specifing exactly the registers etc
* Set init=1 iff calling before probes have taken place.
*/
int ide_register_hw(hw_regs_t *hw, struct ata_channel **hwifp)
{
int h;
int retry = 1;
struct ata_channel *ch;
struct ata_operations *subdriver;
do {
for (h = 0; h < MAX_HWIFS; ++h) {
ch = &ide_hwifs[h];
if (ch->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
goto found;
}
for (h = 0; h < MAX_HWIFS; ++h) {
ch = &ide_hwifs[h];
if ((!ch->present && (ch->unit == ATA_PRIMARY) && !initializing) ||
(!ch->hw.io_ports[IDE_DATA_OFFSET] && initializing))
goto found;
}
for (h = 0; h < MAX_HWIFS; ++h)
ide_unregister(&ide_hwifs[h]);
} while (retry--);
return -1;
found:
ide_unregister(ch);
if (ch->present)
return -1;
memcpy(&ch->hw, hw, sizeof(*hw));
memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->hw.io_ports));
ch->irq = hw->irq;
ch->noprobe = 0;
ch->chipset = hw->chipset;
if (!initializing) {
ideprobe_init();
revalidate_drives();
/* FIXME: Do we really have to call it second time here?! */
ide_driver_module();
}
/* Look up whatever there is a subdriver, which will serve this
* device.
*/
subdriver = NULL;
while ((subdriver = subdriver_iterator(subdriver))) {
if (subdriver_match(ch, subdriver) > 0)
break;
}
if (hwifp)
*hwifp = ch;
return (initializing || ch->present) ? h : -1;
}
/****************************************************************************
* FIXME: rewrite the following crap:
*/
/*
* stridx() returns the offset of c within s,
* or -1 if c is '\0' or not found within s.
*/
static int __init stridx (const char *s, char c)
{
char *i = strchr(s, c);
return (i && c) ? i - s : -1;
}
/*
* Parsing for ide_setup():
*
* 1. the first char of s must be '='.
* 2. if the remainder matches one of the supplied keywords,
* the index (1 based) of the keyword is negated and returned.
* 3. if the remainder is a series of no more than max_vals numbers
* separated by commas, the numbers are saved in vals[] and a
* count of how many were saved is returned. Base10 is assumed,
* and base16 is allowed when prefixed with "0x".
* 4. otherwise, zero is returned.
*/
static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals)
{
static const char *decimal = "0123456789";
static const char *hex = "0123456789abcdef";
int i, n;
if (*s++ == '=') {
/*
* Try matching against the supplied keywords,
* and return -(index+1) if we match one
*/
if (keywords != NULL) {
for (i = 0; *keywords != NULL; ++i) {
if (!strcmp(s, *keywords++))
return -(i+1);
}
}
/*
* Look for a series of no more than "max_vals"
* numeric values separated by commas, in base10,
* or base16 when prefixed with "0x".
* Return a count of how many were found.
*/
for (n = 0; (i = stridx(decimal, *s)) >= 0;) {
vals[n] = i;
while ((i = stridx(decimal, *++s)) >= 0)
vals[n] = (vals[n] * 10) + i;
if (*s == 'x' && !vals[n]) {
while ((i = stridx(hex, *++s)) >= 0)
vals[n] = (vals[n] * 0x10) + i;
}
if (++n == max_vals)
break;
if (*s == ',' || *s == ';')
++s;
}
if (!*s)
return n;
}
return 0; /* zero = nothing matched */
}
/*
* This sets reasonable default values into all fields of all instances of the
* channles and drives, but only on the first call. Subsequent calls have no
* effect (they don't wipe out anything).
*
* This routine is normally called at driver initialization time, but may also
* be called MUCH earlier during kernel "command-line" parameter processing.
* As such, we cannot depend on any other parts of the kernel (such as memory
* allocation) to be functioning yet.
*
* This is too bad, as otherwise we could dynamically allocate the ata_device
* structs as needed, rather than always consuming memory for the max possible
* number (MAX_HWIFS * MAX_DRIVES) of them.
*/
#define MAGIC_COOKIE 0x12345678
static void __init init_global_data(void)
{
unsigned int h;
static unsigned long magic_cookie = MAGIC_COOKIE;
if (magic_cookie != MAGIC_COOKIE)
return; /* already initialized */
magic_cookie = 0;
/* Initialize all interface structures */
for (h = 0; h < MAX_HWIFS; ++h)
init_hwif_data(&ide_hwifs[h], h);
/* Add default hw interfaces */
ide_init_default_hwifs();
}
/*
* 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.
*
* Here is the complete set currently supported comand line options:
*
* "hdx=" is recognized for all "x" from "a" to "h", such as "hdc".
* "idex=" is recognized for all "x" from "0" to "3", such as "ide1".
*
* "hdx=noprobe" : drive may be present, but do not probe for it
* "hdx=none" : drive is NOT present, ignore cmos and do not probe
* "hdx=nowerr" : ignore the WRERR_STAT bit on this drive
* "hdx=cdrom" : drive is present, and is a cdrom drive
* "hdx=cyl,head,sect" : disk drive is present, with specified geometry
* "hdx=noremap" : do not remap 0->1 even though EZD was detected
* "hdx=autotune" : driver will attempt to tune interface speed
* to the fastest PIO mode supported,
* if possible for this drive only.
* Not fully supported by all chipset types,
* and quite likely to cause trouble with
* older/odd IDE drives.
*
* "hdx=slow" : insert a huge pause after each access to the data
* port. Should be used only as a last resort.
*
* "hdxlun=xx" : set the drive last logical unit.
* "hdx=flash" : allows for more than one ata_flash disk to be
* registered. In most cases, only one device
* will be present.
* "hdx=ide-scsi" : the return of the ide-scsi flag, this is useful for
* allowwing ide-floppy, ide-tape, and ide-cdrom|writers
* to use ide-scsi emulation on a device specific option.
* "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz,
* where "xx" is between 20 and 66 inclusive,
* used when tuning chipset PIO modes.
* For PCI bus, 25 is correct for a P75 system,
* 30 is correct for P90,P120,P180 systems,
* and 33 is used for P100,P133,P166 systems.
* If in doubt, use idebus=33 for PCI.
* As for VLB, it is safest to not specify it.
*
* "idex=noprobe" : do not attempt to access/use this interface
* "idex=base" : probe for an interface at the address specified,
* where "base" is usually 0x1f0 or 0x170
* and "ctl" is assumed to be "base"+0x206
* "idex=base,ctl" : specify both base and ctl
* "idex=base,ctl,irq" : specify base, ctl, and irq number
* "idex=autotune" : driver will attempt to tune interface speed
* to the fastest PIO mode supported,
* for all drives on this interface.
* Not fully supported by all chipset types,
* and quite likely to cause trouble with
* older/odd IDE drives.
* "idex=noautotune" : driver will NOT attempt to tune interface speed
* This is the default for most chipsets,
* except the cmd640.
* "idex=serialize" : do not overlap operations on idex and ide(x^1)
* "idex=four" : four drives on idex and ide(x^1) share same ports
* "idex=reset" : reset interface before first use
* "idex=dma" : enable DMA by default on both drives if possible
* "idex=ata66" : informs the interface that it has an 80c cable
* for chipsets that are ATA-66 capable, but
* the ablity to bit test for detection is
* currently unknown.
* "ide=reverse" : Formerly called to pci sub-system, but now local.
*
* The following are valid ONLY on ide0, (except dc4030)
* and the defaults for the base,ctl ports must not be altered.
*
* "ide0=dtc2278" : probe/support DTC2278 interface
* "ide0=ht6560b" : probe/support HT6560B interface
* "ide0=cmd640_vlb" : *REQUIRED* for VLB cards with the CMD640 chip
* (not for PCI -- automatically detected)
* "ide0=qd65xx" : probe/support qd65xx interface
* "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445)
* "ide0=umc8672" : probe/support umc8672 chipsets
* "idex=dc4030" : probe/support Promise DC4030VL interface
* "ide=doubler" : probe/support IDE doublers on Amiga
*/
int __init ide_setup(char *s)
{
int i, vals[3];
struct ata_channel *ch;
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 */
return 0;
if (strncmp(s,"ide",3) &&
strncmp(s,"idebus",6) &&
strncmp(s,"hd",2)) /* hdx= & hdxlun= */
return 0;
printk(KERN_INFO "ide_setup: %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",
"serialize", "autotune", "noautotune",
"slow", "flash", "remap", "noremap", "scsi", NULL};
unit = s[2] - 'a';
hw = unit / MAX_DRIVES;
unit = unit % MAX_DRIVES;
ch = &ide_hwifs[hw];
drive = &ch->drives[unit];
if (!strncmp(s + 4, "ide-", 4)) {
strncpy(drive->driver_req, s + 4, 9);
goto done;
}
/*
* Look for last lun option: "hdxlun="
*/
if (!strncmp(&s[3], "lun", 3)) {
if (match_parm(&s[6], NULL, vals, 1) != 1)
goto bad_option;
if (vals[0] >= 0 && vals[0] <= 7) {
drive->last_lun = vals[0];
drive->forced_lun = 1;
} else
printk(" -- BAD LAST LUN! Expected value from 0 to 7");
goto done;
}
switch (match_parm(&s[3], hd_words, vals, 3)) {
case -1: /* "none" */
drive->nobios = 1; /* drop into "noprobe" */
case -2: /* "noprobe" */
drive->noprobe = 1;
goto done;
case -3: /* "nowerr" */
drive->bad_wstat = BAD_R_STAT;
ch->noprobe = 0;
goto done;
case -4: /* "cdrom" */
drive->present = 1;
drive->type = ATA_ROM;
ch->noprobe = 0;
goto done;
case -5: /* "serialize" */
printk(" -- USE \"ide%d=serialize\" INSTEAD", hw);
goto do_serialize;
case -6: /* "autotune" */
drive->autotune = 1;
goto done;
case -7: /* "noautotune" */
drive->autotune = 2;
goto done;
case -8: /* "slow" */
ch->slow = 1;
goto done;
case -9: /* "flash" */
drive->ata_flash = 1;
goto done;
case -10: /* "remap" */
drive->remap_0_to_1 = 1;
goto done;
case -11: /* "noremap" */
drive->remap_0_to_1 = 2;
goto done;
case -12: /* "scsi" */
#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI)
drive->scsi = 1;
goto done;
#else
drive->scsi = 0;
goto bad_option;
#endif
case 3: /* cyl,head,sect */
drive->type = ATA_DISK;
drive->cyl = drive->bios_cyl = vals[0];
drive->head = drive->bios_head = vals[1];
drive->sect = drive->bios_sect = vals[2];
drive->present = 1;
drive->forced_geom = 1;
ch->noprobe = 0;
goto done;
default:
goto bad_option;
}
}
/*
* Look for bus speed option: "idebus="
*/
if (!strncmp(s, "idebus", 6)) {
if (match_parm(&s[6], NULL, vals, 1) != 1)
goto bad_option;
idebus_parameter = vals[0];
goto done;
}
/*
* Look for interface options: "idex="
*/
if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_ch) {
/*
* Be VERY CAREFUL changing this: note hardcoded indexes below
* -8,-9,-10. -11 : are reserved for future idex calls to ease the hardcoding.
*/
const char *ide_words[] = {
"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66",
"minus8", "minus9", "minus10", "minus11",
"qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
hw = s[3] - '0';
ch = &ide_hwifs[hw];
i = match_parm(&s[4], ide_words, vals, 3);
/*
* Cryptic check to ensure chipset not already set for a channel:
*/
if (i > 0 || i <= -11) { /* is parameter a chipset name? */
if (ch->chipset != ide_unknown)
goto bad_option; /* chipset already specified */
if (i <= -11 && i != -18 && hw != 0)
goto bad_channel; /* chipset drivers are for "ide0=" only */
if (i <= -11 && i != -18 && ide_hwifs[hw+1].chipset != ide_unknown)
goto bad_option; /* chipset for 2nd port already specified */
printk("\n");
}
switch (i) {
#ifdef CONFIG_BLK_DEV_PDC4030
case -18: /* "dc4030" */
{
extern void init_pdc4030(void);
init_pdc4030();
goto done;
}
#endif
#ifdef CONFIG_BLK_DEV_ALI14XX
case -17: /* "ali14xx" */
{
extern void init_ali14xx (void);
init_ali14xx();
goto done;
}
#endif
#ifdef CONFIG_BLK_DEV_UMC8672
case -16: /* "umc8672" */
{
extern void init_umc8672 (void);
init_umc8672();
goto done;
}
#endif
#ifdef CONFIG_BLK_DEV_DTC2278
case -15: /* "dtc2278" */
{
extern void init_dtc2278 (void);
init_dtc2278();
goto done;
}
#endif
#ifdef CONFIG_BLK_DEV_CMD640
case -14: /* "cmd640_vlb" */
{
extern int cmd640_vlb; /* flag for cmd640.c */
cmd640_vlb = 1;
goto done;
}
#endif
#ifdef CONFIG_BLK_DEV_HT6560B
case -13: /* "ht6560b" */
{
extern void init_ht6560b (void);
init_ht6560b();
goto done;
}
#endif
#if CONFIG_BLK_DEV_QD65XX
case -12: /* "qd65xx" */
{
extern void init_qd65xx (void);
init_qd65xx();
goto done;
}
#endif
case -11: /* minus11 */
case -10: /* minus10 */
case -9: /* minus9 */
case -8: /* minus8 */
goto bad_option;
case -7: /* ata66 */
#ifdef CONFIG_PCI
ch->udma_four = 1;
goto done;
#else
ch->udma_four = 0;
goto bad_channel;
#endif
case -6: /* dma */
ch->autodma = 1;
goto done;
case -5: /* "reset" */
ch->reset = 1;
goto done;
case -4: /* "noautotune" */
ch->drives[0].autotune = 2;
ch->drives[1].autotune = 2;
goto done;
case -3: /* "autotune" */
ch->drives[0].autotune = 1;
ch->drives[1].autotune = 1;
goto done;
case -2: /* "serialize" */
do_serialize:
{
struct ata_channel *mate;
mate = &ide_hwifs[hw ^ 1];
ch->serialized = 1;
mate->serialized = 1;
}
goto done;
case -1: /* "noprobe" */
ch->noprobe = 1;
goto done;
case 1: /* base */
vals[1] = vals[0] + 0x206; /* default ctl */
case 2: /* base,ctl */
vals[2] = 0; /* default irq = probe for it */
case 3: /* base,ctl,irq */
ch->hw.irq = vals[2];
ide_init_hwif_ports(&ch->hw, (ide_ioreg_t) vals[0], (ide_ioreg_t) vals[1], &ch->irq);
memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->io_ports));
ch->irq = vals[2];
ch->noprobe = 0;
ch->chipset = ide_generic;
goto done;
case 0:
goto bad_option;
default:
printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n");
return 1;
}
}
bad_option:
printk(" -- BAD OPTION\n");
return 1;
bad_channel:
printk("-- NOT SUPPORTED ON ide%d", hw);
done:
printk("\n");
return 1;
}
/****************************************************************************/
/*
* This is in fact registering a device not a driver.
*/
int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driver)
{
unsigned long flags;
save_flags(flags); /* all CPUs */
cli(); /* all CPUs */
if (!drive->present || drive->driver != NULL || drive->busy || drive->usage) {
restore_flags(flags); /* all CPUs */
return 1;
}
/* FIXME: This will be pushed to the drivers! Thus allowing us to
* save one parameter here separate this out.
*/
drive->driver = driver;
restore_flags(flags); /* all CPUs */
/* FIXME: Check what this magic number is supposed to be about? */
if (drive->autotune != 2) {
if (drive->channel->XXX_udma) {
/*
* Force DMAing for the beginning of the check. Some
* chipsets appear to do interesting things, if not
* checked and cleared.
*
* PARANOIA!!!
*/
udma_enable(drive, 0, 0);
drive->channel->XXX_udma(drive);
#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
udma_tcq_enable(drive, 1);
#endif
}
/* Only CD-ROMs and tape drives support DSC overlap. But only
* if they are alone on a channel. */
if (drive->type == ATA_ROM || drive->type == ATA_TAPE) {
int single = 0;
int unit;
for (unit = 0; unit < MAX_DRIVES; ++unit)
if (drive->channel->drives[unit].present)
++single;
drive->dsc_overlap = (single == 1);
} else
drive->dsc_overlap = 0;
}
drive->revalidate = 1;
drive->suspend_reset = 0;
return 0;
}
/*
* This is in fact the default cleanup routine.
*
* FIXME: Check whatever we maybe don't call it twice!.
*/
int ide_unregister_subdriver(struct ata_device *drive)
{
unsigned long flags;
save_flags(flags); /* all CPUs */
cli(); /* all CPUs */
#if 0
if (__MOD_IN_USE(ata_ops(drive)->owner)) {
restore_flags(flags);
return 1;
}
#endif
if (drive->usage || drive->busy || !ata_ops(drive)) {
restore_flags(flags); /* all CPUs */
return 1;
}
#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE)
pnpide_init(0);
#endif
drive->driver = NULL;
restore_flags(flags); /* all CPUs */
return 0;
}
/*
* Register an ATA subdriver for a particular device type.
*/
int register_ata_driver(struct ata_operations *driver)
{
unsigned long flags;
int index;
int count = 0;
spin_lock_irqsave(&ata_drivers_lock, flags);
driver->next = ata_drivers;
ata_drivers = driver;
spin_unlock_irqrestore(&ata_drivers_lock, flags);
for (index = 0; index < MAX_HWIFS; ++index)
count += subdriver_match(&ide_hwifs[index], driver);
return count;
}
EXPORT_SYMBOL(register_ata_driver);
/*
* Unregister an ATA subdriver for a particular device type.
*/
void unregister_ata_driver(struct ata_operations *driver)
{
struct ata_operations **tmp;
unsigned long flags;
int index;
int unit;
spin_lock_irqsave(&ata_drivers_lock, flags);
for (tmp = &ata_drivers; *tmp != NULL; tmp = &(*tmp)->next) {
if (*tmp == driver) {
*tmp = driver->next;
break;
}
}
spin_unlock_irqrestore(&ata_drivers_lock, flags);
for (index = 0; index < MAX_HWIFS; ++index) {
struct ata_channel *ch = &ide_hwifs[index];
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &ch->drives[unit];
if (drive->driver == driver)
(*ata_ops(drive)->cleanup)(drive);
}
}
}
EXPORT_SYMBOL(unregister_ata_driver);
EXPORT_SYMBOL(ide_hwifs);
EXPORT_SYMBOL(ide_lock);
devfs_handle_t ide_devfs_handle;
EXPORT_SYMBOL(ide_register_subdriver);
EXPORT_SYMBOL(ide_unregister_subdriver);
EXPORT_SYMBOL(ata_revalidate);
EXPORT_SYMBOL(ide_register_hw);
EXPORT_SYMBOL(ide_unregister);
EXPORT_SYMBOL(get_info_ptr);
/*
* Handle power handling related events ths system informs us about.
*/
static int ata_sys_notify(struct notifier_block *this, unsigned long event, void *x)
{
int i;
switch (event) {
case SYS_HALT:
case SYS_POWER_OFF:
case SYS_RESTART:
break;
default:
return NOTIFY_DONE;
}
printk("flushing ide devices: ");
for (i = 0; i < MAX_HWIFS; i++) {
int unit;
struct ata_channel *ch = &ide_hwifs[i];
if (!ch->present)
continue;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &ch->drives[unit];
if (!drive->present)
continue;
/* set the drive to standby */
printk("%s ", drive->name);
if (ata_ops(drive)) {
if (event != SYS_RESTART)
if (ata_ops(drive)->standby && ata_ops(drive)->standby(drive))
continue;
if (ata_ops(drive)->cleanup)
ata_ops(drive)->cleanup(drive);
}
}
}
printk("\n");
return NOTIFY_DONE;
}
static struct notifier_block ata_notifier = {
ata_sys_notify,
NULL,
5
};
/*
* This is the global initialization entry point.
*/
static int __init ata_module_init(void)
{
int h;
printk(KERN_INFO "ATA/ATAPI device driver v" VERSION "\n");
ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL);
/*
* Because most of the ATA adapters represent the timings in unit of
* bus clocks, and there is no known reliable way to detect the bus
* clock frequency, we assume 50 MHz for non-PCI (VLB, EISA) and 33 MHz
* for PCI based systems. Since assuming only hurts performance and not
* stability, this is OK. The user can change this on the command line
* by using the "idebus=XX" parameter. While the system_bus_speed
* variable is in kHz units, we accept both MHz and kHz entry on the
* command line for backward compatibility.
*/
system_bus_speed = 50000;
if (pci_present())
system_bus_speed = 33333;
if (idebus_parameter >= 20 && idebus_parameter <= 80) {
system_bus_speed = idebus_parameter * 1000;
switch (system_bus_speed) {
case 33000: system_bus_speed = 33333; break;
case 37000: system_bus_speed = 37500; break;
case 41000: system_bus_speed = 41666; break;
case 66000: system_bus_speed = 66666; break;
}
}
if (idebus_parameter >= 20000 && idebus_parameter <= 80000)
system_bus_speed = idebus_parameter;
printk(KERN_INFO "ATA: %s bus speed %d.%dMHz\n",
pci_present() ? "PCI" : "System", system_bus_speed / 1000, system_bus_speed / 100 % 10);
init_global_data();
initializing = 1;
#ifdef CONFIG_PCI
/*
* Register the host chip drivers.
*/
# ifdef CONFIG_BLK_DEV_PIIX
init_piix();
# endif
# ifdef CONFIG_BLK_DEV_VIA82CXXX
init_via82cxxx();
# endif
# ifdef CONFIG_BLK_DEV_PDC202XX
init_pdc202xx();
# endif
# ifdef CONFIG_BLK_DEV_RZ1000
init_rz1000();
# endif
# ifdef CONFIG_BLK_DEV_SIS5513
init_sis5513();
# endif
# ifdef CONFIG_BLK_DEV_CMD64X
init_cmd64x();
# endif
# ifdef CONFIG_BLK_DEV_OPTI621
init_opti621();
# endif
# ifdef CONFIG_BLK_DEV_TRM290
init_trm290();
# endif
# ifdef CONFIG_BLK_DEV_NS87415
init_ns87415();
# endif
# ifdef CONFIG_BLK_DEV_AEC62XX
init_aec62xx();
# endif
# ifdef CONFIG_BLK_DEV_SL82C105
init_sl82c105();
# endif
# ifdef CONFIG_BLK_DEV_HPT34X
init_hpt34x();
# endif
# ifdef CONFIG_BLK_DEV_HPT366
init_hpt366();
# endif
# ifdef CONFIG_BLK_DEV_ALI15X3
init_ali15x3();
# endif
# ifdef CONFIG_BLK_DEV_CY82C693
init_cy82c693();
# endif
# ifdef CONFIG_BLK_DEV_CS5530
init_cs5530();
# endif
# ifdef CONFIG_BLK_DEV_AMD74XX
init_amd74xx();
# endif
# ifdef CONFIG_BLK_DEV_SVWKS
init_svwks();
# endif
# ifdef CONFIG_BLK_DEV_IT8172
init_it8172();
# endif
init_ata_pci_misc();
/*
* Detect and initialize "known" IDE host chip types.
*/
if (pci_present()) {
# ifdef CONFIG_PCI
ide_scan_pcibus(ide_scan_direction);
# else
# ifdef CONFIG_BLK_DEV_RZ1000
ide_probe_for_rz100x();
# endif
# endif
}
#endif
#ifdef CONFIG_ETRAX_IDE
init_e100_ide();
#endif
#ifdef CONFIG_BLK_DEV_CMD640
ide_probe_for_cmd640x();
#endif
#ifdef CONFIG_BLK_DEV_PDC4030
ide_probe_for_pdc4030();
#endif
#ifdef CONFIG_BLK_DEV_IDE_PMAC
pmac_ide_probe();
#endif
#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
icside_init();
#endif
#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
rapide_init();
#endif
#ifdef CONFIG_BLK_DEV_GAYLE
gayle_init();
#endif
#ifdef CONFIG_BLK_DEV_FALCON_IDE
falconide_init();
#endif
#ifdef CONFIG_BLK_DEV_MAC_IDE
macide_init();
#endif
#ifdef CONFIG_BLK_DEV_Q40IDE
q40ide_init();
#endif
#ifdef CONFIG_BLK_DEV_BUDDHA
buddha_init();
#endif
#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP)
pnpide_init(1);
#endif
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
# if defined(__mc68000__) || defined(CONFIG_APUS)
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
// ide_get_lock(&irq_lock, NULL, NULL);/* for atari only */
disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */
// disable_irq_nosync(ide_hwifs[0].irq);
}
# endif
ideprobe_init();
# if defined(__mc68000__) || defined(CONFIG_APUS)
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
enable_irq(ide_hwifs[0].irq);
ide_release_lock(&irq_lock);/* for atari only */
}
# endif
#endif
/*
* Initialize all device type driver modules.
*/
#ifdef CONFIG_BLK_DEV_IDEDISK
idedisk_init();
#endif
#ifdef CONFIG_BLK_DEV_IDECD
ide_cdrom_init();
#endif
#ifdef CONFIG_BLK_DEV_IDETAPE
idetape_init();
#endif
#ifdef CONFIG_BLK_DEV_IDEFLOPPY
idefloppy_init();
#endif
#ifdef CONFIG_BLK_DEV_IDESCSI
# ifdef CONFIG_SCSI
idescsi_init();
# else
#error ATA SCSI emulation selected but no SCSI-subsystem in kernel
# endif
#endif
initializing = 0;
for (h = 0; h < MAX_HWIFS; ++h) {
struct ata_channel *channel = &ide_hwifs[h];
if (channel->present)
ide_geninit(channel);
}
register_reboot_notifier(&ata_notifier);
return 0;
}
static char *options = NULL;
static int __init init_ata(void)
{
if (options != NULL && *options) {
char *next = options;
while ((options = next) != NULL) {
if ((next = strchr(options,' ')) != NULL)
*next++ = 0;
if (!ide_setup(options))
printk(KERN_ERR "Unknown option '%s'\n", options);
}
}
return ata_module_init();
}
static void __exit cleanup_ata(void)
{
int h;
unregister_reboot_notifier(&ata_notifier);
for (h = 0; h < MAX_HWIFS; ++h) {
ide_unregister(&ide_hwifs[h]);
}
devfs_unregister(ide_devfs_handle);
}
module_init(init_ata);
module_exit(cleanup_ata);
#ifndef MODULE
/* command line option parser */
__setup("", ide_setup);
#endif
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
* Samuel Thibault <samuel.thibault@fnac.net> * Samuel Thibault <samuel.thibault@fnac.net>
*/ */
#include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -84,7 +85,7 @@ ...@@ -84,7 +85,7 @@
static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
static void qd_write_reg (byte content, byte reg) static void qd_write_reg(byte content, byte reg)
{ {
unsigned long flags; unsigned long flags;
...@@ -94,7 +95,7 @@ static void qd_write_reg (byte content, byte reg) ...@@ -94,7 +95,7 @@ static void qd_write_reg (byte content, byte reg)
restore_flags(flags); /* all CPUs */ restore_flags(flags); /* all CPUs */
} }
byte __init qd_read_reg (byte reg) byte __init qd_read_reg(byte reg)
{ {
unsigned long flags; unsigned long flags;
byte read; byte read;
...@@ -150,10 +151,10 @@ static byte qd6500_compute_timing(struct ata_channel *hwif, int active_time, int ...@@ -150,10 +151,10 @@ static byte qd6500_compute_timing(struct ata_channel *hwif, int active_time, int
* idem for qd6580 * idem for qd6580
*/ */
static byte qd6580_compute_timing (int active_time, int recovery_time) static byte qd6580_compute_timing(int active_time, int recovery_time)
{ {
byte active_cycle = 17-IDE_IN(active_time * system_bus_speed / 1000000 + 1, 2, 17); byte active_cycle = 17 - IDE_IN(active_time * system_bus_speed / 1000000 + 1, 2, 17);
byte recovery_cycle = 15-IDE_IN(recovery_time * system_bus_speed / 1000000 + 1, 2, 15); byte recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_speed / 1000000 + 1, 2, 15);
return((recovery_cycle<<4) | active_cycle); return((recovery_cycle<<4) | active_cycle);
} }
...@@ -176,8 +177,8 @@ static int qd_find_disk_type(struct ata_device *drive, ...@@ -176,8 +177,8 @@ static int qd_find_disk_type(struct ata_device *drive,
ide_fixstring(model,40,1); /* byte-swap */ ide_fixstring(model,40,1); /* byte-swap */
for (p = qd65xx_timing ; p->offset != -1 ; p++) { for (p = qd65xx_timing ; p->offset != -1 ; p++) {
if (!strncmp(p->model, model+p->offset,4)) { if (!strncmp(p->model, model+p->offset, 4)) {
printk(KERN_DEBUG "%s: listed !\n",drive->name); printk(KERN_DEBUG "%s: listed !\n", drive->name);
*active_time = p->active; *active_time = p->active;
*recovery_time = p->recovery; *recovery_time = p->recovery;
return 1; return 1;
...@@ -218,7 +219,7 @@ static void qd_set_timing(struct ata_device *drive, byte timing) ...@@ -218,7 +219,7 @@ static void qd_set_timing(struct ata_device *drive, byte timing)
} else } else
hwif->selectproc = &qd_select; hwif->selectproc = &qd_select;
printk(KERN_DEBUG "%s: %#x\n",drive->name,timing); printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
} }
/* /*
...@@ -230,17 +231,16 @@ static void qd6500_tune_drive(struct ata_device *drive, byte pio) ...@@ -230,17 +231,16 @@ static void qd6500_tune_drive(struct ata_device *drive, byte pio)
int active_time = 175; int active_time = 175;
int recovery_time = 415; /* worst case values from the dos driver */ int recovery_time = 415; /* worst case values from the dos driver */
if (drive->id && !qd_find_disk_type(drive,&active_time,&recovery_time) if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)
&& drive->id->tPIO && (drive->id->field_valid & 0x02) && drive->id->tPIO && (drive->id->field_valid & 0x02)
&& drive->id->eide_pio >= 240) { && drive->id->eide_pio >= 240) {
printk(KERN_INFO "%s: PIO mode%d\n", drive->name, printk(KERN_INFO "%s: PIO mode%d\n", drive->name, drive->id->tPIO);
drive->id->tPIO);
active_time = 110; active_time = 110;
recovery_time = drive->id->eide_pio - 120; recovery_time = drive->id->eide_pio - 120;
} }
qd_set_timing(drive,qd6500_compute_timing(drive->channel, active_time,recovery_time)); qd_set_timing(drive, qd6500_compute_timing(drive->channel, active_time, recovery_time));
} }
/* /*
...@@ -254,7 +254,7 @@ static void qd6580_tune_drive(struct ata_device *drive, byte pio) ...@@ -254,7 +254,7 @@ static void qd6580_tune_drive(struct ata_device *drive, byte pio)
int active_time = 175; int active_time = 175;
int recovery_time = 415; /* worst case values from the dos driver */ int recovery_time = 415; /* worst case values from the dos driver */
if (drive->id && !qd_find_disk_type(drive,&active_time,&recovery_time)) { if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
if (pio == 255) if (pio == 255)
pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
...@@ -268,14 +268,14 @@ static void qd6580_tune_drive(struct ata_device *drive, byte pio) ...@@ -268,14 +268,14 @@ static void qd6580_tune_drive(struct ata_device *drive, byte pio)
case 3: case 3:
if (t->cycle >= 110) { if (t->cycle >= 110) {
active_time = 86; active_time = 86;
recovery_time = t->cycle-102; recovery_time = t->cycle - 102;
} else } else
printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name);
break; break;
case 4: case 4:
if (t->cycle >= 69) { if (t->cycle >= 69) {
active_time = 70; active_time = 70;
recovery_time = t->cycle-61; recovery_time = t->cycle - 61;
} else } else
printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name); printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name);
break; break;
...@@ -292,11 +292,11 @@ static void qd6580_tune_drive(struct ata_device *drive, byte pio) ...@@ -292,11 +292,11 @@ static void qd6580_tune_drive(struct ata_device *drive, byte pio)
} }
if (!drive->channel->unit && drive->type != ATA_DISK) { if (!drive->channel->unit && drive->type != ATA_DISK) {
qd_write_reg(0x5f,QD_CONTROL_PORT); qd_write_reg(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); printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n", drive->name, drive->channel->name);
} }
qd_set_timing(drive,qd6580_compute_timing(active_time,recovery_time)); qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time));
} }
/* /*
...@@ -314,9 +314,9 @@ static int __init qd_testreg(int port) ...@@ -314,9 +314,9 @@ static int __init qd_testreg(int port)
save_flags(flags); /* all CPUs */ save_flags(flags); /* all CPUs */
cli(); /* all CPUs */ cli(); /* all CPUs */
savereg = inb_p(port); savereg = inb_p(port);
outb_p(QD_TESTVAL,port); /* safe value */ outb_p(QD_TESTVAL, port); /* safe value */
readreg = inb_p(port); readreg = inb_p(port);
outb(savereg,port); outb(savereg, port);
restore_flags(flags); /* all CPUs */ restore_flags(flags); /* all CPUs */
if (savereg == QD_TESTVAL) { if (savereg == QD_TESTVAL) {
...@@ -330,53 +330,95 @@ static int __init qd_testreg(int port) ...@@ -330,53 +330,95 @@ static int __init qd_testreg(int port)
} }
/* /*
* probe: * qd_setup:
*
* called to setup an ata channel : adjusts attributes & links for tuning
*/
void __init qd_setup(int unit, int base, int config, unsigned int data0, unsigned int data1, void (*tuneproc) (struct ata_device *, byte pio))
{
struct ata_channel *hwif = &ide_hwifs[unit];
hwif->chipset = ide_qd65xx;
hwif->unit = unit;
hwif->select_data = base;
hwif->config_data = config;
hwif->drives[0].drive_data = data0;
hwif->drives[1].drive_data = data1;
hwif->io_32bit = 1;
hwif->tuneproc = tuneproc;
}
/*
* qd_unsetup:
*
* called to unsetup an ata channel : back to default values, unlinks tuning
*/
void __init qd_unsetup(int unit) {
struct ata_channel *hwif = &ide_hwifs[unit];
byte config = hwif->config_data;
int base = hwif->select_data;
void *tuneproc = (void *) hwif->tuneproc;
if (!(hwif->chipset == ide_qd65xx)) return;
printk(KERN_NOTICE "%s: back to defaults\n", hwif->name);
hwif->selectproc = NULL;
hwif->tuneproc = NULL;
if (tuneproc == (void *) qd6500_tune_drive) {
// will do it for both
qd_write_reg(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]));
} else {
qd_write_reg(unit?QD6580_DEF_DATA2:QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
}
} else {
printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n");
printk(KERN_WARNING "keeping settings !\n");
}
}
/*
* qd_probe:
* *
* looks at the specified baseport, and if qd found, registers & initialises it * looks at the specified baseport, and if qd found, registers & initialises it
* return 1 if another qd may be probed * return 1 if another qd may be probed
*/ */
int __init probe (int base) int __init qd_probe(int base)
{ {
byte config; byte config;
byte index; int unit;
config = qd_read_reg(QD_CONFIG_PORT); config = qd_read_reg(QD_CONFIG_PORT);
if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) return 1; if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) return 1;
index = ! (config & QD_CONFIG_IDE_BASEPORT); unit = ! (config & QD_CONFIG_IDE_BASEPORT);
if ((config & 0xf0) == QD_CONFIG_QD6500) { if ((config & 0xf0) == QD_CONFIG_QD6500) {
struct ata_channel *hwif = &ide_hwifs[index];
if (qd_testreg(base)) return 1; /* bad register */ if (qd_testreg(base)) return 1; /* bad register */
/* qd6500 found */ /* qd6500 found */
printk(KERN_NOTICE "%s: qd6500 at %#x\n", printk(KERN_NOTICE "%s: qd6500 at %#x\n", ide_hwifs[unit].name, base);
ide_hwifs[index].name, base); printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n", config, QD_ID3);
printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
config, QD_ID3);
if (config & QD_CONFIG_DISABLED) { if (config & QD_CONFIG_DISABLED) {
printk(KERN_WARNING "qd6500 is disabled !\n"); printk(KERN_WARNING "qd6500 is disabled !\n");
return 1; return 1;
} }
hwif->chipset = ide_qd65xx; qd_setup(unit, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA, &qd6500_tune_drive);
hwif->select_data = base;
hwif->config_data = config;
hwif->drives[0].drive_data =
hwif->drives[1].drive_data = QD6500_DEF_DATA;
hwif->io_32bit = 1;
hwif->tuneproc = &qd6500_tune_drive;
return 1; return 1;
} }
if (((config & 0xf0) == QD_CONFIG_QD6580_A) || ((config & 0xf0) == QD_CONFIG_QD6580_B)) { if (((config & 0xf0) == QD_CONFIG_QD6580_A) || ((config & 0xf0) == QD_CONFIG_QD6580_B)) {
byte control; byte control;
if (qd_testreg(base) || qd_testreg(base+0x02)) return 1; if (qd_testreg(base) || qd_testreg(base+0x02)) return 1;
...@@ -387,52 +429,22 @@ int __init probe (int base) ...@@ -387,52 +429,22 @@ int __init probe (int base)
control = qd_read_reg(QD_CONTROL_PORT); control = qd_read_reg(QD_CONTROL_PORT);
printk(KERN_NOTICE "qd6580 at %#x\n", base); printk(KERN_NOTICE "qd6580 at %#x\n", base);
printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", config, control, QD_ID3);
config, control, QD_ID3);
if (control & QD_CONTR_SEC_DISABLED) { if (control & QD_CONTR_SEC_DISABLED) {
struct ata_channel *hwif = &ide_hwifs[index];
/* secondary disabled */ /* secondary disabled */
printk(KERN_INFO "%s: qd6580: single IDE board\n", printk(KERN_INFO "%s: qd6580: single IDE board\n", ide_hwifs[unit].name);
ide_hwifs[index].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);
hwif->chipset = ide_qd65xx;
hwif->select_data = base;
hwif->config_data = config | (control <<8);
hwif->drives[0].drive_data =
hwif->drives[1].drive_data = QD6580_DEF_DATA;
hwif->io_32bit = 1;
hwif->tuneproc = &qd6580_tune_drive;
qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT);
return 1; return 1;
} else { } else {
int i;
/* secondary enabled */ /* secondary enabled */
printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n", printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n", ide_hwifs[0].name, ide_hwifs[1].name);
ide_hwifs[0].name,ide_hwifs[1].name);
for (i = 0; i < 2; i++) {
int j;
ide_hwifs[i].chipset = ide_qd65xx;
ide_hwifs[i].unit = i;
ide_hwifs[i].select_data = base; qd_setup(ATA_PRIMARY, base, config | (control << 8), QD6580_DEF_DATA, QD6580_DEF_DATA, &qd6580_tune_drive);
ide_hwifs[i].config_data = config | (control <<8); qd_setup(ATA_SECONDARY, base, config | (control << 8), QD6580_DEF_DATA2, QD6580_DEF_DATA2, &qd6580_tune_drive);
ide_hwifs[i].tuneproc = &qd6580_tune_drive; qd_write_reg(QD_DEF_CONTR, QD_CONTROL_PORT);
ide_hwifs[i].io_32bit = 1;
for (j = 0; j < 2; j++) {
ide_hwifs[i].drives[j].drive_data =
i?QD6580_DEF_DATA2:QD6580_DEF_DATA;
}
}
qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT);
return 0; /* no other qd65xx possible */ return 0; /* no other qd65xx possible */
} }
...@@ -441,13 +453,36 @@ int __init probe (int base) ...@@ -441,13 +453,36 @@ int __init probe (int base)
return 1; return 1;
} }
#ifndef MODULE
/* /*
* init_qd65xx: * init_qd65xx:
* *
* called at the very beginning of initialization ; should just probe and link * called by ide.c when parsing command line
*/ */
void __init init_qd65xx (void) void __init init_qd65xx(void)
{
if (qd_probe(0x30)) qd_probe(0xb0);
}
#else
MODULE_AUTHOR("Samuel Thibault");
MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
MODULE_LICENSE("GPL");
int __init qd65xx_mod_init(void)
{
if (qd_probe(0x30)) qd_probe(0xb0);
if (ide_hwifs[0].chipset != ide_qd65xx && ide_hwifs[1].chipset != ide_qd65xx) return -ENODEV;
return 0;
}
module_init(qd65xx_mod_init);
void __init qd65xx_mod_exit(void)
{ {
if (probe(0x30)) probe(0xb0); qd_unsetup(ATA_PRIMARY);
qd_unsetup(ATA_SECONDARY);
} }
module_exit(qd65xx_mod_exit);
#endif
...@@ -564,8 +564,12 @@ media_bay_step(int i) ...@@ -564,8 +564,12 @@ media_bay_step(int i)
bay->timer = 0; bay->timer = 0;
bay->state = mb_up; bay->state = mb_up;
if (bay->cd_index < 0) { if (bay->cd_index < 0) {
hw_regs_t hw;
pmu_suspend(); pmu_suspend();
bay->cd_index = ide_register(bay->cd_base, 0, bay->cd_irq); ide_init_hwif_ports(&hw, (ide_ioreg_t) bay->cd_base, (ide_ioreg_t) 0, NULL);
hw.irq = bay->cd_irq;
bay->cd_index = ide_register_hw(&hw, NULL);
pmu_resume(); pmu_resume();
} }
if (bay->cd_index == -1) { if (bay->cd_index == -1) {
......
...@@ -234,12 +234,17 @@ static void hexdump(u8 *x, int len) ...@@ -234,12 +234,17 @@ static void hexdump(u8 *x, int len)
printk("]\n"); printk("]\n");
} }
static inline idescsi_scsi_t *idescsi_private(struct Scsi_Host *host)
{
return (idescsi_scsi_t*) &host[1];
}
static int idescsi_end_request(struct ata_device *drive, struct request *rq, int uptodate) static int idescsi_end_request(struct ata_device *drive, struct request *rq, int uptodate)
{ {
idescsi_scsi_t *scsi = drive->driver_data; struct Scsi_Host *host = drive->driver_data;
idescsi_scsi_t *scsi = idescsi_private(host);
struct atapi_packet_command *pc = (struct atapi_packet_command *) rq->special; struct atapi_packet_command *pc = (struct atapi_packet_command *) rq->special;
int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
struct Scsi_Host *host;
u8 *scsi_buf; u8 *scsi_buf;
unsigned long flags; unsigned long flags;
...@@ -289,20 +294,21 @@ static inline unsigned long get_timeout(struct atapi_packet_command *pc) ...@@ -289,20 +294,21 @@ static inline unsigned long get_timeout(struct atapi_packet_command *pc)
*/ */
static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request *rq)
{ {
idescsi_scsi_t *scsi = drive->driver_data; struct Scsi_Host *host = drive->driver_data;
idescsi_scsi_t *scsi = idescsi_private(host);
byte status, ireason; byte status, ireason;
int bcount; int bcount;
struct atapi_packet_command *pc = scsi->pc; struct atapi_packet_command *pc=scsi->pc;
unsigned int temp; unsigned int temp;
#if IDESCSI_DEBUG_LOG #if IDESCSI_DEBUG_LOG
printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n"); printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n");
#endif #endif /* IDESCSI_DEBUG_LOG */
if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
#if IDESCSI_DEBUG_LOG #if IDESCSI_DEBUG_LOG
printk ("ide-scsi: %s: DMA complete\n", drive->name); printk ("ide-scsi: %s: DMA complete\n", drive->name);
#endif #endif /* IDESCSI_DEBUG_LOG */
pc->actually_transferred=pc->request_transfer; pc->actually_transferred=pc->request_transfer;
udma_stop(drive); udma_stop(drive);
} }
...@@ -372,7 +378,8 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request ...@@ -372,7 +378,8 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request
static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct request *rq) static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct request *rq)
{ {
idescsi_scsi_t *scsi = drive->driver_data; struct Scsi_Host *host = drive->driver_data;
idescsi_scsi_t *scsi = idescsi_private(host);
struct atapi_packet_command *pc = scsi->pc; struct atapi_packet_command *pc = scsi->pc;
byte ireason; byte ireason;
ide_startstop_t startstop; ide_startstop_t startstop;
...@@ -397,7 +404,8 @@ static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct requ ...@@ -397,7 +404,8 @@ static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct requ
static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request *rq, static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request *rq,
struct atapi_packet_command *pc) struct atapi_packet_command *pc)
{ {
idescsi_scsi_t *scsi = drive->driver_data; struct Scsi_Host *host = drive->driver_data;
idescsi_scsi_t *scsi = idescsi_private(host);
int bcount; int bcount;
int dma_ok = 0; int dma_ok = 0;
...@@ -463,36 +471,14 @@ static void idescsi_ide_release(struct inode *inode, struct file *filp, struct a ...@@ -463,36 +471,14 @@ static void idescsi_ide_release(struct inode *inode, struct file *filp, struct a
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
} }
static struct ata_device *idescsi_drives[MAX_HWIFS * MAX_DRIVES]; static int idescsi_cleanup (struct ata_device *drive)
static int idescsi_initialized = 0;
/*
* Driver initialization.
*/
static void idescsi_setup(struct ata_device *drive, idescsi_scsi_t *scsi, int id)
{ {
idescsi_drives[id] = drive; struct Scsi_Host *host = drive->driver_data;
drive->driver_data = scsi;
drive->ready_stat = 0;
memset (scsi, 0, sizeof (idescsi_scsi_t));
scsi->drive = drive;
if (drive->id && (drive->id->config & 0x0060) == 0x20)
set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
set_bit(IDESCSI_TRANSFORM, &scsi->transform);
clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
#if IDESCSI_DEBUG_LOG
set_bit(IDESCSI_LOG_CMD, &scsi->log);
#endif
}
static int idescsi_cleanup(struct ata_device *drive) if (ide_unregister_subdriver (drive)) {
{
idescsi_scsi_t *scsi = drive->driver_data;
if (ide_unregister_subdriver (drive))
return 1; return 1;
drive->driver_data = NULL; }
kfree (scsi); scsi_unregister(host);
return 0; return 0;
} }
...@@ -522,73 +508,9 @@ static struct ata_operations idescsi_driver = { ...@@ -522,73 +508,9 @@ static struct ata_operations idescsi_driver = {
capacity: NULL, capacity: NULL,
}; };
static void idescsi_attach(struct ata_device *drive)
{
idescsi_scsi_t *scsi;
int i, id;
char *req;
struct ata_channel *channel;
int unit;
if (idescsi_initialized)
return;
idescsi_initialized = 1;
for (i = 0; i < MAX_HWIFS * MAX_DRIVES; i++)
idescsi_drives[i] = NULL;
req = drive->driver_req;
if (req[0] != '\0' && strcmp(req, "ide-scsi"))
return;
if ((scsi = (idescsi_scsi_t *) kmalloc (sizeof (idescsi_scsi_t), GFP_KERNEL)) == NULL) {
printk(KERN_ERR "ide-scsi: %s: Can't allocate a scsi structure\n", drive->name);
return;
}
if (ide_register_subdriver (drive, &idescsi_driver)) {
printk(KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name);
kfree (scsi);
return;
}
for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++);
idescsi_setup (drive, scsi, id);
channel = drive->channel;
unit = drive - channel->drives;
ide_revalidate_disk(mk_kdev(channel->major, unit << PARTN_BITS));
}
int idescsi_detect (Scsi_Host_Template *host_template) int idescsi_detect (Scsi_Host_Template *host_template)
{ {
struct Scsi_Host *host; return register_ata_driver(&idescsi_driver);
int id;
int last_lun = 0;
host_template->proc_name = "ide-scsi";
host = scsi_register(host_template, 0);
if(host == NULL)
return 0;
for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++)
last_lun = max(last_lun, idescsi_drives[id]->last_lun);
host->max_id = id;
host->max_lun = last_lun + 1;
host->can_queue = host->cmd_per_lun * id;
return 1;
}
int idescsi_release (struct Scsi_Host *host)
{
struct ata_device *drive;
int id;
for (id = 0; id < MAX_HWIFS * MAX_DRIVES; id++) {
drive = idescsi_drives[id];
if (drive) {
MOD_DEC_USE_COUNT;
}
}
return 0;
} }
const char *idescsi_info (struct Scsi_Host *host) const char *idescsi_info (struct Scsi_Host *host)
...@@ -598,8 +520,7 @@ const char *idescsi_info (struct Scsi_Host *host) ...@@ -598,8 +520,7 @@ const char *idescsi_info (struct Scsi_Host *host)
int idescsi_ioctl (Scsi_Device *dev, int cmd, void *arg) int idescsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
{ {
struct ata_device *drive = idescsi_drives[dev->id]; idescsi_scsi_t *scsi = idescsi_private(dev->host);
idescsi_scsi_t *scsi = drive->driver_data;
if (cmd == SG_SET_TRANSFORM) { if (cmd == SG_SET_TRANSFORM) {
if (arg) if (arg)
...@@ -693,7 +614,8 @@ static inline struct bio *idescsi_dma_bio(struct ata_device *drive, struct atapi ...@@ -693,7 +614,8 @@ static inline struct bio *idescsi_dma_bio(struct ata_device *drive, struct atapi
static inline int should_transform(struct ata_device *drive, Scsi_Cmnd *cmd) static inline int should_transform(struct ata_device *drive, Scsi_Cmnd *cmd)
{ {
idescsi_scsi_t *scsi = drive->driver_data; struct Scsi_Host *host = drive->driver_data;
idescsi_scsi_t *scsi = idescsi_private(host);
if (major(cmd->request.rq_dev) == SCSI_GENERIC_MAJOR) if (major(cmd->request.rq_dev) == SCSI_GENERIC_MAJOR)
return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
...@@ -702,16 +624,11 @@ static inline int should_transform(struct ata_device *drive, Scsi_Cmnd *cmd) ...@@ -702,16 +624,11 @@ static inline int should_transform(struct ata_device *drive, Scsi_Cmnd *cmd)
int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
{ {
struct ata_device *drive = idescsi_drives[cmd->target]; idescsi_scsi_t *scsi = idescsi_private(cmd->host);
idescsi_scsi_t *scsi; struct ata_device *drive = scsi->drive;
struct request *rq = NULL; struct request *rq = NULL;
struct atapi_packet_command *pc = NULL; struct atapi_packet_command *pc = NULL;
if (!drive) {
printk (KERN_ERR "ide-scsi: drive id %d not present\n", cmd->target);
goto abort;
}
scsi = drive->driver_data;
pc = kmalloc(sizeof(*pc), GFP_ATOMIC); pc = kmalloc(sizeof(*pc), GFP_ATOMIC);
rq = kmalloc(sizeof(*rq), GFP_ATOMIC); rq = kmalloc(sizeof(*rq), GFP_ATOMIC);
if (rq == NULL || pc == NULL) { if (rq == NULL || pc == NULL) {
...@@ -774,7 +691,8 @@ int idescsi_device_reset (Scsi_Cmnd *cmd) ...@@ -774,7 +691,8 @@ int idescsi_device_reset (Scsi_Cmnd *cmd)
int idescsi_bios (Disk *disk, kdev_t dev, int *parm) int idescsi_bios (Disk *disk, kdev_t dev, int *parm)
{ {
struct ata_device *drive = idescsi_drives[disk->device->id]; idescsi_scsi_t *scsi = idescsi_private(disk->device->host);
struct ata_device *drive = scsi->drive;
if (drive->bios_cyl && drive->bios_head && drive->bios_sect) { if (drive->bios_cyl && drive->bios_head && drive->bios_sect) {
parm[0] = drive->bios_head; parm[0] = drive->bios_head;
...@@ -788,7 +706,10 @@ static Scsi_Host_Template idescsi_template = { ...@@ -788,7 +706,10 @@ static Scsi_Host_Template idescsi_template = {
module: THIS_MODULE, module: THIS_MODULE,
name: "idescsi", name: "idescsi",
detect: idescsi_detect, detect: idescsi_detect,
release: idescsi_release, release: NULL, /* unregister_ata_driver is always
called before scsi_unregister_host,
there never controllers left to
release by that point. */
info: idescsi_info, info: idescsi_info,
ioctl: idescsi_ioctl, ioctl: idescsi_ioctl,
queuecommand: idescsi_queue, queuecommand: idescsi_queue,
...@@ -801,33 +722,65 @@ static Scsi_Host_Template idescsi_template = { ...@@ -801,33 +722,65 @@ static Scsi_Host_Template idescsi_template = {
cmd_per_lun: 5, cmd_per_lun: 5,
use_clustering: DISABLE_CLUSTERING, use_clustering: DISABLE_CLUSTERING,
emulated: 1, emulated: 1,
proc_name: "ide-scsi",
}; };
/*
static int __init idescsi_init(void) * Driver initialization.
*/
static void idescsi_attach(struct ata_device *drive)
{ {
int ret; idescsi_scsi_t *scsi;
ret = ata_driver_module(&idescsi_driver); struct Scsi_Host *host;
scsi_register_host(&idescsi_template);
return 0;
}
static void __exit exit_idescsi_module(void)
{
scsi_unregister_host(&idescsi_template);
#if 0 if (drive->type == ATA_DISK)
/* FIXME: what about this cleanup stuff here? This all should be done return;
* on close time perhaps? */
host = scsi_register(&idescsi_template, sizeof(idescsi_scsi_t));
if (idescsi_cleanup (drive)) { if(host == NULL) {
printk ("%s: exit_idescsi_module() called while still busy\n", drive->name); printk (KERN_ERR
"ide-scsi: %s: Can't allocate a scsi host structure\n",
drive->name);
return;
} }
host->max_lun = drive->last_lun + 1;
if (ide_register_subdriver (drive, &idescsi_driver)) {
printk (KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name);
scsi_unregister(host);
return;
}
drive->driver_data = host;
drive->ready_stat = 0;
scsi = idescsi_private(host);
memset (scsi, 0, sizeof (idescsi_scsi_t));
scsi->drive = drive;
if (drive->id && (drive->id->config & 0x0060) == 0x20)
set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
set_bit(IDESCSI_TRANSFORM, &scsi->transform);
clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
#if IDESCSI_DEBUG_LOG
set_bit(IDESCSI_LOG_CMD, &scsi->log);
#endif #endif
}
static int __init init_idescsi_module(void)
{
return scsi_register_host(&idescsi_template);
}
static void __exit exit_idescsi_module(void)
{
unregister_ata_driver(&idescsi_driver); unregister_ata_driver(&idescsi_driver);
scsi_unregister_host(&idescsi_template);
} }
module_init(idescsi_init); module_init(init_idescsi_module);
module_exit(exit_idescsi_module); module_exit(exit_idescsi_module);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -58,8 +58,11 @@ struct atapi_packet_command { ...@@ -58,8 +58,11 @@ struct atapi_packet_command {
} s; } s;
}; };
extern void atapi_init_pc(struct atapi_packet_command *pc);
extern void atapi_discard_data(struct ata_device *drive, unsigned int bcount); extern void atapi_discard_data(struct ata_device *, unsigned int);
extern void atapi_write_zeros(struct ata_device *drive, unsigned int bcount); extern void atapi_write_zeros(struct ata_device *, unsigned int);
extern void atapi_read(struct ata_device *, u8 *, unsigned int);
extern void atapi_write(struct ata_device *, u8 *, unsigned int);
extern void atapi_init_pc(struct atapi_packet_command *pc);
...@@ -742,9 +742,6 @@ struct ata_taskfile { ...@@ -742,9 +742,6 @@ struct ata_taskfile {
extern void ata_read(struct ata_device *, void *, unsigned int); extern void ata_read(struct ata_device *, void *, unsigned int);
extern void ata_write(struct ata_device *, void *, unsigned int); extern void ata_write(struct ata_device *, void *, unsigned int);
extern void atapi_read(struct ata_device *, void *, unsigned int);
extern void atapi_write(struct ata_device *, void *, unsigned int);
extern ide_startstop_t ata_taskfile(struct ata_device *, extern ide_startstop_t ata_taskfile(struct ata_device *,
struct ata_taskfile *, struct request *); struct ata_taskfile *, struct request *);
...@@ -811,7 +808,8 @@ extern int idescsi_init (void); ...@@ -811,7 +808,8 @@ extern int idescsi_init (void);
extern int ide_register_subdriver(struct ata_device *, struct ata_operations *); extern int ide_register_subdriver(struct ata_device *, struct ata_operations *);
extern int ide_unregister_subdriver(struct ata_device *drive); extern int ide_unregister_subdriver(struct ata_device *drive);
extern int ide_revalidate_disk(kdev_t i_rdev); extern int ata_revalidate(kdev_t i_rdev);
extern void ide_driver_module(void);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
# define ON_BOARD 0 # define ON_BOARD 0
......
...@@ -1787,3 +1787,7 @@ ...@@ -1787,3 +1787,7 @@
#define PCI_DEVICE_ID_MICROGATE_USC 0x0010 #define PCI_DEVICE_ID_MICROGATE_USC 0x0010
#define PCI_DEVICE_ID_MICROGATE_SCC 0x0020 #define PCI_DEVICE_ID_MICROGATE_SCC 0x0020
#define PCI_DEVICE_ID_MICROGATE_SCA 0x0030 #define PCI_DEVICE_ID_MICROGATE_SCA 0x0030
#define PCI_VENDOR_ID_HINT 0x3388
#define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment