aboutsummaryrefslogtreecommitdiffstats
path: root/xen/drivers/ide
diff options
context:
space:
mode:
Diffstat (limited to 'xen/drivers/ide')
-rw-r--r--xen/drivers/ide/Makefile8
-rw-r--r--xen/drivers/ide/ide-cd.c3084
-rw-r--r--xen/drivers/ide/ide-cd.h746
-rw-r--r--xen/drivers/ide/ide-disk.c1553
-rw-r--r--xen/drivers/ide/ide-dma.c897
-rw-r--r--xen/drivers/ide/ide-features.c384
-rw-r--r--xen/drivers/ide/ide-geometry.c219
-rw-r--r--xen/drivers/ide/ide-pci.c1016
-rw-r--r--xen/drivers/ide/ide-probe.c1066
-rw-r--r--xen/drivers/ide/ide-taskfile.c1733
-rw-r--r--xen/drivers/ide/ide-xen.c61
-rw-r--r--xen/drivers/ide/ide.c4211
-rw-r--r--xen/drivers/ide/ide_modes.h236
-rw-r--r--xen/drivers/ide/piix.c542
14 files changed, 0 insertions, 15756 deletions
diff --git a/xen/drivers/ide/Makefile b/xen/drivers/ide/Makefile
deleted file mode 100644
index 574b7d2d79..0000000000
--- a/xen/drivers/ide/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-
-include $(BASEDIR)/Rules.mk
-
-default: $(OBJS)
- $(LD) -r -o driver.o $(OBJS)
-
-clean:
- rm -f *.o *~ core
diff --git a/xen/drivers/ide/ide-cd.c b/xen/drivers/ide/ide-cd.c
deleted file mode 100644
index ead14222a1..0000000000
--- a/xen/drivers/ide/ide-cd.c
+++ /dev/null
@@ -1,3084 +0,0 @@
-/*
- * linux/drivers/ide/ide-cd.c
- *
- * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
- * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
- * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * ATAPI CD-ROM driver. To be used with ide.c.
- * See Documentation/cdrom/ide-cd for usage information.
- *
- * Suggestions are welcome. Patches that work are more welcome though. ;-)
- * For those wishing to work on this driver, please be sure you download
- * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
- * (SFF-8020i rev 2.6) standards. These documents can be obtained by
- * anonymous ftp from:
- * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
- * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
- *
- * Drives that deviate from these standards will be accomodated as much
- * as possible via compile time or command-line options. Since I only have
- * a few drives, you generally need to send me patches...
- *
- * ----------------------------------
- * TO DO LIST:
- * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
- * boot
- *
- * ----------------------------------
- * 1.00 Oct 31, 1994 -- Initial version.
- * 1.01 Nov 2, 1994 -- Fixed problem with starting request in
- * cdrom_check_status.
- * 1.03 Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks)
- * (from mlord) -- minor changes to cdrom_setup()
- * -- renamed ide_dev_s to ide_drive_t, enable irq on command
- * 2.00 Nov 27, 1994 -- Generalize packet command interface;
- * add audio ioctls.
- * 2.01 Dec 3, 1994 -- Rework packet command interface to handle devices
- * which send an interrupt when ready for a command.
- * 2.02 Dec 11, 1994 -- Cache the TOC in the driver.
- * Don't use SCMD_PLAYAUDIO_TI; it's not included
- * in the current version of ATAPI.
- * Try to use LBA instead of track or MSF addressing
- * when possible.
- * Don't wait for READY_STAT.
- * 2.03 Jan 10, 1995 -- Rewrite block read routines to handle block sizes
- * other than 2k and to move multiple sectors in a
- * single transaction.
- * 2.04 Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives.
- * Thanks to Nick Saw <cwsaw@pts7.pts.mot.com> for
- * help in figuring this out. Ditto for Acer and
- * Aztech drives, which seem to have the same problem.
- * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml
- * 2.05 Jun 8, 1995 -- Don't attempt to retry after an illegal request
- * or data protect error.
- * Use HWIF and DEV_HWIF macros as in ide.c.
- * Always try to do a request_sense after
- * a failed command.
- * Include an option to give textual descriptions
- * of ATAPI errors.
- * Fix a bug in handling the sector cache which
- * showed up if the drive returned data in 512 byte
- * blocks (like Pioneer drives). Thanks to
- * Richard Hirst <srh@gpt.co.uk> for diagnosing this.
- * Properly supply the page number field in the
- * MODE_SELECT command.
- * PLAYAUDIO12 is broken on the Aztech; work around it.
- * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c
- * (my apologies to Scott, but now ide-cd.c is independent)
- * 3.00 Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl.
- * Implement CDROMREADAUDIO ioctl (UNTESTED).
- * Use input_ide_data() and output_ide_data().
- * Add door locking.
- * Fix usage count leak in cdrom_open, which happened
- * when a read-write mount was attempted.
- * Try to load the disk on open.
- * Implement CDROMEJECT_SW ioctl (off by default).
- * Read total cdrom capacity during open.
- * Rearrange logic in cdrom_decode_status. Issue
- * request sense commands for failed packet commands
- * from here instead of from cdrom_queue_packet_command.
- * Fix a race condition in retrieving error information.
- * Suppress printing normal unit attention errors and
- * some drive not ready errors.
- * Implement CDROMVOLREAD ioctl.
- * Implement CDROMREADMODE1/2 ioctls.
- * Fix race condition in setting up interrupt handlers
- * when the `serialize' option is used.
- * 3.01 Sep 2, 1995 -- Fix ordering of reenabling interrupts in
- * cdrom_queue_request.
- * Another try at using ide_[input,output]_data.
- * 3.02 Sep 16, 1995 -- Stick total disk capacity in partition table as well.
- * Make VERBOSE_IDE_CD_ERRORS dump failed command again.
- * Dump out more information for ILLEGAL REQUEST errs.
- * Fix handling of errors occurring before the
- * packet command is transferred.
- * Fix transfers with odd bytelengths.
- * 3.03 Oct 27, 1995 -- Some Creative drives have an id of just `CD'.
- * `DCI-2S10' drives are broken too.
- * 3.04 Nov 20, 1995 -- So are Vertos drives.
- * 3.05 Dec 1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c
- * 3.06 Dec 16, 1995 -- Add support needed for partitions.
- * More workarounds for Vertos bugs (based on patches
- * from Holger Dietze <dietze@aix520.informatik.uni-leipzig.de>).
- * Try to eliminate byteorder assumptions.
- * Use atapi_cdrom_subchnl struct definition.
- * Add STANDARD_ATAPI compilation option.
- * 3.07 Jan 29, 1996 -- More twiddling for broken drives: Sony 55D,
- * Vertos 300.
- * Add NO_DOOR_LOCKING configuration option.
- * Handle drive_cmd requests w/NULL args (for hdparm -t).
- * Work around sporadic Sony55e audio play problem.
- * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix
- * problem with "hde=cdrom" with no drive present. -ml
- * 3.08 Mar 6, 1996 -- More Vertos workarounds.
- * 3.09 Apr 5, 1996 -- Add CDROMCLOSETRAY ioctl.
- * Switch to using MSF addressing for audio commands.
- * Reformat to match kernel tabbing style.
- * Add CDROM_GET_UPC ioctl.
- * 3.10 Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI.
- * 3.11 Apr 29, 1996 -- Patch from Heiko Eissfeldt <heiko@colossus.escape.de>
- * to remove redundant verify_area calls.
- * 3.12 May 7, 1996 -- Rudimentary changer support. Based on patches
- * from Gerhard Zuber <zuber@berlin.snafu.de>.
- * Let open succeed even if there's no loaded disc.
- * 3.13 May 19, 1996 -- Fixes for changer code.
- * 3.14 May 29, 1996 -- Add work-around for Vertos 600.
- * (From Hennus Bergman <hennus@sky.ow.nl>.)
- * 3.15 July 2, 1996 -- Added support for Sanyo 3 CD changers
- * from Ben Galliart <bgallia@luc.edu> with
- * special help from Jeff Lightfoot
- * <jeffml@pobox.com>
- * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification
- * 3.16 Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl.
- * 3.17 Sep 17, 1996 -- Tweak audio reads for some drives.
- * Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC.
- * 3.18 Oct 31, 1996 -- Added module and DMA support.
- *
- *
- * 4.00 Nov 5, 1996 -- New ide-cd maintainer,
- * Erik B. Andersen <andersee@debian.org>
- * -- Newer Creative drives don't always set the error
- * register correctly. Make sure we see media changes
- * regardless.
- * -- Integrate with generic cdrom driver.
- * -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on
- * a patch from Ciro Cattuto <>.
- * -- Call set_device_ro.
- * -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE
- * ioctls, based on patch by Erik Andersen
- * -- Add some probes of drive capability during setup.
- *
- * 4.01 Nov 11, 1996 -- Split into ide-cd.c and ide-cd.h
- * -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE
- * ioctls in favor of a generalized approach
- * using the generic cdrom driver.
- * -- Fully integrated with the 2.1.X kernel.
- * -- Other stuff that I forgot (lots of changes)
- *
- * 4.02 Dec 01, 1996 -- Applied patch from Gadi Oxman <gadio@netvision.net.il>
- * to fix the drive door locking problems.
- *
- * 4.03 Dec 04, 1996 -- Added DSC overlap support.
- * 4.04 Dec 29, 1996 -- Added CDROMREADRAW ioclt based on patch
- * by Ales Makarov (xmakarov@sun.felk.cvut.cz)
- *
- * 4.05 Nov 20, 1997 -- Modified to print more drive info on init
- * Minor other changes
- * Fix errors on CDROMSTOP (If you have a "Dolphin",
- * you must define IHAVEADOLPHIN)
- * Added identifier so new Sanyo CD-changer works
- * Better detection if door locking isn't supported
- *
- * 4.06 Dec 17, 1997 -- fixed endless "tray open" messages -ml
- * 4.07 Dec 17, 1997 -- fallback to set pc->stat on "tray open"
- * 4.08 Dec 18, 1997 -- spew less noise when tray is empty
- * -- fix speed display for ACER 24X, 18X
- * 4.09 Jan 04, 1998 -- fix handling of the last block so we return
- * an end of file instead of an I/O error (Gadi)
- * 4.10 Jan 24, 1998 -- fixed a bug so now changers can change to a new
- * slot when there is no disc in the current slot.
- * -- Fixed a memory leak where info->changer_info was
- * malloc'ed but never free'd when closing the device.
- * -- Cleaned up the global namespace a bit by making more
- * functions static that should already have been.
- * 4.11 Mar 12, 1998 -- Added support for the CDROM_SELECT_SPEED ioctl
- * based on a patch for 2.0.33 by Jelle Foks
- * <jelle@scintilla.utwente.nl>, a patch for 2.0.33
- * by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI
- * version, and my own efforts. -erik
- * -- Fixed a stupid bug which egcs was kind enough to
- * inform me of where "Illegal mode for this track"
- * was never returned due to a comparison on data
- * types of limited range.
- * 4.12 Mar 29, 1998 -- Fixed bug in CDROM_SELECT_SPEED so write speed is
- * now set ionly for CD-R and CD-RW drives. I had
- * removed this support because it produced errors.
- * It produced errors _only_ for non-writers. duh.
- * 4.13 May 05, 1998 -- Suppress useless "in progress of becoming ready"
- * messages, since this is not an error.
- * -- Change error messages to be const
- * -- Remove a "\t" which looks ugly in the syslogs
- * 4.14 July 17, 1998 -- Change to pointing to .ps version of ATAPI spec
- * since the .pdf version doesn't seem to work...
- * -- Updated the TODO list to something more current.
- *
- * 4.15 Aug 25, 1998 -- Updated ide-cd.h to respect mechine endianess,
- * patch thanks to "Eddie C. Dost" <ecd@skynet.be>
- *
- * 4.50 Oct 19, 1998 -- New maintainers!
- * Jens Axboe <axboe@image.dk>
- * Chris Zwilling <chris@cloudnet.com>
- *
- * 4.51 Dec 23, 1998 -- Jens Axboe <axboe@image.dk>
- * - ide_cdrom_reset enabled since the ide subsystem
- * handles resets fine now. <axboe@image.dk>
- * - Transfer size fix for Samsung CD-ROMs, thanks to
- * "Ville Hallik" <ville.hallik@mail.ee>.
- * - other minor stuff.
- *
- * 4.52 Jan 19, 1999 -- Jens Axboe <axboe@image.dk>
- * - Detect DVD-ROM/RAM drives
- *
- * 4.53 Feb 22, 1999 - Include other model Samsung and one Goldstar
- * drive in transfer size limit.
- * - Fix the I/O error when doing eject without a medium
- * loaded on some drives.
- * - CDROMREADMODE2 is now implemented through
- * CDROMREADRAW, since many drives don't support
- * MODE2 (even though ATAPI 2.6 says they must).
- * - Added ignore parameter to ide-cd (as a module), eg
- * insmod ide-cd ignore='hda hdb'
- * Useful when using ide-cd in conjunction with
- * ide-scsi. TODO: non-modular way of doing the
- * same.
- *
- * 4.54 Aug 5, 1999 - Support for MMC2 class commands through the generic
- * packet interface to cdrom.c.
- * - Unified audio ioctl support, most of it.
- * - cleaned up various deprecated verify_area().
- * - Added ide_cdrom_packet() as the interface for
- * the Uniform generic_packet().
- * - bunch of other stuff, will fill in logs later.
- * - report 1 slot for non-changers, like the other
- * cd-rom drivers. don't report select disc for
- * non-changers as well.
- * - mask out audio playing, if the device can't do it.
- *
- * 4.55 Sep 1, 1999 - Eliminated the rest of the audio ioctls, except
- * for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers
- * use this independently of the actual audio handling.
- * They will disappear later when I get the time to
- * do it cleanly.
- * - Minimize the TOC reading - only do it when we
- * know a media change has occurred.
- * - Moved all the CDROMREADx ioctls to the Uniform layer.
- * - Heiko Eissfeldt <heiko@colossus.escape.de> supplied
- * some fixes for CDI.
- * - CD-ROM leaving door locked fix from Andries
- * Brouwer <Andries.Brouwer@cwi.nl>
- * - Erik Andersen <andersen@xmission.com> unified
- * commands across the various drivers and how
- * sense errors are handled.
- *
- * 4.56 Sep 12, 1999 - Removed changer support - it is now in the
- * Uniform layer.
- * - Added partition based multisession handling.
- * - Mode sense and mode select moved to the
- * Uniform layer.
- * - Fixed a problem with WPI CDS-32X drive - it
- * failed the capabilities
- *
- * 4.57 Apr 7, 2000 - Fixed sense reporting.
- * - Fixed possible oops in ide_cdrom_get_last_session()
- * - Fix locking mania and make ide_cdrom_reset relock
- * - Stop spewing errors to log when magicdev polls with
- * TEST_UNIT_READY on some drives.
- * - Various fixes from Tobias Ringstrom:
- * tray if it was locked prior to the reset.
- * - cdrom_read_capacity returns one frame too little.
- * - Fix real capacity reporting.
- *
- * 4.58 May 1, 2000 - Clean up ACER50 stuff.
- * - Fix small problem with ide_cdrom_capacity
- *
- * 4.59 Aug 11, 2000 - Fix changer problem in cdrom_read_toc, we weren't
- * correctly sensing a disc change.
- * - Rearranged some code
- * - Use extended sense on drives that support it for
- * correctly reporting tray status -- from
- * Michael D Johnson <johnsom@orst.edu>
- *
- *************************************************************************/
-
-#define IDECD_VERSION "4.59"
-
-#include <xen/config.h>
-#include <xen/module.h>
-#include <xen/types.h>
-#include <xen/kernel.h>
-#include <xen/delay.h>
-#include <xen/timer.h>
-#include <xen/slab.h>
-#include <xen/interrupt.h>
-#include <xen/errno.h>
-#include <xen/cdrom.h>
-#include <xen/ide.h>
-// #include <xen/completion.h>
-
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-#include <asm/unaligned.h>
-
-#include "ide-cd.h"
-
-/****************************************************************************
- * Generic packet command support and error handling routines.
- */
-
-/* Mark that we've seen a media change, and invalidate our internal
- buffers. */
-static void cdrom_saw_media_change (ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
-
- CDROM_STATE_FLAGS (drive)->media_changed = 1;
- CDROM_STATE_FLAGS (drive)->toc_valid = 0;
- info->nsectors_buffered = 0;
-}
-
-static int cdrom_log_sense(ide_drive_t *drive, struct packet_command *pc,
- struct request_sense *sense)
-{
- int log = 0;
-
- if (sense == NULL || pc == NULL || pc->quiet)
- return 0;
-
- switch (sense->sense_key) {
- case NO_SENSE: case RECOVERED_ERROR:
- break;
- case NOT_READY:
- /*
- * don't care about tray state messages for
- * e.g. capacity commands or in-progress or
- * becoming ready
- */
- if (sense->asc == 0x3a || sense->asc == 0x04)
- break;
- log = 1;
- break;
- case UNIT_ATTENTION:
- /*
- * Make good and sure we've seen this potential media
- * change. Some drives (i.e. Creative) fail to present
- * the correct sense key in the error register.
- */
- cdrom_saw_media_change(drive);
- break;
- default:
- log = 1;
- break;
- }
- return log;
-}
-
-static
-void cdrom_analyze_sense_data(ide_drive_t *drive,
- struct packet_command *failed_command,
- struct request_sense *sense)
-{
-
- if (!cdrom_log_sense(drive, failed_command, sense))
- return;
-
- /*
- * If a read toc is executed for a CD-R or CD-RW medium where
- * the first toc has not been recorded yet, it will fail with
- * 05/24/00 (which is a confusing error)
- */
- if (failed_command && failed_command->c[0] == GPCMD_READ_TOC_PMA_ATIP)
- if (sense->sense_key == 0x05 && sense->asc == 0x24)
- return;
-
-#if VERBOSE_IDE_CD_ERRORS
- {
- int i;
- const char *s;
- char buf[80];
-
- printk ("ATAPI device %s:\n", drive->name);
- if (sense->error_code==0x70)
- printk(" Error: ");
- else if (sense->error_code==0x71)
- printk(" Deferred Error: ");
- else if (sense->error_code == 0x7f)
- printk(" Vendor-specific Error: ");
- else
- printk(" Unknown Error Type: ");
-
- if (sense->sense_key < ARY_LEN(sense_key_texts))
- s = sense_key_texts[sense->sense_key];
- else
- s = "bad sense key!";
-
- printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
-
- if (sense->asc == 0x40) {
- sprintf(buf, "Diagnostic failure on component 0x%02x",
- sense->ascq);
- s = buf;
- } else {
- int lo = 0, mid, hi = ARY_LEN(sense_data_texts);
- unsigned long key = (sense->sense_key << 16);
- key |= (sense->asc << 8);
- if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
- key |= sense->ascq;
- s = NULL;
-
- while (hi > lo) {
- mid = (lo + hi) / 2;
- if (sense_data_texts[mid].asc_ascq == key ||
- sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
- s = sense_data_texts[mid].text;
- break;
- }
- else if (sense_data_texts[mid].asc_ascq > key)
- hi = mid;
- else
- lo = mid+1;
- }
- }
-
- if (s == NULL) {
- if (sense->asc > 0x80)
- s = "(vendor-specific error)";
- else
- s = "(reserved error code)";
- }
-
- printk(" %s -- (asc=0x%02x, ascq=0x%02x)\n",
- s, sense->asc, sense->ascq);
-
- if (failed_command != NULL) {
-
- int lo=0, mid, hi= ARY_LEN (packet_command_texts);
- s = NULL;
-
- while (hi > lo) {
- mid = (lo + hi) / 2;
- if (packet_command_texts[mid].packet_command ==
- failed_command->c[0]) {
- s = packet_command_texts[mid].text;
- break;
- }
- if (packet_command_texts[mid].packet_command >
- failed_command->c[0])
- hi = mid;
- else
- lo = mid+1;
- }
-
- printk (" The failed \"%s\" packet command was: \n \"", s);
- for (i=0; i<sizeof (failed_command->c); i++)
- printk ("%02x ", failed_command->c[i]);
- printk ("\"\n");
- }
-
- /* The SKSV bit specifies validity of the sense_key_specific
- * in the next two commands. It is bit 7 of the first byte.
- * In the case of NOT_READY, if SKSV is set the drive can
- * give us nice ETA readings.
- */
- if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
- int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
- printk(" Command is %02d%% complete\n", progress / 0xffff);
-
- }
-
- if (sense->sense_key == ILLEGAL_REQUEST &&
- (sense->sks[0] & 0x80) != 0) {
- printk(" Error in %s byte %d",
- (sense->sks[0] & 0x40) != 0 ?
- "command packet" : "command data",
- (sense->sks[1] << 8) + sense->sks[2]);
-
- if ((sense->sks[0] & 0x40) != 0)
- printk (" bit %d", sense->sks[0] & 0x07);
-
- printk ("\n");
- }
- }
-
-#else /* not VERBOSE_IDE_CD_ERRORS */
-
- /* Suppress printing unit attention and `in progress of becoming ready'
- errors when we're not being verbose. */
-
- if (sense->sense_key == UNIT_ATTENTION ||
- (sense->sense_key == NOT_READY && (sense->asc == 4 ||
- sense->asc == 0x3a)))
- return;
-
- printk("%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n",
- drive->name,
- sense->error_code, sense->sense_key,
- sense->asc, sense->ascq);
-#endif /* not VERBOSE_IDE_CD_ERRORS */
-}
-
-static void cdrom_queue_request_sense(ide_drive_t *drive,
- struct completion *wait,
- struct request_sense *sense,
- struct packet_command *failed_command)
-{
- struct cdrom_info *info = drive->driver_data;
- struct packet_command *pc = &info->request_sense_pc;
- struct request *rq;
-
- if (sense == NULL)
- sense = &info->sense_data;
-
- memset(pc, 0, sizeof(struct packet_command));
- pc->c[0] = GPCMD_REQUEST_SENSE;
- pc->c[4] = pc->buflen = 18;
- pc->buffer = (char *) sense;
- pc->sense = (struct request_sense *) failed_command;
-
- /* stuff the sense request in front of our current request */
- rq = &info->request_sense_request;
- ide_init_drive_cmd(rq);
- rq->cmd = REQUEST_SENSE_COMMAND;
- rq->buffer = (char *) pc;
- rq->waiting = wait;
-
- (void) ide_do_drive_cmd(drive, rq, ide_preempt);
-}
-
-
-static void cdrom_end_request (int uptodate, ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
-
- if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate) {
- struct packet_command *pc = (struct packet_command *) rq->buffer;
- cdrom_analyze_sense_data(drive,
- (struct packet_command *) pc->sense,
- (struct request_sense *) (pc->buffer - pc->c[4]));
- }
- if (rq->cmd == READ || rq->cmd == WRITE)
- if (!rq->current_nr_sectors)
- uptodate = 1;
-
- ide_end_request (uptodate, HWGROUP(drive));
-}
-
-
-/* Returns 0 if the request should be continued.
- Returns 1 if the request was ended. */
-static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
- int good_stat, int *stat_ret)
-{
- struct request *rq = HWGROUP(drive)->rq;
- int stat, err, sense_key;
- struct packet_command *pc;
-
- /* Check for errors. */
- stat = GET_STAT();
- *stat_ret = stat;
-
- if (OK_STAT (stat, good_stat, BAD_R_STAT))
- return 0;
-
- /* Get the IDE error register. */
- err = GET_ERR();
- sense_key = err >> 4;
-
- if (rq == NULL) {
- printk("%s: missing rq in cdrom_decode_status\n", drive->name);
- *startstop = ide_stopped;
- return 1;
- }
-
- if (rq->cmd == REQUEST_SENSE_COMMAND) {
- /* We got an error trying to get sense info
- from the drive (probably while trying
- to recover from a former error). Just give up. */
-
- pc = (struct packet_command *) rq->buffer;
- pc->stat = 1;
- cdrom_end_request (1, drive);
- *startstop = ide_error (drive, "request sense failure", stat);
- return 1;
-
- } else if (rq->cmd == PACKET_COMMAND) {
- /* All other functions, except for READ. */
- struct completion *wait = NULL;
- pc = (struct packet_command *) rq->buffer;
-
- /* Check for tray open. */
- if (sense_key == NOT_READY) {
- cdrom_saw_media_change (drive);
- } else if (sense_key == UNIT_ATTENTION) {
- /* Check for media change. */
- cdrom_saw_media_change (drive);
- /*printk("%s: media changed\n",drive->name);*/
- return 0;
- } else if (!pc->quiet) {
- /* Otherwise, print an error. */
- ide_dump_status(drive, "packet command error", stat);
- }
-
- /* Set the error flag and complete the request.
- Then, if we have a CHECK CONDITION status,
- queue a request sense command. We must be careful,
- though: we don't want the thread in
- cdrom_queue_packet_command to wake up until
- the request sense has completed. We do this
- by transferring the semaphore from the packet
- command request to the request sense request. */
-
- if ((stat & ERR_STAT) != 0) {
- // XXX SMH: if we get here we should retry ... hmmm
-// printk("ide-cd: error (stat = 0x%x): will retry\n", stat);
- wait = rq->waiting;
- rq->waiting = NULL;
- }
-
- pc->stat = 1;
- cdrom_end_request (1, drive);
-
- if ((stat & ERR_STAT) != 0)
- cdrom_queue_request_sense(drive, wait, pc->sense, pc);
- } else {
- /* Handle errors from READ and WRITE requests. */
-
- if (sense_key == NOT_READY) {
- /* Tray open. */
- cdrom_saw_media_change (drive);
-
- /* Fail the request. */
- printk ("%s: tray open\n", drive->name);
- cdrom_end_request (0, drive);
- } else if (sense_key == UNIT_ATTENTION) {
- /* Media change. */
- cdrom_saw_media_change (drive);
-
- /* Arrange to retry the request.
- But be sure to give up if we've retried
- too many times. */
- if (++rq->errors > ERROR_MAX)
- cdrom_end_request (0, drive);
- } else if (sense_key == ILLEGAL_REQUEST ||
- sense_key == DATA_PROTECT) {
- /* No point in retrying after an illegal
- request or data protect error.*/
- ide_dump_status (drive, "command error", stat);
- cdrom_end_request (0, drive);
- } else if ((err & ~ABRT_ERR) != 0) {
- /* Go to the default handler
- for other errors. */
- *startstop = ide_error (drive, "cdrom_decode_status", stat);
- return 1;
- } else if ((++rq->errors > ERROR_MAX)) {
- /* We've racked up too many retries. Abort. */
- cdrom_end_request (0, drive);
- }
-
- /* If we got a CHECK_CONDITION status,
- queue a request sense command. */
- if ((stat & ERR_STAT) != 0)
- cdrom_queue_request_sense(drive, NULL, NULL, NULL);
- }
-
- /* Retry, or handle the next request. */
- *startstop = ide_stopped;
- return 1;
-}
-
-static int cdrom_timer_expiry(ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
- struct packet_command *pc = (struct packet_command *) rq->buffer;
- unsigned long wait = 0;
-
- /*
- * Some commands are *slow* and normally take a long time to
- * complete. Usually we can use the ATAPI "disconnect" to bypass
- * this, but not all commands/drives support that. Let
- * ide_timer_expiry keep polling us for these.
- */
- switch (pc->c[0]) {
- case GPCMD_BLANK:
- case GPCMD_FORMAT_UNIT:
- case GPCMD_RESERVE_RZONE_TRACK:
- wait = WAIT_CMD;
- break;
- default:
- wait = 0;
- break;
- }
- return wait;
-}
-
-/* Set up the device registers for transferring a packet command on DEV,
- expecting to later transfer XFERLEN bytes. HANDLER is the routine
- which actually transfers the command to the drive. If this is a
- drq_interrupt device, this routine will arrange for HANDLER to be
- called when the interrupt from the drive arrives. Otherwise, HANDLER
- will be called immediately after the drive is prepared for the transfer. */
-
-static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
- int xferlen,
- ide_handler_t *handler)
-{
- ide_startstop_t startstop;
- struct cdrom_info *info = drive->driver_data;
-
- /* Wait for the controller to be idle. */
- if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
- return startstop;
-
- if (info->dma) {
- if (info->cmd == READ) {
- info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive);
- } else if (info->cmd == WRITE) {
- info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive);
- } else {
- printk("ide-cd: DMA set, but not allowed\n");
- }
- }
-
- /* Set up the controller registers. */
- OUT_BYTE (info->dma, IDE_FEATURE_REG);
- OUT_BYTE (0, IDE_NSECTOR_REG);
- OUT_BYTE (0, IDE_SECTOR_REG);
-
- OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG);
- OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG);
- if (IDE_CONTROL_REG)
- OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
-
- if (info->dma)
- (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
-
- if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
- ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry);
- OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- return ide_started;
- } else {
- OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- return (*handler) (drive);
- }
-}
-
-/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN.
- The device registers must have already been prepared
- by cdrom_start_packet_command.
- HANDLER is the interrupt handler to call when the command completes
- or there's data ready. */
-/*
- * changed 5 parameters to 3 for dvd-ram
- * struct packet_command *pc; now packet_command_t *pc;
- */
-static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
- struct packet_command *pc,
- ide_handler_t *handler)
-{
- unsigned char *cmd_buf = pc->c;
- int cmd_len = sizeof(pc->c);
- unsigned int timeout = pc->timeout;
- ide_startstop_t startstop;
-
- if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
- /* Here we should have been called after receiving an interrupt
- from the device. DRQ should how be set. */
- int stat_dum;
-
- /* Check for errors. */
- if (cdrom_decode_status (&startstop, drive, DRQ_STAT, &stat_dum))
- return startstop;
- } else {
- /* Otherwise, we must wait for DRQ to get set. */
- if (ide_wait_stat (&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY))
- return startstop;
- }
-
- /* Arm the interrupt handler. */
- ide_set_handler (drive, handler, timeout, cdrom_timer_expiry);
-
- /* Send the command to the device. */
- atapi_output_bytes (drive, cmd_buf, cmd_len);
- return ide_started;
-}
-
-/****************************************************************************
- * Block read functions.
- */
-
-/*
- * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
- * buffer. Once the first sector is added, any subsequent sectors are
- * assumed to be continuous (until the buffer is cleared). For the first
- * sector added, SECTOR is its sector number. (SECTOR is then ignored until
- * the buffer is cleared.)
- */
-static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
- int sectors_to_transfer)
-{
- struct cdrom_info *info = drive->driver_data;
-
- /* Number of sectors to read into the buffer. */
- int sectors_to_buffer = MIN (sectors_to_transfer,
- (SECTOR_BUFFER_SIZE >> SECTOR_BITS) -
- info->nsectors_buffered);
-
- char *dest, *dum;
-
- /* If we couldn't get a buffer, don't try to buffer anything... */
- if (info->buffer == NULL)
- sectors_to_buffer = 0;
-
- /* If this is the first sector in the buffer, remember its number. */
- if (info->nsectors_buffered == 0)
- info->sector_buffered = sector;
-
- /* Read the data into the buffer. */
- dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE;
- while (sectors_to_buffer > 0) {
- atapi_input_bytes (drive, dest, SECTOR_SIZE);
- --sectors_to_buffer;
- --sectors_to_transfer;
- ++info->nsectors_buffered;
- dest += SECTOR_SIZE;
- }
-
- /* Throw away any remaining data. */
- dum = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
- while (sectors_to_transfer > 0) {
- atapi_input_bytes (drive, dum, SECTOR_SIZE);
- --sectors_to_transfer;
- }
- kfree(dum);
-}
-
-/*
- * Check the contents of the interrupt reason register from the cdrom
- * and attempt to recover if there are problems. Returns 0 if everything's
- * ok; nonzero if the request has been terminated.
- */
-static inline
-int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
-{
- ireason &= 3;
- if (ireason == 2) return 0;
-
- if (ireason == 0) {
- /* Whoops... The drive is expecting to receive data from us! */
- printk ("%s: cdrom_read_intr: "
- "Drive wants to transfer data the wrong way!\n",
- drive->name);
-
- /* Throw some data at the drive so it doesn't hang
- and quit this request. */
- while (len > 0) {
- int dum = 0;
- atapi_output_bytes (drive, &dum, sizeof (dum));
- len -= sizeof (dum);
- }
- } else if (ireason == 1) {
- /* Some drives (ASUS) seem to tell us that status
- * info is available. just get it and ignore.
- */
- GET_STAT();
- return 0;
- } else {
- /* Drive wants a command packet, or invalid ireason... */
- printk ("%s: cdrom_read_intr: bad interrupt reason %d\n",
- drive->name, ireason);
- }
-
- cdrom_end_request (0, drive);
- return -1;
-}
-
-/*
- * Interrupt routine. Called when a read request has completed.
- */
-static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
-{
- int stat;
- int ireason, len, sectors_to_transfer, nskip;
- struct cdrom_info *info = drive->driver_data;
- int i, dma = info->dma, dma_error = 0;
- ide_startstop_t startstop;
- char *dum;
-
- struct request *rq = HWGROUP(drive)->rq;
-
- /* Check for errors. */
- if (dma) {
- info->dma = 0;
- if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive)))
- HWIF(drive)->dmaproc(ide_dma_off, drive);
- }
-
- if (cdrom_decode_status (&startstop, drive, 0, &stat))
- return startstop;
-
- if (dma) {
- if (!dma_error) {
- for (i = rq->nr_sectors; i > 0;) {
- i -= rq->current_nr_sectors;
- ide_end_request(1, HWGROUP(drive));
- }
- return ide_stopped;
- } else
- return ide_error (drive, "dma error", stat);
- }
-
- /* Read the interrupt reason and the transfer length. */
- ireason = IN_BYTE (IDE_NSECTOR_REG);
- len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG);
-
- /* If DRQ is clear, the command has completed. */
- if ((stat & DRQ_STAT) == 0) {
- /* If we're not done filling the current buffer, complain.
- Otherwise, complete the command normally. */
- if (rq->current_nr_sectors > 0) {
- printk ("%s: cdrom_read_intr: data underrun (%ld blocks)\n",
- drive->name, rq->current_nr_sectors);
- cdrom_end_request (0, drive);
- } else
- cdrom_end_request (1, drive);
- return ide_stopped;
- }
-
- /* Check that the drive is expecting to do the same thing we are. */
- if (cdrom_read_check_ireason (drive, len, ireason))
- return ide_stopped;
-
- /* Assume that the drive will always provide data in multiples
- of at least SECTOR_SIZE, as it gets hairy to keep track
- of the transfers otherwise. */
- if ((len % SECTOR_SIZE) != 0) {
- printk ("%s: cdrom_read_intr: Bad transfer size %d\n",
- drive->name, len);
- if (CDROM_CONFIG_FLAGS (drive)->limit_nframes)
- printk (" This drive is not supported by this version of the driver\n");
- else {
- printk (" Trying to limit transfer sizes\n");
- CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
- }
- cdrom_end_request (0, drive);
- return ide_stopped;
- }
-
- /* The number of sectors we need to read from the drive. */
- sectors_to_transfer = len / SECTOR_SIZE;
-
- /* First, figure out if we need to bit-bucket
- any of the leading sectors. */
- nskip = MIN ((int)(rq->current_nr_sectors - (rq->bh->b_size >> SECTOR_BITS)),
- sectors_to_transfer);
-
- if ( (dum = kmalloc(SECTOR_SIZE, GFP_ATOMIC)) == NULL )
- {
- cdrom_end_request (0, drive);
- return ide_stopped;
- }
- while (nskip > 0) {
- /* We need to throw away a sector. */
- atapi_input_bytes (drive, dum, SECTOR_SIZE);
-
- --rq->current_nr_sectors;
- --nskip;
- --sectors_to_transfer;
- }
- kfree(dum);
-
- /* Now loop while we still have data to read from the drive. */
- while (sectors_to_transfer > 0) {
- int this_transfer;
-
- /* If we've filled the present buffer but there's another
- chained buffer after it, move on. */
- if (rq->current_nr_sectors == 0 && rq->nr_sectors)
- cdrom_end_request (1, drive);
-
- /* If the buffers are full, cache the rest of the data in our
- internal buffer. */
- if (rq->current_nr_sectors == 0) {
- cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer);
- sectors_to_transfer = 0;
- } else {
- /* Transfer data to the buffers.
- Figure out how many sectors we can transfer
- to the current buffer. */
- this_transfer = MIN (sectors_to_transfer,
- rq->current_nr_sectors);
-
- /* Read this_transfer sectors
- into the current buffer. */
- while (this_transfer > 0) {
- atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE);
- rq->buffer += SECTOR_SIZE;
- --rq->nr_sectors;
- --rq->current_nr_sectors;
- ++rq->sector;
- --this_transfer;
- --sectors_to_transfer;
- }
- }
- }
-
- /* Done moving data!
- Wait for another interrupt. */
- ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL);
- return ide_started;
-}
-
-/*
- * Try to satisfy some of the current read request from our cached data.
- * Returns nonzero if the request has been completed, zero otherwise.
- */
-static int cdrom_read_from_buffer (ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- struct request *rq = HWGROUP(drive)->rq;
-
- /* Can't do anything if there's no buffer. */
- if (info->buffer == NULL) return 0;
-
- /* Loop while this request needs data and the next block is present
- in our cache. */
- while (rq->nr_sectors > 0 &&
- rq->sector >= info->sector_buffered &&
- rq->sector < info->sector_buffered + info->nsectors_buffered) {
- if (rq->current_nr_sectors == 0)
- cdrom_end_request (1, drive);
-
- memcpy (rq->buffer,
- info->buffer +
- (rq->sector - info->sector_buffered) * SECTOR_SIZE,
- SECTOR_SIZE);
- rq->buffer += SECTOR_SIZE;
- --rq->current_nr_sectors;
- --rq->nr_sectors;
- ++rq->sector;
- }
-
- /* If we've satisfied the current request,
- terminate it successfully. */
- if (rq->nr_sectors == 0) {
- cdrom_end_request (1, drive);
- return -1;
- }
-
- /* Move on to the next buffer if needed. */
- if (rq->current_nr_sectors == 0)
- cdrom_end_request (1, drive);
-
- /* If this condition does not hold, then the kluge i use to
- represent the number of sectors to skip at the start of a transfer
- will fail. I think that this will never happen, but let's be
- paranoid and check. */
- if (rq->current_nr_sectors < (rq->bh->b_size >> SECTOR_BITS) &&
- (rq->sector % SECTORS_PER_FRAME) != 0) {
- printk ("%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
- drive->name, rq->sector);
- cdrom_end_request (0, drive);
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Routine to send a read packet command to the drive.
- * This is usually called directly from cdrom_start_read.
- * However, for drq_interrupt devices, it is called from an interrupt
- * when the drive is ready to accept the command.
- */
-static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
-{
- struct packet_command pc;
- struct request *rq = HWGROUP(drive)->rq;
- int nsect, sector, nframes, frame, nskip;
-
- /* Number of sectors to transfer. */
- nsect = rq->nr_sectors;
-
- /* Starting sector. */
- sector = rq->sector;
-
- /* If the requested sector doesn't start on a cdrom block boundary,
- we must adjust the start of the transfer so that it does,
- and remember to skip the first few sectors.
- If the CURRENT_NR_SECTORS field is larger than the size
- of the buffer, it will mean that we're to skip a number
- of sectors equal to the amount by which CURRENT_NR_SECTORS
- is larger than the buffer size. */
- nskip = (sector % SECTORS_PER_FRAME);
- if (nskip > 0) {
- /* Sanity check... */
- if (rq->current_nr_sectors != (rq->bh->b_size >> SECTOR_BITS) &&
- (rq->sector % CD_FRAMESIZE != 0)) {
- printk ("%s: cdrom_start_read_continuation: buffer botch (%lu)\n",
- drive->name, rq->current_nr_sectors);
- cdrom_end_request (0, drive);
- return ide_stopped;
- }
- sector -= nskip;
- nsect += nskip;
- rq->current_nr_sectors += nskip;
- }
-
- /* Convert from sectors to cdrom blocks, rounding up the transfer
- length if needed. */
- nframes = (nsect + SECTORS_PER_FRAME-1) / SECTORS_PER_FRAME;
- frame = sector / SECTORS_PER_FRAME;
-
- /* Largest number of frames was can transfer at once is 64k-1. For
- some drives we need to limit this even more. */
- nframes = MIN (nframes, (CDROM_CONFIG_FLAGS (drive)->limit_nframes) ?
- (65534 / CD_FRAMESIZE) : 65535);
-
- /* Set up the command */
- memset (&pc.c, 0, sizeof (pc.c));
- pc.c[0] = GPCMD_READ_10;
- pc.c[7] = (nframes >> 8);
- pc.c[8] = (nframes & 0xff);
- put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
- pc.timeout = WAIT_CMD;
-
- /* Send the command to the drive and return. */
- return cdrom_transfer_packet_command(drive, &pc, &cdrom_read_intr);
-}
-
-
-#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
-#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
-#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */
-
-static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- int stat;
- static int retry = 10;
- ide_startstop_t startstop;
-
- if (cdrom_decode_status (&startstop, drive, 0, &stat))
- return startstop;
- CDROM_CONFIG_FLAGS(drive)->seeking = 1;
-
- if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) {
- if (--retry == 0) {
- /*
- * this condition is far too common, to bother
- * users about it
- */
-#if 0
- printk("%s: disabled DSC seek overlap\n", drive->name);
-#endif
- drive->dsc_overlap = 0;
- }
- }
- return ide_stopped;
-}
-
-static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
-{
- struct packet_command pc;
- struct request *rq = HWGROUP(drive)->rq;
- int sector, frame, nskip;
-
- sector = rq->sector;
- nskip = (sector % SECTORS_PER_FRAME);
- if (nskip > 0)
- sector -= nskip;
- frame = sector / SECTORS_PER_FRAME;
-
- memset (&pc.c, 0, sizeof (pc.c));
- pc.c[0] = GPCMD_SEEK;
- put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
-
- pc.timeout = WAIT_CMD;
- return cdrom_transfer_packet_command(drive, &pc, &cdrom_seek_intr);
-}
-
-static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
-{
- struct cdrom_info *info = drive->driver_data;
-
- info->dma = 0;
- info->cmd = 0;
- info->start_seek = jiffies;
- return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation);
-}
-
-static inline int cdrom_merge_requests(struct request *rq, struct request *nxt)
-{
- int ret = 1;
-
- /*
- * partitions not really working, but better check anyway...
- */
- if (rq->cmd == nxt->cmd && rq->rq_dev == nxt->rq_dev) {
- rq->nr_sectors += nxt->nr_sectors;
- rq->hard_nr_sectors += nxt->nr_sectors;
- rq->bhtail->b_reqnext = nxt->bh;
- rq->bhtail = nxt->bhtail;
- list_del(&nxt->queue);
- blkdev_release_request(nxt);
- ret = 0;
- }
-
- return ret;
-}
-
-/*
- * the current request will always be the first one on the list
- */
-static void cdrom_attempt_remerge(ide_drive_t *drive, struct request *rq)
-{
- struct list_head *entry;
- struct request *nxt;
- unsigned long flags;
-
- spin_lock_irqsave(&io_request_lock, flags);
-
- while (1) {
- entry = rq->queue.next;
- if (entry == &drive->queue.queue_head)
- break;
-
- nxt = blkdev_entry_to_request(entry);
- if (rq->sector + rq->nr_sectors != nxt->sector)
- break;
- else if (rq->nr_sectors + nxt->nr_sectors > SECTORS_MAX)
- break;
-
- if (cdrom_merge_requests(rq, nxt))
- break;
- }
-
- spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-/* Fix up a possibly partially-processed request so that we can
- start it over entirely, or even put it back on the request queue. */
-static void restore_request (struct request *rq)
-{
- if (rq->buffer != rq->bh->b_data) {
- int n = (rq->buffer - rq->bh->b_data) / SECTOR_SIZE;
- rq->buffer = rq->bh->b_data;
- rq->nr_sectors += n;
- rq->sector -= n;
- }
- rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS;
- rq->hard_nr_sectors = rq->nr_sectors;
- rq->hard_sector = rq->sector;
-}
-
-/*
- * Start a read request from the CD-ROM.
- */
-static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
-{
- struct cdrom_info *info = drive->driver_data;
- struct request *rq = HWGROUP(drive)->rq;
- int minor = MINOR (rq->rq_dev);
-
- /* If the request is relative to a partition, fix it up to refer to the
- absolute address. */
- if (minor & PARTN_MASK) {
- rq->sector = block;
- minor &= ~PARTN_MASK;
- rq->rq_dev = MKDEV(MAJOR(rq->rq_dev), minor);
- }
-
- /* We may be retrying this request after an error. Fix up
- any weirdness which might be present in the request packet. */
- restore_request(rq);
-
- /* Satisfy whatever we can of this request from our cached sector. */
- if (cdrom_read_from_buffer(drive))
- return ide_stopped;
-
- cdrom_attempt_remerge(drive, rq);
-
- /* Clear the local sector buffer. */
- info->nsectors_buffered = 0;
-
- /* use dma, if possible. */
- if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) &&
- (rq->nr_sectors % SECTORS_PER_FRAME == 0))
- info->dma = 1;
- else
- info->dma = 0;
-
- info->cmd = READ;
- /* Start sending the read request to the drive. */
- return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
-}
-
-/****************************************************************************
- * Execute all other packet commands.
- */
-
-/* Forward declarations. */
-static int cdrom_lockdoor(ide_drive_t *drive, int lockflag,
- struct request_sense *sense);
-
-/* Interrupt routine for packet command completion. */
-static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
-{
- int ireason, len, stat, thislen;
- struct request *rq = HWGROUP(drive)->rq;
- struct packet_command *pc = (struct packet_command *)rq->buffer;
- ide_startstop_t startstop;
-
- /* Check for errors. */
- if (cdrom_decode_status (&startstop, drive, 0, &stat))
- return startstop;
-
- /* Read the interrupt reason and the transfer length. */
- ireason = IN_BYTE (IDE_NSECTOR_REG);
- len = IN_BYTE (IDE_LCYL_REG) + 256 * IN_BYTE (IDE_HCYL_REG);
-
- /* If DRQ is clear, the command has completed.
- Complain if we still have data left to transfer. */
- if ((stat & DRQ_STAT) == 0) {
- /* Some of the trailing request sense fields are optional, and
- some drives don't send them. Sigh. */
- if (pc->c[0] == GPCMD_REQUEST_SENSE &&
- pc->buflen > 0 &&
- pc->buflen <= 5) {
- while (pc->buflen > 0) {
- *pc->buffer++ = 0;
- --pc->buflen;
- }
- }
-
- if (pc->buflen == 0)
- cdrom_end_request (1, drive);
- else {
- /* Comment this out, because this always happens
- right after a reset occurs, and it is annoying to
- always print expected stuff. */
- /*
- printk ("%s: cdrom_pc_intr: data underrun %d\n",
- drive->name, pc->buflen);
- */
- pc->stat = 1;
- cdrom_end_request (1, drive);
- }
- return ide_stopped;
- }
-
- /* Figure out how much data to transfer. */
- thislen = pc->buflen;
- if (thislen > len) thislen = len;
-
- /* The drive wants to be written to. */
- if ((ireason & 3) == 0) {
- /* Transfer the data. */
- atapi_output_bytes (drive, pc->buffer, thislen);
-
- /* If we haven't moved enough data to satisfy the drive,
- add some padding. */
- while (len > thislen) {
- int dum = 0;
- atapi_output_bytes (drive, &dum, sizeof (dum));
- len -= sizeof (dum);
- }
-
- /* Keep count of how much data we've moved. */
- pc->buffer += thislen;
- pc->buflen -= thislen;
- }
-
- /* Same drill for reading. */
- else if ((ireason & 3) == 2) {
-
- /* Transfer the data. */
- atapi_input_bytes (drive, pc->buffer, thislen);
-
- /* If we haven't moved enough data to satisfy the drive,
- add some padding. */
- while (len > thislen) {
- int dum = 0;
- atapi_input_bytes (drive, &dum, sizeof (dum));
- len -= sizeof (dum);
- }
-
- /* Keep count of how much data we've moved. */
- pc->buffer += thislen;
- pc->buflen -= thislen;
- } else {
- printk ("%s: cdrom_pc_intr: The drive "
- "appears confused (ireason = 0x%2x)\n",
- drive->name, ireason);
- pc->stat = 1;
- }
-
- /* Now we wait for another interrupt. */
- ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry);
- return ide_started;
-}
-
-
-static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
- struct packet_command *pc = (struct packet_command *)rq->buffer;
-
- if (!pc->timeout)
- pc->timeout = WAIT_CMD;
-
- /* Send the command to the drive and return. */
- return cdrom_transfer_packet_command(drive, pc, &cdrom_pc_intr);
-}
-
-
-static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
-{
- int len;
- struct request *rq = HWGROUP(drive)->rq;
- struct packet_command *pc = (struct packet_command *)rq->buffer;
- struct cdrom_info *info = drive->driver_data;
-
- info->dma = 0;
- info->cmd = 0;
- pc->stat = 0;
- len = pc->buflen;
-
- /* Start sending the command to the drive. */
- return cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation);
-}
-
-
-/* Sleep for TIME jiffies.
- Not to be called from an interrupt handler. */
-static
-void cdrom_sleep (int time)
-{
- int sleep = time;
-
- do {
- set_current_state(TASK_INTERRUPTIBLE);
- sleep = schedule_timeout(sleep);
- } while (sleep);
-}
-
-static
-int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
-{
- struct request_sense sense;
- struct request req;
- int retries = 10;
-
- if (pc->sense == NULL)
- pc->sense = &sense;
-
- /* Start of retry loop. */
- do {
- ide_init_drive_cmd (&req);
- req.cmd = PACKET_COMMAND;
- req.buffer = (char *)pc;
- if (ide_do_drive_cmd (drive, &req, ide_wait)) {
- printk("%s: do_drive_cmd returned stat=%02x,err=%02x\n",
- drive->name, req.buffer[0], req.buffer[1]);
- /* FIXME: we should probably abort/retry or something */
- }
- if (pc->stat != 0) {
- /* The request failed. Retry if it was due to a unit
- attention status
- (usually means media was changed). */
- struct request_sense *reqbuf = pc->sense;
-
- if (reqbuf->sense_key == UNIT_ATTENTION)
- cdrom_saw_media_change (drive);
- else if (reqbuf->sense_key == NOT_READY &&
- reqbuf->asc == 4 && reqbuf->ascq != 4) {
- /* The drive is in the process of loading
- a disk. Retry, but wait a little to give
- the drive time to complete the load. */
- cdrom_sleep(2 * HZ);
- } else {
- /* Otherwise, don't retry. */
- retries = 0;
- }
- --retries;
- }
-
- /* End of retry loop. */
- } while (pc->stat != 0 && retries >= 0);
-
- /* Return an error if the command failed. */
- return pc->stat ? -EIO : 0;
-}
-
-/*
- * Write handling
- */
-static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
-{
- /* Two notes about IDE interrupt reason here - 0 means that
- * the drive wants to receive data from us, 2 means that
- * the drive is expecting data from us.
- */
- ireason &= 3;
-
- if (ireason == 2) {
- /* Whoops... The drive wants to send data. */
- printk("%s: cdrom_write_intr: wrong transfer direction!\n",
- drive->name);
-
- /* Throw some data at the drive so it doesn't hang
- and quit this request. */
- while (len > 0) {
- int dum = 0;
- atapi_output_bytes(drive, &dum, sizeof(dum));
- len -= sizeof(dum);
- }
- } else {
- /* Drive wants a command packet, or invalid ireason... */
- printk("%s: cdrom_write_intr: bad interrupt reason %d\n",
- drive->name, ireason);
- }
-
- cdrom_end_request(0, drive);
- return 1;
-}
-
-static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
-{
- int stat, ireason, len, sectors_to_transfer, uptodate;
- struct cdrom_info *info = drive->driver_data;
- int i, dma_error = 0, dma = info->dma;
- ide_startstop_t startstop;
-
- struct request *rq = HWGROUP(drive)->rq;
-
- /* Check for errors. */
- if (dma) {
- info->dma = 0;
- if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) {
- printk("ide-cd: write dma error\n");
- HWIF(drive)->dmaproc(ide_dma_off, drive);
- }
- }
-
- if (cdrom_decode_status(&startstop, drive, 0, &stat)) {
- printk("ide-cd: write_intr decode_status bad\n");
- return startstop;
- }
-
- /*
- * using dma, transfer is complete now
- */
- if (dma) {
- if (dma_error)
- return ide_error(drive, "dma error", stat);
-
- rq = HWGROUP(drive)->rq;
- for (i = rq->nr_sectors; i > 0;) {
- i -= rq->current_nr_sectors;
- ide_end_request(1, HWGROUP(drive));
- }
- return ide_stopped;
- }
-
- /* Read the interrupt reason and the transfer length. */
- ireason = IN_BYTE(IDE_NSECTOR_REG);
- len = IN_BYTE(IDE_LCYL_REG) + 256 * IN_BYTE(IDE_HCYL_REG);
-
- /* If DRQ is clear, the command has completed. */
- if ((stat & DRQ_STAT) == 0) {
- /* If we're not done writing, complain.
- * Otherwise, complete the command normally.
- */
- uptodate = 1;
- if (rq->current_nr_sectors > 0) {
- printk("%s: write_intr: data underrun (%ld blocks)\n",
- drive->name, rq->current_nr_sectors);
- uptodate = 0;
- }
- cdrom_end_request(uptodate, drive);
- return ide_stopped;
- }
-
- /* Check that the drive is expecting to do the same thing we are. */
- if (ireason & 3)
- if (cdrom_write_check_ireason(drive, len, ireason))
- return ide_stopped;
-
- sectors_to_transfer = len / SECTOR_SIZE;
-
- /*
- * now loop and write out the data
- */
- while (sectors_to_transfer > 0) {
- int this_transfer;
-
- if (!rq->current_nr_sectors) {
- printk("ide-cd: write_intr: oops\n");
- break;
- }
-
- /*
- * Figure out how many sectors we can transfer
- */
- this_transfer = MIN(sectors_to_transfer,rq->current_nr_sectors);
-
- while (this_transfer > 0) {
- atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE);
- rq->buffer += SECTOR_SIZE;
- --rq->nr_sectors;
- --rq->current_nr_sectors;
- ++rq->sector;
- --this_transfer;
- --sectors_to_transfer;
- }
-
- /*
- * current buffer complete, move on
- */
- if (rq->current_nr_sectors == 0 && rq->nr_sectors)
- cdrom_end_request (1, drive);
- }
-
- /* re-arm handler */
- ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL);
- return ide_started;
-}
-
-static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
-{
- struct packet_command pc; /* packet_command_t pc; */
- struct request *rq = HWGROUP(drive)->rq;
- unsigned nframes, frame;
-
- nframes = rq->nr_sectors >> 2;
- frame = rq->sector >> 2;
-
- memset(&pc.c, 0, sizeof(pc.c));
- /*
- * we might as well use WRITE_12, but none of the device I have
- * support the streaming feature anyway, so who cares.
- */
- pc.c[0] = GPCMD_WRITE_10;
-#if 0 /* the immediate bit */
- pc.c[1] = 1 << 3;
-#endif
- pc.c[7] = (nframes >> 8) & 0xff;
- pc.c[8] = nframes & 0xff;
- put_unaligned(cpu_to_be32(frame), (unsigned int *)&pc.c[2]);
- pc.timeout = 2 * WAIT_CMD;
-
- return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr);
-}
-
-static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
-{
- struct cdrom_info *info = drive->driver_data;
-
- /*
- * writes *must* be 2kB frame aligned
- */
- if ((rq->nr_sectors & 3) || (rq->sector & 3)) {
- cdrom_end_request(0, drive);
- return ide_stopped;
- }
-
- /*
- * for dvd-ram and such media, it's a really big deal to get
- * big writes all the time. so scour the queue and attempt to
- * remerge requests, often the plugging will not have had time
- * to do this properly
- */
- cdrom_attempt_remerge(drive, rq);
-
- info->nsectors_buffered = 0;
-
- /* use dma, if possible. we don't need to check more, since we
- * know that the transfer is always (at least!) 2KB aligned */
- info->dma = drive->using_dma ? 1 : 0;
- info->cmd = WRITE;
-
- /* Start sending the read request to the drive. */
- return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);
-}
-
-/****************************************************************************
- * cdrom driver request routine.
- */
-static ide_startstop_t
-ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
-{
- ide_startstop_t action;
- struct cdrom_info *info = drive->driver_data;
-
- switch (rq->cmd) {
- case WRITE:
- case READ: {
- if (CDROM_CONFIG_FLAGS(drive)->seeking) {
- unsigned long elpased = jiffies - info->start_seek;
- int stat = GET_STAT();
-
- if ((stat & SEEK_STAT) != SEEK_STAT) {
- if (elpased < IDECD_SEEK_TIMEOUT) {
- ide_stall_queue(drive, IDECD_SEEK_TIMER);
- return ide_stopped;
- }
- printk ("%s: DSC timeout\n", drive->name);
- }
- CDROM_CONFIG_FLAGS(drive)->seeking = 0;
- }
- if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
- action = cdrom_start_seek (drive, block);
- else {
- if (rq->cmd == READ)
- action = cdrom_start_read(drive, block);
- else
- action = cdrom_start_write(drive, rq);
- }
- info->last_block = block;
- return action;
- }
-
- case PACKET_COMMAND:
- case REQUEST_SENSE_COMMAND: {
- return cdrom_do_packet_command(drive);
- }
-
- case RESET_DRIVE_COMMAND: {
- cdrom_end_request(1, drive);
- return ide_do_reset(drive);
- }
-
- default: {
- printk("ide-cd: bad cmd %d\n", rq->cmd);
- cdrom_end_request(0, drive);
- return ide_stopped;
- }
- }
-}
-
-
-
-/****************************************************************************
- * Ioctl handling.
- *
- * Routines which queue packet commands take as a final argument a pointer
- * to a request_sense struct. If execution of the command results
- * in an error with a CHECK CONDITION status, this structure will be filled
- * with the results of the subsequent request sense command. The pointer
- * can also be NULL, in which case no sense information is returned.
- */
-
-#if ! STANDARD_ATAPI
-static inline
-int bin2bcd (int x)
-{
- return (x%10) | ((x/10) << 4);
-}
-
-
-static inline
-int bcd2bin (int x)
-{
- return (x >> 4) * 10 + (x & 0x0f);
-}
-
-static
-void msf_from_bcd (struct atapi_msf *msf)
-{
- msf->minute = bcd2bin (msf->minute);
- msf->second = bcd2bin (msf->second);
- msf->frame = bcd2bin (msf->frame);
-}
-
-#endif /* not STANDARD_ATAPI */
-
-
-static inline
-void lba_to_msf (int lba, byte *m, byte *s, byte *f)
-{
- lba += CD_MSF_OFFSET;
- lba &= 0xffffff; /* negative lbas use only 24 bits */
- *m = lba / (CD_SECS * CD_FRAMES);
- lba %= (CD_SECS * CD_FRAMES);
- *s = lba / CD_FRAMES;
- *f = lba % CD_FRAMES;
-}
-
-
-static inline
-int msf_to_lba (byte m, byte s, byte f)
-{
- return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
-}
-
-static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
-{
- struct packet_command pc;
- struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *cdi = &info->devinfo;
-
- memset(&pc, 0, sizeof(pc));
- pc.sense = sense;
-
- pc.c[0] = GPCMD_TEST_UNIT_READY;
-
-#if ! STANDARD_ATAPI
- /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
- switch CDs instead of supporting the LOAD_UNLOAD opcode */
-
- pc.c[7] = cdi->sanyo_slot % 3;
-#endif /* not STANDARD_ATAPI */
-
- return cdrom_queue_packet_command(drive, &pc);
-}
-
-
-/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
-static int
-cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
-{
- struct request_sense my_sense;
- struct packet_command pc;
- int stat;
-
- if (sense == NULL)
- sense = &my_sense;
-
- /* If the drive cannot lock the door, just pretend. */
- if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
- stat = 0;
- } else {
- memset(&pc, 0, sizeof(pc));
- pc.sense = sense;
- pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
- pc.c[4] = lockflag ? 1 : 0;
- stat = cdrom_queue_packet_command (drive, &pc);
- }
-
- /* If we got an illegal field error, the drive
- probably cannot lock the door. */
- if (stat != 0 &&
- sense->sense_key == ILLEGAL_REQUEST &&
- (sense->asc == 0x24 || sense->asc == 0x20)) {
- printk ("%s: door locking not supported\n",
- drive->name);
- CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
- stat = 0;
- }
-
- /* no medium, that's alright. */
- if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
- stat = 0;
-
- if (stat == 0)
- CDROM_STATE_FLAGS (drive)->door_locked = lockflag;
-
- return stat;
-}
-
-
-/* Eject the disk if EJECTFLAG is 0.
- If EJECTFLAG is 1, try to reload the disk. */
-static int cdrom_eject(ide_drive_t *drive, int ejectflag,
- struct request_sense *sense)
-{
- struct packet_command pc;
-
- if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag)
- return -EDRIVE_CANT_DO_THIS;
-
- /* reload fails on some drives, if the tray is locked */
- if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)
- return 0;
-
- memset(&pc, 0, sizeof (pc));
- pc.sense = sense;
-
- pc.c[0] = GPCMD_START_STOP_UNIT;
- pc.c[4] = 0x02 + (ejectflag != 0);
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
- struct request_sense *sense)
-{
- struct {
- __u32 lba;
- __u32 blocklen;
- } capbuf;
-
- int stat;
- struct packet_command pc;
-
- memset(&pc, 0, sizeof(pc));
- pc.sense = sense;
-
- pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
- pc.buffer = (char *)&capbuf;
- pc.buflen = sizeof(capbuf);
-
- stat = cdrom_queue_packet_command(drive, &pc);
- if (stat == 0)
- *capacity = 1 + be32_to_cpu(capbuf.lba);
-
- return stat;
-}
-
-static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
- int format, char *buf, int buflen,
- struct request_sense *sense)
-{
- struct packet_command pc;
-
- memset(&pc, 0, sizeof(pc));
- pc.sense = sense;
-
- pc.buffer = buf;
- pc.buflen = buflen;
- pc.quiet = 1;
- pc.c[0] = GPCMD_READ_TOC_PMA_ATIP;
- pc.c[6] = trackno;
- pc.c[7] = (buflen >> 8);
- pc.c[8] = (buflen & 0xff);
- pc.c[9] = (format << 6);
-
- if (msf_flag)
- pc.c[1] = 2;
-
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-/* Try to read the entire TOC for the disk into our internal buffer. */
-static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
-{
- int minor, stat, ntracks, i;
- kdev_t dev;
- struct cdrom_info *info = drive->driver_data;
- struct atapi_toc *toc = info->toc;
- struct {
- struct atapi_toc_header hdr;
- struct atapi_toc_entry ent;
- } ms_tmp;
-
- if (toc == NULL) {
- /* Try to allocate space. */
- toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc),
- GFP_KERNEL);
- info->toc = toc;
- if (toc == NULL) {
- printk ("%s: No cdrom TOC buffer!\n", drive->name);
- return -ENOMEM;
- }
- }
-
- /* Check to see if the existing data is still valid.
- If it is, just return. */
- (void) cdrom_check_status(drive, sense);
-
- if (CDROM_STATE_FLAGS(drive)->toc_valid)
- return 0;
-
- /* First read just the header, so we know how long the TOC is. */
- stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
- sizeof(struct atapi_toc_header), sense);
- if (stat) return stat;
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {
- toc->hdr.first_track = bcd2bin (toc->hdr.first_track);
- toc->hdr.last_track = bcd2bin (toc->hdr.last_track);
- }
-#endif /* not STANDARD_ATAPI */
-
- ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
- if (ntracks <= 0)
- return -EIO;
- if (ntracks > MAX_TRACKS)
- ntracks = MAX_TRACKS;
-
- /* Now read the whole schmeer. */
- stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,
- (char *)&toc->hdr,
- sizeof(struct atapi_toc_header) +
- (ntracks + 1) *
- sizeof(struct atapi_toc_entry), sense);
-
- if (stat && toc->hdr.first_track > 1) {
- /* Cds with CDI tracks only don't have any TOC entries,
- despite of this the returned values are
- first_track == last_track = number of CDI tracks + 1,
- so that this case is indistinguishable from the same
- layout plus an additional audio track.
- If we get an error for the regular case, we assume
- a CDI without additional audio tracks. In this case
- the readable TOC is empty (CDI tracks are not included)
- and only holds the Leadout entry. Heiko Eißfeldt */
- ntracks = 0;
- stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
- (char *)&toc->hdr,
- sizeof(struct atapi_toc_header) +
- (ntracks + 1) *
- sizeof(struct atapi_toc_entry),
- sense);
- if (stat) {
- return stat;
- }
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {
- toc->hdr.first_track = bin2bcd(CDROM_LEADOUT);
- toc->hdr.last_track = bin2bcd(CDROM_LEADOUT);
- } else
-#endif /* not STANDARD_ATAPI */
- {
- toc->hdr.first_track = CDROM_LEADOUT;
- toc->hdr.last_track = CDROM_LEADOUT;
- }
- }
-
- if (stat)
- return stat;
-
- toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {
- toc->hdr.first_track = bcd2bin (toc->hdr.first_track);
- toc->hdr.last_track = bcd2bin (toc->hdr.last_track);
- }
-#endif /* not STANDARD_ATAPI */
-
- for (i=0; i<=ntracks; i++) {
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd) {
- if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd)
- toc->ent[i].track = bcd2bin (toc->ent[i].track);
- msf_from_bcd (&toc->ent[i].addr.msf);
- }
-#endif /* not STANDARD_ATAPI */
- toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
- toc->ent[i].addr.msf.second,
- toc->ent[i].addr.msf.frame);
- }
-
- /* Read the multisession information. */
- if (toc->hdr.first_track != CDROM_LEADOUT) {
- /* Read the multisession information. */
- stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
- sizeof(ms_tmp), sense);
- if (stat) return stat;
- } else {
- ms_tmp.ent.addr.msf.minute = 0;
- ms_tmp.ent.addr.msf.second = 2;
- ms_tmp.ent.addr.msf.frame = 0;
- ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
- }
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd)
- msf_from_bcd (&ms_tmp.ent.addr.msf);
-#endif /* not STANDARD_ATAPI */
-
- toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute,
- ms_tmp.ent.addr.msf.second,
- ms_tmp.ent.addr.msf.frame);
-
- toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
-
- /* Now try to get the total cdrom capacity. */
- minor = (drive->select.b.unit) << PARTN_BITS;
- dev = MKDEV(HWIF(drive)->major, minor);
- stat = cdrom_get_last_written(dev, &toc->capacity);
- if (stat)
- stat = cdrom_read_capacity(drive, &toc->capacity, sense);
- if (stat)
- toc->capacity = 0x1fffff;
-
- HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
- drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
-
- /* Remember that we've read this stuff. */
- CDROM_STATE_FLAGS (drive)->toc_valid = 1;
-
- return 0;
-}
-
-
-static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
- int buflen, struct request_sense *sense)
-{
- struct packet_command pc;
-
- memset(&pc, 0, sizeof(pc));
- pc.sense = sense;
-
- pc.buffer = buf;
- pc.buflen = buflen;
- pc.c[0] = GPCMD_READ_SUBCHANNEL;
- pc.c[1] = 2; /* MSF addressing */
- pc.c[2] = 0x40; /* request subQ data */
- pc.c[3] = format;
- pc.c[7] = (buflen >> 8);
- pc.c[8] = (buflen & 0xff);
- return cdrom_queue_packet_command(drive, &pc);
-}
-
-/* ATAPI cdrom drives are free to select the speed you request or any slower
- rate :-( Requesting too fast a speed will _not_ produce an error. */
-static int cdrom_select_speed(ide_drive_t *drive, int speed,
- struct request_sense *sense)
-{
- struct packet_command pc;
- memset(&pc, 0, sizeof(pc));
- pc.sense = sense;
-
- if (speed == 0)
- speed = 0xffff; /* set to max */
- else
- speed *= 177; /* Nx to kbytes/s */
-
- pc.c[0] = GPCMD_SET_SPEED;
- /* Read Drive speed in kbytes/second MSB */
- pc.c[2] = (speed >> 8) & 0xff;
- /* Read Drive speed in kbytes/second LSB */
- pc.c[3] = speed & 0xff;
- if (CDROM_CONFIG_FLAGS(drive)->cd_r ||
- CDROM_CONFIG_FLAGS(drive)->cd_rw ||
- CDROM_CONFIG_FLAGS(drive)->dvd_r) {
- /* Write Drive speed in kbytes/second MSB */
- pc.c[4] = (speed >> 8) & 0xff;
- /* Write Drive speed in kbytes/second LSB */
- pc.c[5] = speed & 0xff;
- }
-
- return cdrom_queue_packet_command(drive, &pc);
-}
-
-static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
-{
- struct request_sense sense;
- struct packet_command pc;
-
- memset(&pc, 0, sizeof (pc));
- pc.sense = &sense;
-
- pc.c[0] = GPCMD_PLAY_AUDIO_MSF;
- lba_to_msf(lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
- lba_to_msf(lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);
-
- return cdrom_queue_packet_command(drive, &pc);
-}
-
-static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
- struct atapi_toc_entry **ent)
-{
- struct cdrom_info *info = drive->driver_data;
- struct atapi_toc *toc = info->toc;
- int ntracks;
-
- /*
- * don't serve cached data, if the toc isn't valid
- */
- if (!CDROM_STATE_FLAGS(drive)->toc_valid)
- return -EINVAL;
-
- /* Check validity of requested track number. */
- ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
- if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0;
- if (track == CDROM_LEADOUT)
- *ent = &toc->ent[ntracks];
- else if (track < toc->hdr.first_track ||
- track > toc->hdr.last_track)
- return -EINVAL;
- else
- *ent = &toc->ent[track - toc->hdr.first_track];
-
- return 0;
-}
-
-/* the generic packet interface to cdrom.c */
-static int ide_cdrom_packet(struct cdrom_device_info *cdi,
- struct cdrom_generic_command *cgc)
-{
- struct packet_command pc;
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
-
- if (cgc->timeout <= 0)
- cgc->timeout = WAIT_CMD;
-
- /* here we queue the commands from the uniform CD-ROM
- layer. the packet must be complete, as we do not
- touch it at all. */
- memset(&pc, 0, sizeof(pc));
- memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE);
- pc.buffer = cgc->buffer;
- pc.buflen = cgc->buflen;
- pc.quiet = cgc->quiet;
- pc.timeout = cgc->timeout;
- pc.sense = cgc->sense;
- return cgc->stat = cdrom_queue_packet_command(drive, &pc);
-}
-
-static
-int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
- unsigned int cmd, unsigned long arg)
-{
- struct cdrom_generic_command cgc;
- char buffer[16];
- int stat;
-
- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
-
- /* These will be moved into the Uniform layer shortly... */
- switch (cmd) {
- case CDROMSETSPINDOWN: {
- char spindown;
-
- if (copy_from_user(&spindown, (void *) arg, sizeof(char)))
- return -EFAULT;
-
- if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
- return stat;
-
- buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
-
- return cdrom_mode_select(cdi, &cgc);
- }
-
- case CDROMGETSPINDOWN: {
- char spindown;
-
- if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
- return stat;
-
- spindown = buffer[11] & 0x0f;
-
- if (copy_to_user((void *) arg, &spindown, sizeof (char)))
- return -EFAULT;
-
- return 0;
- }
-
- default:
- return -EINVAL;
- }
-
-}
-
-static
-int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg)
-
-{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct cdrom_info *info = drive->driver_data;
- int stat;
-
- switch (cmd) {
- /*
- * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
- * atapi doesn't support it
- */
- case CDROMPLAYTRKIND: {
- unsigned long lba_start, lba_end;
- struct cdrom_ti *ti = (struct cdrom_ti *)arg;
- struct atapi_toc_entry *first_toc, *last_toc;
-
- stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
- if (stat)
- return stat;
-
- stat = cdrom_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
- if (stat)
- return stat;
-
- if (ti->cdti_trk1 != CDROM_LEADOUT)
- ++last_toc;
- lba_start = first_toc->addr.lba;
- lba_end = last_toc->addr.lba;
-
- if (lba_end <= lba_start)
- return -EINVAL;
-
- return cdrom_play_audio(drive, lba_start, lba_end);
- }
-
- case CDROMREADTOCHDR: {
- struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
- struct atapi_toc *toc;
-
- /* Make sure our saved TOC is valid. */
- stat = cdrom_read_toc(drive, NULL);
- if (stat) return stat;
-
- toc = info->toc;
- tochdr->cdth_trk0 = toc->hdr.first_track;
- tochdr->cdth_trk1 = toc->hdr.last_track;
-
- return 0;
- }
-
- case CDROMREADTOCENTRY: {
- struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg;
- struct atapi_toc_entry *toce;
-
- stat = cdrom_get_toc_entry (drive, tocentry->cdte_track, &toce);
- if (stat) return stat;
-
- tocentry->cdte_ctrl = toce->control;
- tocentry->cdte_adr = toce->adr;
- if (tocentry->cdte_format == CDROM_MSF) {
- lba_to_msf (toce->addr.lba,
- &tocentry->cdte_addr.msf.minute,
- &tocentry->cdte_addr.msf.second,
- &tocentry->cdte_addr.msf.frame);
- } else
- tocentry->cdte_addr.lba = toce->addr.lba;
-
- return 0;
- }
-
- default:
- return -EINVAL;
- }
-}
-
-static
-int ide_cdrom_reset (struct cdrom_device_info *cdi)
-{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct request_sense sense;
- struct request req;
- int ret;
-
- ide_init_drive_cmd (&req);
- req.cmd = RESET_DRIVE_COMMAND;
- ret = ide_do_drive_cmd(drive, &req, ide_wait);
-
- /*
- * A reset will unlock the door. If it was previously locked,
- * lock it again.
- */
- if (CDROM_STATE_FLAGS(drive)->door_locked)
- (void) cdrom_lockdoor(drive, 1, &sense);
-
- return ret;
-}
-
-
-static
-int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
-{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct request_sense sense;
-
- if (position) {
- int stat = cdrom_lockdoor(drive, 0, &sense);
- if (stat) return stat;
- }
-
- return cdrom_eject(drive, !position, &sense);
-}
-
-static
-int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
-{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- return cdrom_lockdoor(drive, lock, NULL);
-}
-
-static
-int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
-{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct request_sense sense;
- int stat;
-
- if ((stat = cdrom_select_speed (drive, speed, &sense)) < 0)
- return stat;
-
- cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed;
- return 0;
-}
-
-static
-int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
-{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
-
- if (slot_nr == CDSL_CURRENT) {
- struct request_sense sense;
- int stat = cdrom_check_status(drive, &sense);
- if (stat == 0 || sense.sense_key == UNIT_ATTENTION)
- return CDS_DISC_OK;
-
- if (sense.sense_key == NOT_READY && sense.asc == 0x04 &&
- sense.ascq == 0x04)
- return CDS_DISC_OK;
-
-
- /*
- * If not using Mt Fuji extended media tray reports,
- * just return TRAY_OPEN since ATAPI doesn't provide
- * any other way to detect this...
- */
- if (sense.sense_key == NOT_READY) {
- if (sense.asc == 0x3a && sense.ascq == 1)
- return CDS_NO_DISC;
- else
- return CDS_TRAY_OPEN;
- }
-
- return CDS_DRIVE_NOT_READY;
- }
- return -EINVAL;
-}
-
-static
-int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
- struct cdrom_multisession *ms_info)
-{
- struct atapi_toc *toc;
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct cdrom_info *info = drive->driver_data;
- struct request_sense sense;
- int ret;
-
- if (!CDROM_STATE_FLAGS(drive)->toc_valid || info->toc == NULL)
- if ((ret = cdrom_read_toc(drive, &sense)))
- return ret;
-
- toc = info->toc;
- ms_info->addr.lba = toc->last_session_lba;
- ms_info->xa_flag = toc->xa_flag;
-
- return 0;
-}
-
-static
-int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
- struct cdrom_mcn *mcn_info)
-{
- int stat;
- char mcnbuf[24];
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
-
-/* get MCN */
- if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
- return stat;
-
- memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
- sizeof (mcn_info->medium_catalog_number)-1);
- mcn_info->medium_catalog_number[sizeof (mcn_info->medium_catalog_number)-1]
- = '\0';
-
- return 0;
-}
-
-
-
-/****************************************************************************
- * Other driver requests (open, close, check media change).
- */
-
-static
-int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
- int slot_nr)
-{
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- int retval;
-
- if (slot_nr == CDSL_CURRENT) {
- (void) cdrom_check_status(drive, NULL);
- retval = CDROM_STATE_FLAGS (drive)->media_changed;
- CDROM_STATE_FLAGS (drive)->media_changed = 0;
- return retval;
- } else {
- return -EINVAL;
- }
-}
-
-
-static
-int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose)
-{
- return 0;
-}
-
-
-/*
- * Close down the device. Invalidate all cached blocks.
- */
-
-static
-void ide_cdrom_release_real (struct cdrom_device_info *cdi)
-{
-}
-
-
-
-/****************************************************************************
- * Device initialization.
- */
-static struct cdrom_device_ops ide_cdrom_dops = {
- open: ide_cdrom_open_real,
- release: ide_cdrom_release_real,
- drive_status: ide_cdrom_drive_status,
- media_changed: ide_cdrom_check_media_change_real,
- tray_move: ide_cdrom_tray_move,
- lock_door: ide_cdrom_lock_door,
- select_speed: ide_cdrom_select_speed,
- get_last_session: ide_cdrom_get_last_session,
- get_mcn: ide_cdrom_get_mcn,
- reset: ide_cdrom_reset,
- audio_ioctl: ide_cdrom_audio_ioctl,
- dev_ioctl: ide_cdrom_dev_ioctl,
- capability: CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
- CDC_SELECT_SPEED | CDC_SELECT_DISC |
- CDC_MULTI_SESSION | CDC_MCN |
- CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
- CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R |
- CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
- CDC_GENERIC_PACKET,
- generic_packet: ide_cdrom_packet,
-};
-
-static int ide_cdrom_register (ide_drive_t *drive, int nslots)
-{
- struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *devinfo = &info->devinfo;
- int minor = (drive->select.b.unit) << PARTN_BITS;
-
- devinfo->dev = MKDEV (HWIF(drive)->major, minor);
- devinfo->ops = &ide_cdrom_dops;
- devinfo->mask = 0;
- *(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed;
- *(int *)&devinfo->capacity = nslots;
- devinfo->handle = (void *) drive;
- strcpy(devinfo->name, drive->name);
-
- /* set capability mask to match the probe. */
- if (!CDROM_CONFIG_FLAGS (drive)->cd_r)
- devinfo->mask |= CDC_CD_R;
- if (!CDROM_CONFIG_FLAGS (drive)->cd_rw)
- devinfo->mask |= CDC_CD_RW;
- if (!CDROM_CONFIG_FLAGS (drive)->dvd)
- devinfo->mask |= CDC_DVD;
- if (!CDROM_CONFIG_FLAGS (drive)->dvd_r)
- devinfo->mask |= CDC_DVD_R;
- if (!CDROM_CONFIG_FLAGS (drive)->dvd_ram)
- devinfo->mask |= CDC_DVD_RAM;
- if (!CDROM_CONFIG_FLAGS (drive)->is_changer)
- devinfo->mask |= CDC_SELECT_DISC;
- if (!CDROM_CONFIG_FLAGS (drive)->audio_play)
- devinfo->mask |= CDC_PLAY_AUDIO;
- if (!CDROM_CONFIG_FLAGS (drive)->close_tray)
- devinfo->mask |= CDC_CLOSE_TRAY;
-
-#if 0
- devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT,
- HWIF(drive)->major, minor,
- S_IFBLK | S_IRUGO | S_IWUGO,
- ide_fops, NULL);
-#endif
-
- return register_cdrom(devinfo);
-}
-
-static
-int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
-{
- struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *cdi = &info->devinfo;
- struct cdrom_generic_command cgc;
- int stat, attempts = 3, size = sizeof(*cap);
-
- /*
- * ACER50 (and others?) require the full spec length mode sense
- * page capabilities size, but older drives break.
- */
- if (drive->id) {
- if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
- !strcmp(drive->id->model, "WPI CDS-32X")))
- size -= sizeof(cap->pad);
- }
-
- /* we have to cheat a little here. the packet will eventually
- * be queued with ide_cdrom_packet(), which extracts the
- * drive from cdi->handle. Since this device hasn't been
- * registered with the Uniform layer yet, it can't do this.
- * Same goes for cdi->ops.
- */
- cdi->handle = (ide_drive_t *) drive;
- cdi->ops = &ide_cdrom_dops;
- init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
- do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
- stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
- if (!stat)
- break;
- } while (--attempts);
- return stat;
-}
-
-static
-int ide_cdrom_probe_capabilities (ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *cdi = &info->devinfo;
- struct atapi_capabilities_page cap;
- int nslots = 1;
-
- if (CDROM_CONFIG_FLAGS (drive)->nec260) {
- CDROM_CONFIG_FLAGS (drive)->no_eject = 0;
- CDROM_CONFIG_FLAGS (drive)->audio_play = 1;
- return nslots;
- }
-
- if (ide_cdrom_get_capabilities(drive, &cap))
- return 0;
-
- if (cap.lock == 0)
- CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
- if (cap.eject)
- CDROM_CONFIG_FLAGS (drive)->no_eject = 0;
- if (cap.cd_r_write)
- CDROM_CONFIG_FLAGS (drive)->cd_r = 1;
- if (cap.cd_rw_write)
- CDROM_CONFIG_FLAGS (drive)->cd_rw = 1;
- if (cap.test_write)
- CDROM_CONFIG_FLAGS (drive)->test_write = 1;
- if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom)
- CDROM_CONFIG_FLAGS (drive)->dvd = 1;
- if (cap.dvd_ram_write)
- CDROM_CONFIG_FLAGS (drive)->dvd_ram = 1;
- if (cap.dvd_r_write)
- CDROM_CONFIG_FLAGS (drive)->dvd_r = 1;
- if (cap.audio_play)
- CDROM_CONFIG_FLAGS (drive)->audio_play = 1;
- if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup)
- CDROM_CONFIG_FLAGS (drive)->close_tray = 0;
-
-#if ! STANDARD_ATAPI
- if (cdi->sanyo_slot > 0) {
- CDROM_CONFIG_FLAGS (drive)->is_changer = 1;
- nslots = 3;
- }
-
- else
-#endif /* not STANDARD_ATAPI */
- if (cap.mechtype == mechtype_individual_changer ||
- cap.mechtype == mechtype_cartridge_changer) {
- if ((nslots = cdrom_number_of_slots(cdi)) > 1) {
- CDROM_CONFIG_FLAGS (drive)->is_changer = 1;
- CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 1;
- }
- }
-
- /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
- if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
- CDROM_STATE_FLAGS (drive)->current_speed =
- (((unsigned int)cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS (drive)->max_speed =
- (((unsigned int)cap.maxspeed) + (176/2)) / 176;
- } else {
- CDROM_STATE_FLAGS (drive)->current_speed =
- (ntohs(cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS (drive)->max_speed =
- (ntohs(cap.maxspeed) + (176/2)) / 176;
- }
-
- /* don't print speed if the drive reported 0.
- */
- printk("%s: ATAPI", drive->name);
- if (CDROM_CONFIG_FLAGS(drive)->max_speed)
- printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed);
- printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM");
-
- if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram)
- printk (" DVD%s%s",
- (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "",
- (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "-RAM" : "");
-
- if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw)
- printk (" CD%s%s",
- (CDROM_CONFIG_FLAGS (drive)->cd_r)? "-R" : "",
- (CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : "");
-
- if (CDROM_CONFIG_FLAGS (drive)->is_changer)
- printk (" changer w/%d slots", nslots);
- else
- printk (" drive");
-
- printk (", %dkB Cache", be16_to_cpu(cap.buffer_size));
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (drive->using_dma)
- (void) HWIF(drive)->dmaproc(ide_dma_verbose, drive);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
- printk("\n");
-
- return nslots;
-}
-
-static void ide_cdrom_add_settings(ide_drive_t *drive)
-{
-#if 0
- int major = HWIF(drive)->major;
- int minor = drive->select.b.unit << PARTN_BITS;
-
- ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL);
- ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL);
- ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);
-#endif
- ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
-}
-
-static
-int ide_cdrom_setup (ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *cdi = &info->devinfo;
- int minor = drive->select.b.unit << PARTN_BITS;
- int nslots;
-
- /*
- * default to read-only always and fix latter at the bottom
- */
- set_device_ro(MKDEV(HWIF(drive)->major, minor), 1);
-#if 0
- set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
-#endif
-
- drive->special.all = 0;
- drive->ready_stat = 0;
-
- CDROM_STATE_FLAGS (drive)->media_changed = 1;
- CDROM_STATE_FLAGS (drive)->toc_valid = 0;
- CDROM_STATE_FLAGS (drive)->door_locked = 0;
-
-#if NO_DOOR_LOCKING
- CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
-#else
- CDROM_CONFIG_FLAGS (drive)->no_doorlock = 0;
-#endif
-
- if (drive->id != NULL)
- CDROM_CONFIG_FLAGS (drive)->drq_interrupt =
- ((drive->id->config & 0x0060) == 0x20);
- else
- CDROM_CONFIG_FLAGS (drive)->drq_interrupt = 0;
-
- CDROM_CONFIG_FLAGS (drive)->is_changer = 0;
- CDROM_CONFIG_FLAGS (drive)->cd_r = 0;
- CDROM_CONFIG_FLAGS (drive)->cd_rw = 0;
- CDROM_CONFIG_FLAGS (drive)->test_write = 0;
- CDROM_CONFIG_FLAGS (drive)->dvd = 0;
- CDROM_CONFIG_FLAGS (drive)->dvd_r = 0;
- CDROM_CONFIG_FLAGS (drive)->dvd_ram = 0;
- CDROM_CONFIG_FLAGS (drive)->no_eject = 1;
- CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0;
- CDROM_CONFIG_FLAGS (drive)->audio_play = 0;
- CDROM_CONFIG_FLAGS (drive)->close_tray = 1;
-
- /* limit transfer size per interrupt. */
- CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0;
- if (drive->id != NULL) {
- /* a testament to the nice quality of Samsung drives... */
- if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430"))
- CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
- else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
- CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
- /* the 3231 model does not support the SET_CD_SPEED command */
- else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231"))
- cdi->mask |= CDC_SELECT_SPEED;
- }
-
-#if ! STANDARD_ATAPI
- /* by default Sanyo 3 CD changer support is turned off and
- ATAPI Rev 2.2+ standard support for CD changers is used */
- cdi->sanyo_slot = 0;
-
- CDROM_CONFIG_FLAGS (drive)->nec260 = 0;
- CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 0;
- CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 0;
- CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 0;
- CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 0;
-
- if (drive->id != NULL) {
- if (strcmp (drive->id->model, "V003S0DS") == 0 &&
- drive->id->fw_rev[4] == '1' &&
- drive->id->fw_rev[6] <= '2') {
- /* Vertos 300.
- Some versions of this drive like to talk BCD. */
- CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1;
- CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1;
- CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1;
- CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1;
- }
-
- else if (strcmp (drive->id->model, "V006E0DS") == 0 &&
- drive->id->fw_rev[4] == '1' &&
- drive->id->fw_rev[6] <= '2') {
- /* Vertos 600 ESD. */
- CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd = 1;
- }
-
- else if (strcmp (drive->id->model,
- "NEC CD-ROM DRIVE:260") == 0 &&
- strncmp (drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */
- /* Old NEC260 (not R).
- This drive was released before the 1.2 version
- of the spec. */
- CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd = 1;
- CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1;
- CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1;
- CDROM_CONFIG_FLAGS (drive)->nec260 = 1;
- }
-
- else if (strcmp (drive->id->model, "WEARNES CDD-120") == 0 &&
- strncmp (drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */
- /* Wearnes */
- CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd = 1;
- CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1;
- }
-
- /* Sanyo 3 CD changer uses a non-standard command
- for CD changing */
- else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) ||
- (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) ||
- (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) {
- /* uses CD in slot 0 when value is set to 3 */
- cdi->sanyo_slot = 3;
- }
-
-
- }
-#endif /* not STANDARD_ATAPI */
-
- info->toc = NULL;
- info->buffer = NULL;
- info->sector_buffered = 0;
- info->nsectors_buffered = 0;
- info->changer_info = NULL;
- info->last_block = 0;
- info->start_seek = 0;
-
- nslots = ide_cdrom_probe_capabilities (drive);
-
- if (CDROM_CONFIG_FLAGS(drive)->dvd_ram)
- set_device_ro(MKDEV(HWIF(drive)->major, minor), 0);
-
- if (ide_cdrom_register (drive, nslots)) {
- printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
- info->devinfo.handle = NULL;
- return 1;
- }
- ide_cdrom_add_settings(drive);
- return 0;
-}
-
-/* Forwarding functions to generic routines. */
-static
-int ide_cdrom_ioctl (ide_drive_t *drive,
- struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return cdrom_ioctl (inode, file, cmd, arg);
-}
-
-static
-int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- int rc = -ENOMEM;
-
- MOD_INC_USE_COUNT;
- if (info->buffer == NULL)
- info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
- if ((info->buffer == NULL) || (rc = cdrom_open(ip, fp))) {
- drive->usage--;
- MOD_DEC_USE_COUNT;
- }
- return rc;
-}
-
-static
-void ide_cdrom_release (struct inode *inode, struct file *file,
- ide_drive_t *drive)
-{
- cdrom_release (inode, file);
- MOD_DEC_USE_COUNT;
-}
-
-static
-int ide_cdrom_check_media_change (ide_drive_t *drive)
-{
- return cdrom_media_changed(MKDEV (HWIF (drive)->major,
- (drive->select.b.unit) << PARTN_BITS));
-}
-
-static
-void ide_cdrom_revalidate (ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- struct atapi_toc *toc;
- int minor = drive->select.b.unit << PARTN_BITS;
- struct request_sense sense;
-
- cdrom_read_toc(drive, &sense);
-
- if (!CDROM_STATE_FLAGS(drive)->toc_valid)
- return;
-
- toc = info->toc;
-
- /* for general /dev/cdrom like mounting, one big disc */
- drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
- HWIF(drive)->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
-
- /*
- * reset block size, ide_revalidate_disk incorrectly sets it to
- * 1024 even for CDROM's
- */
- blk_size[HWIF(drive)->major] = HWIF(drive)->gd->sizes;
-#if 0
- set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
-#endif
-}
-
-static
-unsigned long ide_cdrom_capacity (ide_drive_t *drive)
-{
- unsigned long capacity;
-
- if (cdrom_read_capacity(drive, &capacity, NULL))
- return 0;
-
- return capacity * SECTORS_PER_FRAME;
-}
-
-static
-int ide_cdrom_cleanup(ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *devinfo = &info->devinfo;
-
- if (ide_unregister_subdriver (drive))
- return 1;
- if (info->buffer != NULL)
- kfree(info->buffer);
- if (info->toc != NULL)
- kfree(info->toc);
- if (info->changer_info != NULL)
- kfree(info->changer_info);
- if (devinfo->handle == drive && unregister_cdrom (devinfo))
- printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
- kfree(info);
- drive->driver_data = NULL;
- return 0;
-}
-
-#if 0
-static
-int ide_cdrom_reinit (ide_drive_t *drive)
-{
- return 0;
-}
-#endif /* 0 */
-
-static ide_driver_t ide_cdrom_driver = {
- name: "ide-cdrom",
- version: IDECD_VERSION,
- media: ide_cdrom,
- busy: 0,
- supports_dma: 1,
- supports_dsc_overlap: 1,
- cleanup: ide_cdrom_cleanup,
- do_request: ide_do_rw_cdrom,
- end_request: NULL,
- ioctl: ide_cdrom_ioctl,
- open: ide_cdrom_open,
- release: ide_cdrom_release,
- media_change: ide_cdrom_check_media_change,
- revalidate: ide_cdrom_revalidate,
- pre_reset: NULL,
- capacity: ide_cdrom_capacity,
- special: NULL,
-#if 0
- proc: NULL,
- driver_reinit: ide_cdrom_reinit,
-#endif
-};
-
-int ide_cdrom_init(void);
-static ide_module_t ide_cdrom_module = {
- IDE_DRIVER_MODULE,
- ide_cdrom_init,
- &ide_cdrom_driver,
- NULL
-};
-
-/* options */
-char *ignore = NULL;
-
-MODULE_PARM(ignore, "s");
-MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
-
-static void __exit ide_cdrom_exit(void)
-{
- ide_drive_t *drive;
- int failed = 0;
-
- while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, &ide_cdrom_driver, failed)) != NULL)
- if (ide_cdrom_cleanup (drive)) {
- printk ("%s: cleanup_module() called while still busy\n", drive->name);
- failed++;
- }
- ide_unregister_module (&ide_cdrom_module);
-}
-
-int ide_cdrom_init(void)
-{
- ide_drive_t *drive;
- struct cdrom_info *info;
- int failed = 0;
-
- MOD_INC_USE_COUNT;
- while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) {
- /* skip drives that we were told to ignore */
- if (ignore != NULL) {
- if (strstr(ignore, drive->name)) {
- printk("ide-cd: ignoring drive %s\n", drive->name);
- continue;
- }
- }
- if (drive->scsi) {
- printk("ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
- continue;
- }
- info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
- if (info == NULL) {
- printk ("%s: Can't allocate a cdrom structure\n", drive->name);
- continue;
- }
- if (ide_register_subdriver (drive, &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) {
- printk ("%s: Failed to register the driver with ide.c\n", drive->name);
- kfree (info);
- continue;
- }
- memset (info, 0, sizeof (struct cdrom_info));
- drive->driver_data = info;
- DRIVER(drive)->busy++;
- if (ide_cdrom_setup (drive)) {
- DRIVER(drive)->busy--;
- if (ide_cdrom_cleanup (drive))
- printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name);
- continue;
- }
- DRIVER(drive)->busy--;
- failed--;
- }
- ide_register_module(&ide_cdrom_module);
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-module_init(ide_cdrom_init);
-module_exit(ide_cdrom_exit);
-MODULE_LICENSE("GPL");
diff --git a/xen/drivers/ide/ide-cd.h b/xen/drivers/ide/ide-cd.h
deleted file mode 100644
index 41db4722c5..0000000000
--- a/xen/drivers/ide/ide-cd.h
+++ /dev/null
@@ -1,746 +0,0 @@
-/*
- * linux/drivers/ide/ide_cd.h
- *
- * Copyright (C) 1996-98 Erik Andersen
- * Copyright (C) 1998-2000 Jens Axboe
- */
-#ifndef _IDE_CD_H
-#define _IDE_CD_H
-
-#include <xen/cdrom.h>
-#include <asm/byteorder.h>
-
-/* Turn this on to have the driver print out the meanings of the
- ATAPI error codes. This will use up additional kernel-space
- memory, though. */
-
-#ifndef VERBOSE_IDE_CD_ERRORS
-#define VERBOSE_IDE_CD_ERRORS 1
-#endif
-
-
-/* Turning this on will remove code to work around various nonstandard
- ATAPI implementations. If you know your drive follows the standard,
- this will give you a slightly smaller kernel. */
-
-#ifndef STANDARD_ATAPI
-#define STANDARD_ATAPI 0
-#endif
-
-
-/* Turning this on will disable the door-locking functionality.
- This is apparently needed for supermount. */
-
-#ifndef NO_DOOR_LOCKING
-#define NO_DOOR_LOCKING 0
-#endif
-
-/************************************************************************/
-
-#define SECTOR_BITS 9
-// XXX SMH: already defined in ide.h
-#ifdef SECTOR_SIZE
-#undef SECTOR_SIZE
-#endif
-#define SECTOR_SIZE (1 << SECTOR_BITS)
-#define SECTORS_PER_FRAME (CD_FRAMESIZE >> SECTOR_BITS)
-#define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32)
-#define SECTORS_BUFFER (SECTOR_BUFFER_SIZE >> SECTOR_BITS)
-#define SECTORS_MAX (131072 >> SECTOR_BITS)
-
-#define BLOCKS_PER_FRAME (CD_FRAMESIZE / BLOCK_SIZE)
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-/* special command codes for strategy routine. */
-#define PACKET_COMMAND 4315
-#define REQUEST_SENSE_COMMAND 4316
-#define RESET_DRIVE_COMMAND 4317
-
-
-/* Configuration flags. These describe the capabilities of the drive.
- They generally do not change after initialization, unless we learn
- more about the drive from stuff failing. */
-struct ide_cd_config_flags {
- __u8 drq_interrupt : 1; /* Device sends an interrupt when ready
- for a packet command. */
- __u8 no_doorlock : 1; /* Drive cannot lock the door. */
- __u8 no_eject : 1; /* Drive cannot eject the disc. */
- __u8 nec260 : 1; /* Drive is a pre-1.2 NEC 260 drive. */
- __u8 playmsf_as_bcd : 1; /* PLAYMSF command takes BCD args. */
- __u8 tocaddr_as_bcd : 1; /* TOC addresses are in BCD. */
- __u8 toctracks_as_bcd : 1; /* TOC track numbers are in BCD. */
- __u8 subchan_as_bcd : 1; /* Subchannel info is in BCD. */
- __u8 is_changer : 1; /* Drive is a changer. */
- __u8 cd_r : 1; /* Drive can write to CD-R media . */
- __u8 cd_rw : 1; /* Drive can write to CD-R/W media . */
- __u8 dvd : 1; /* Drive is a DVD-ROM */
- __u8 dvd_r : 1; /* Drive can write DVD-R */
- __u8 dvd_ram : 1; /* Drive can write DVD-RAM */
- __u8 test_write : 1; /* Drive can fake writes */
- __u8 supp_disc_present : 1; /* Changer can report exact contents
- of slots. */
- __u8 limit_nframes : 1; /* Drive does not provide data in
- multiples of SECTOR_SIZE when more
- than one interrupt is needed. */
- __u8 seeking : 1; /* Seeking in progress */
- __u8 audio_play : 1; /* can do audio related commands */
- __u8 close_tray : 1; /* can close the tray */
- __u8 writing : 1; /* pseudo write in progress */
- __u8 reserved : 3;
- byte max_speed; /* Max speed of the drive */
-};
-#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
-
-
-/* State flags. These give information about the current state of the
- drive, and will change during normal operation. */
-struct ide_cd_state_flags {
- __u8 media_changed : 1; /* Driver has noticed a media change. */
- __u8 toc_valid : 1; /* Saved TOC information is current. */
- __u8 door_locked : 1; /* We think that the drive door is locked. */
- __u8 writing : 1; /* the drive is currently writing */
- __u8 reserved : 4;
- byte current_speed; /* Current speed of the drive */
-};
-
-#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
-
-struct packet_command {
- char *buffer;
- int buflen;
- int stat;
- int quiet;
- int timeout;
- struct request_sense *sense;
- unsigned char c[12];
-};
-
-/* Structure of a MSF cdrom address. */
-struct atapi_msf {
- byte reserved;
- byte minute;
- byte second;
- byte frame;
-};
-
-/* Space to hold the disk TOC. */
-#define MAX_TRACKS 99
-struct atapi_toc_header {
- unsigned short toc_length;
- byte first_track;
- byte last_track;
-};
-
-struct atapi_toc_entry {
- byte reserved1;
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 adr : 4;
- __u8 control : 4;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 control : 4;
- __u8 adr : 4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
- byte track;
- byte reserved2;
- union {
- unsigned lba;
- struct atapi_msf msf;
- } addr;
-};
-
-struct atapi_toc {
- int last_session_lba;
- int xa_flag;
- unsigned long capacity;
- struct atapi_toc_header hdr;
- struct atapi_toc_entry ent[MAX_TRACKS+1];
- /* One extra for the leadout. */
-};
-
-
-/* This structure is annoyingly close to, but not identical with,
- the cdrom_subchnl structure from cdrom.h. */
-struct atapi_cdrom_subchnl {
- u_char acdsc_reserved;
- u_char acdsc_audiostatus;
- u_short acdsc_length;
- u_char acdsc_format;
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- u_char acdsc_ctrl: 4;
- u_char acdsc_adr: 4;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- u_char acdsc_adr: 4;
- u_char acdsc_ctrl: 4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
- u_char acdsc_trk;
- u_char acdsc_ind;
- union {
- struct atapi_msf msf;
- int lba;
- } acdsc_absaddr;
- union {
- struct atapi_msf msf;
- int lba;
- } acdsc_reladdr;
-};
-
-
-
-/* This should probably go into cdrom.h along with the other
- * generic stuff now in the Mt. Fuji spec.
- */
-struct atapi_capabilities_page {
- struct mode_page_header header;
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 parameters_saveable : 1;
- __u8 reserved1 : 1;
- __u8 page_code : 6;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 page_code : 6;
- __u8 reserved1 : 1;
- __u8 parameters_saveable : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
- byte page_length;
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved2 : 2;
- /* Drive supports reading of DVD-RAM discs */
- __u8 dvd_ram_read : 1;
- /* Drive supports reading of DVD-R discs */
- __u8 dvd_r_read : 1;
- /* Drive supports reading of DVD-ROM discs */
- __u8 dvd_rom : 1;
- /* Drive supports reading CD-R discs with addressing method 2 */
- __u8 method2 : 1; /* reserved in 1.2 */
- /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_read : 1; /* reserved in 1.2 */
- /* Drive supports read from CD-R discs (orange book, part II) */
- __u8 cd_r_read : 1; /* reserved in 1.2 */
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- /* Drive supports read from CD-R discs (orange book, part II) */
- __u8 cd_r_read : 1; /* reserved in 1.2 */
- /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_read : 1; /* reserved in 1.2 */
- /* Drive supports reading CD-R discs with addressing method 2 */
- __u8 method2 : 1;
- /* Drive supports reading of DVD-ROM discs */
- __u8 dvd_rom : 1;
- /* Drive supports reading of DVD-R discs */
- __u8 dvd_r_read : 1;
- /* Drive supports reading of DVD-RAM discs */
- __u8 dvd_ram_read : 1;
- __u8 reserved2 : 2;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved3 : 2;
- /* Drive can write DVD-RAM discs */
- __u8 dvd_ram_write : 1;
- /* Drive can write DVD-R discs */
- __u8 dvd_r_write : 1;
- __u8 reserved3a : 1;
- /* Drive can fake writes */
- __u8 test_write : 1;
- /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_write : 1; /* reserved in 1.2 */
- /* Drive supports write to CD-R discs (orange book, part II) */
- __u8 cd_r_write : 1; /* reserved in 1.2 */
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- /* Drive can write to CD-R discs (orange book, part II) */
- __u8 cd_r_write : 1; /* reserved in 1.2 */
- /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_write : 1; /* reserved in 1.2 */
- /* Drive can fake writes */
- __u8 test_write : 1;
- __u8 reserved3a : 1;
- /* Drive can write DVD-R discs */
- __u8 dvd_r_write : 1;
- /* Drive can write DVD-RAM discs */
- __u8 dvd_ram_write : 1;
- __u8 reserved3 : 2;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved4 : 1;
- /* Drive can read multisession discs. */
- __u8 multisession : 1;
- /* Drive can read mode 2, form 2 data. */
- __u8 mode2_form2 : 1;
- /* Drive can read mode 2, form 1 (XA) data. */
- __u8 mode2_form1 : 1;
- /* Drive supports digital output on port 2. */
- __u8 digport2 : 1;
- /* Drive supports digital output on port 1. */
- __u8 digport1 : 1;
- /* Drive can deliver a composite audio/video data stream. */
- __u8 composite : 1;
- /* Drive supports audio play operations. */
- __u8 audio_play : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- /* Drive supports audio play operations. */
- __u8 audio_play : 1;
- /* Drive can deliver a composite audio/video data stream. */
- __u8 composite : 1;
- /* Drive supports digital output on port 1. */
- __u8 digport1 : 1;
- /* Drive supports digital output on port 2. */
- __u8 digport2 : 1;
- /* Drive can read mode 2, form 1 (XA) data. */
- __u8 mode2_form1 : 1;
- /* Drive can read mode 2, form 2 data. */
- __u8 mode2_form2 : 1;
- /* Drive can read multisession discs. */
- __u8 multisession : 1;
- __u8 reserved4 : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved5 : 1;
- /* Drive can return Media Catalog Number (UPC) info. */
- __u8 upc : 1;
- /* Drive can return International Standard Recording Code info. */
- __u8 isrc : 1;
- /* Drive supports C2 error pointers. */
- __u8 c2_pointers : 1;
- /* R-W data will be returned deinterleaved and error corrected. */
- __u8 rw_corr : 1;
- /* Subchannel reads can return combined R-W information. */
- __u8 rw_supported : 1;
- /* Drive can continue a read cdda operation from a loss of streaming.*/
- __u8 cdda_accurate : 1;
- /* Drive can read Red Book audio data. */
- __u8 cdda : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- /* Drive can read Red Book audio data. */
- __u8 cdda : 1;
- /* Drive can continue a read cdda operation from a loss of streaming.*/
- __u8 cdda_accurate : 1;
- /* Subchannel reads can return combined R-W information. */
- __u8 rw_supported : 1;
- /* R-W data will be returned deinterleaved and error corrected. */
- __u8 rw_corr : 1;
- /* Drive supports C2 error pointers. */
- __u8 c2_pointers : 1;
- /* Drive can return International Standard Recording Code info. */
- __u8 isrc : 1;
- /* Drive can return Media Catalog Number (UPC) info. */
- __u8 upc : 1;
- __u8 reserved5 : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- /* Drive mechanism types. */
- mechtype_t mechtype : 3;
- __u8 reserved6 : 1;
- /* Drive can eject a disc or changer cartridge. */
- __u8 eject : 1;
- /* State of prevent/allow jumper. */
- __u8 prevent_jumper : 1;
- /* Present state of door lock. */
- __u8 lock_state : 1;
- /* Drive can lock the door. */
- __u8 lock : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-
- /* Drive can lock the door. */
- __u8 lock : 1;
- /* Present state of door lock. */
- __u8 lock_state : 1;
- /* State of prevent/allow jumper. */
- __u8 prevent_jumper : 1;
- /* Drive can eject a disc or changer cartridge. */
- __u8 eject : 1;
- __u8 reserved6 : 1;
- /* Drive mechanism types. */
- mechtype_t mechtype : 3;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved7 : 4;
- /* Drive supports software slot selection. */
- __u8 sss : 1; /* reserved in 1.2 */
- /* Changer can report exact contents of slots. */
- __u8 disc_present : 1; /* reserved in 1.2 */
- /* Audio for each channel can be muted independently. */
- __u8 separate_mute : 1;
- /* Audio level for each channel can be controlled independently. */
- __u8 separate_volume : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
-
- /* Audio level for each channel can be controlled independently. */
- __u8 separate_volume : 1;
- /* Audio for each channel can be muted independently. */
- __u8 separate_mute : 1;
- /* Changer can report exact contents of slots. */
- __u8 disc_present : 1; /* reserved in 1.2 */
- /* Drive supports software slot selection. */
- __u8 sss : 1; /* reserved in 1.2 */
- __u8 reserved7 : 4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
- /* Note: the following four fields are returned in big-endian form. */
- /* Maximum speed (in kB/s). */
- unsigned short maxspeed;
- /* Number of discrete volume levels. */
- unsigned short n_vol_levels;
- /* Size of cache in drive, in kB. */
- unsigned short buffer_size;
- /* Current speed (in kB/s). */
- unsigned short curspeed;
- char pad[4];
-};
-
-
-struct atapi_mechstat_header {
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 fault : 1;
- __u8 changer_state : 2;
- __u8 curslot : 5;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 curslot : 5;
- __u8 changer_state : 2;
- __u8 fault : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 mech_state : 3;
- __u8 door_open : 1;
- __u8 reserved1 : 4;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 reserved1 : 4;
- __u8 door_open : 1;
- __u8 mech_state : 3;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
- byte curlba[3];
- byte nslots;
- __u16 slot_tablelen;
-};
-
-
-struct atapi_slot {
-#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 disc_present : 1;
- __u8 reserved1 : 6;
- __u8 change : 1;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 change : 1;
- __u8 reserved1 : 6;
- __u8 disc_present : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-
- byte reserved2[3];
-};
-
-struct atapi_changer_info {
- struct atapi_mechstat_header hdr;
- struct atapi_slot slots[0];
-};
-
-/* Extra per-device info for cdrom drives. */
-struct cdrom_info {
-
- /* Buffer for table of contents. NULL if we haven't allocated
- a TOC buffer for this device yet. */
-
- struct atapi_toc *toc;
-
- unsigned long sector_buffered;
- unsigned long nsectors_buffered;
- unsigned char *buffer;
-
- /* The result of the last successful request sense command
- on this device. */
- struct request_sense sense_data;
-
- struct request request_sense_request;
- struct packet_command request_sense_pc;
- int dma;
- int cmd;
- unsigned long last_block;
- unsigned long start_seek;
- /* Buffer to hold mechanism status and changer slot table. */
- struct atapi_changer_info *changer_info;
-
- struct ide_cd_config_flags config_flags;
- struct ide_cd_state_flags state_flags;
-
- /* Per-device info needed by cdrom.c generic driver. */
- struct cdrom_device_info devinfo;
-};
-
-/****************************************************************************
- * Descriptions of ATAPI error codes.
- */
-
-#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0])))
-
-/* This stuff should be in cdrom.h, since it is now generic... */
-
-/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
-#define NO_SENSE 0x00
-#define RECOVERED_ERROR 0x01
-#define NOT_READY 0x02
-#define MEDIUM_ERROR 0x03
-#define HARDWARE_ERROR 0x04
-#define ILLEGAL_REQUEST 0x05
-#define UNIT_ATTENTION 0x06
-#define DATA_PROTECT 0x07
-#define ABORTED_COMMAND 0x0b
-#define MISCOMPARE 0x0e
-
-
-
-/* This stuff should be in cdrom.h, since it is now generic... */
-#if VERBOSE_IDE_CD_ERRORS
-
- /* The generic packet command opcodes for CD/DVD Logical Units,
- * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-const struct {
- unsigned short packet_command;
- const char * const text;
-} packet_command_texts[] = {
- { GPCMD_TEST_UNIT_READY, "Test Unit Ready" },
- { GPCMD_REQUEST_SENSE, "Request Sense" },
- { GPCMD_FORMAT_UNIT, "Format Unit" },
- { GPCMD_INQUIRY, "Inquiry" },
- { GPCMD_START_STOP_UNIT, "Start/Stop Unit" },
- { GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
- { GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" },
- { GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" },
- { GPCMD_READ_10, "Read 10" },
- { GPCMD_WRITE_10, "Write 10" },
- { GPCMD_SEEK, "Seek" },
- { GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" },
- { GPCMD_VERIFY_10, "Verify 10" },
- { GPCMD_FLUSH_CACHE, "Flush Cache" },
- { GPCMD_READ_SUBCHANNEL, "Read Subchannel" },
- { GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" },
- { GPCMD_READ_HEADER, "Read Header" },
- { GPCMD_PLAY_AUDIO_10, "Play Audio 10" },
- { GPCMD_GET_CONFIGURATION, "Get Configuration" },
- { GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" },
- { GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" },
- { GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" },
- { GPCMD_PAUSE_RESUME, "Pause/Resume" },
- { GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" },
- { GPCMD_READ_DISC_INFO, "Read Disc Info" },
- { GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" },
- { GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" },
- { GPCMD_SEND_OPC, "Send OPC" },
- { GPCMD_MODE_SELECT_10, "Mode Select 10" },
- { GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" },
- { GPCMD_MODE_SENSE_10, "Mode Sense 10" },
- { GPCMD_CLOSE_TRACK, "Close Track" },
- { GPCMD_BLANK, "Blank" },
- { GPCMD_SEND_EVENT, "Send Event" },
- { GPCMD_SEND_KEY, "Send Key" },
- { GPCMD_REPORT_KEY, "Report Key" },
- { GPCMD_LOAD_UNLOAD, "Load/Unload" },
- { GPCMD_SET_READ_AHEAD, "Set Read-ahead" },
- { GPCMD_READ_12, "Read 12" },
- { GPCMD_GET_PERFORMANCE, "Get Performance" },
- { GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" },
- { GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" },
- { GPCMD_SET_STREAMING, "Set Streaming" },
- { GPCMD_READ_CD_MSF, "Read CD MSF" },
- { GPCMD_SCAN, "Scan" },
- { GPCMD_SET_SPEED, "Set Speed" },
- { GPCMD_PLAY_CD, "Play CD" },
- { GPCMD_MECHANISM_STATUS, "Mechanism Status" },
- { GPCMD_READ_CD, "Read CD" },
-};
-
-
-
-/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-const char * const sense_key_texts[16] = {
- "No sense data",
- "Recovered error",
- "Not ready",
- "Medium error",
- "Hardware error",
- "Illegal request",
- "Unit attention",
- "Data protect",
- "(reserved)",
- "(reserved)",
- "(reserved)",
- "Aborted command",
- "(reserved)",
- "(reserved)",
- "Miscompare",
- "(reserved)",
-};
-
-/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-const struct {
- unsigned long asc_ascq;
- const char * const text;
-} sense_data_texts[] = {
- { 0x000000, "No additional sense information" },
- { 0x000011, "Play operation in progress" },
- { 0x000012, "Play operation paused" },
- { 0x000013, "Play operation successfully completed" },
- { 0x000014, "Play operation stopped due to error" },
- { 0x000015, "No current audio status to return" },
- { 0x010c0a, "Write error - padding blocks added" },
- { 0x011700, "Recovered data with no error correction applied" },
- { 0x011701, "Recovered data with retries" },
- { 0x011702, "Recovered data with positive head offset" },
- { 0x011703, "Recovered data with negative head offset" },
- { 0x011704, "Recovered data with retries and/or CIRC applied" },
- { 0x011705, "Recovered data using previous sector ID" },
- { 0x011800, "Recovered data with error correction applied" },
- { 0x011801, "Recovered data with error correction and retries applied"},
- { 0x011802, "Recovered data - the data was auto-reallocated" },
- { 0x011803, "Recovered data with CIRC" },
- { 0x011804, "Recovered data with L-EC" },
- { 0x015d00,
- "Failure prediction threshold exceeded - Predicted logical unit failure" },
- { 0x015d01,
- "Failure prediction threshold exceeded - Predicted media failure" },
- { 0x015dff, "Failure prediction threshold exceeded - False" },
- { 0x017301, "Power calibration area almost full" },
- { 0x020400, "Logical unit not ready - cause not reportable" },
- /* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
- { 0x020401,
- "Logical unit not ready - in progress [sic] of becoming ready" },
- { 0x020402, "Logical unit not ready - initializing command required" },
- { 0x020403, "Logical unit not ready - manual intervention required" },
- { 0x020404, "Logical unit not ready - format in progress" },
- { 0x020407, "Logical unit not ready - operation in progress" },
- { 0x020408, "Logical unit not ready - long write in progress" },
- { 0x020600, "No reference position found (media may be upside down)" },
- { 0x023000, "Incompatible medium installed" },
- { 0x023a00, "Medium not present" },
- { 0x025300, "Media load or eject failed" },
- { 0x025700, "Unable to recover table of contents" },
- { 0x030300, "Peripheral device write fault" },
- { 0x030301, "No write current" },
- { 0x030302, "Excessive write errors" },
- { 0x030c00, "Write error" },
- { 0x030c01, "Write error - Recovered with auto reallocation" },
- { 0x030c02, "Write error - auto reallocation failed" },
- { 0x030c03, "Write error - recommend reassignment" },
- { 0x030c04, "Compression check miscompare error" },
- { 0x030c05, "Data expansion occurred during compress" },
- { 0x030c06, "Block not compressible" },
- { 0x030c07, "Write error - recovery needed" },
- { 0x030c08, "Write error - recovery failed" },
- { 0x030c09, "Write error - loss of streaming" },
- { 0x031100, "Unrecovered read error" },
- { 0x031106, "CIRC unrecovered error" },
- { 0x033101, "Format command failed" },
- { 0x033200, "No defect spare location available" },
- { 0x033201, "Defect list update failure" },
- { 0x035100, "Erase failure" },
- { 0x037200, "Session fixation error" },
- { 0x037201, "Session fixation error writin lead-in" },
- { 0x037202, "Session fixation error writin lead-out" },
- { 0x037300, "CD control error" },
- { 0x037302, "Power calibration area is full" },
- { 0x037303, "Power calibration area error" },
- { 0x037304, "Program memory area / RMA update failure" },
- { 0x037305, "Program memory area / RMA is full" },
- { 0x037306, "Program memory area / RMA is (almost) full" },
-
- { 0x040200, "No seek complete" },
- { 0x040300, "Write fault" },
- { 0x040900, "Track following error" },
- { 0x040901, "Tracking servo failure" },
- { 0x040902, "Focus servo failure" },
- { 0x040903, "Spindle servo failure" },
- { 0x041500, "Random positioning error" },
- { 0x041501, "Mechanical positioning or changer error" },
- { 0x041502, "Positioning error detected by read of medium" },
- { 0x043c00, "Mechanical positioning or changer error" },
- { 0x044000, "Diagnostic failure on component (ASCQ)" },
- { 0x044400, "Internal CD/DVD logical unit failure" },
- { 0x04b600, "Media load mechanism failed" },
- { 0x051a00, "Parameter list length error" },
- { 0x052000, "Invalid command operation code" },
- { 0x052100, "Logical block address out of range" },
- { 0x052102, "Invalid address for write" },
- { 0x052400, "Invalid field in command packet" },
- { 0x052600, "Invalid field in parameter list" },
- { 0x052601, "Parameter not supported" },
- { 0x052602, "Parameter value invalid" },
- { 0x052700, "Write protected media" },
- { 0x052c00, "Command sequence error" },
- { 0x052c03, "Current program area is not empty" },
- { 0x052c04, "Current program area is empty" },
- { 0x053001, "Cannot read medium - unknown format" },
- { 0x053002, "Cannot read medium - incompatible format" },
- { 0x053900, "Saving parameters not supported" },
- { 0x054e00, "Overlapped commands attempted" },
- { 0x055302, "Medium removal prevented" },
- { 0x055500, "System resource failure" },
- { 0x056300, "End of user area encountered on this track" },
- { 0x056400, "Illegal mode for this track or incompatible medium" },
- { 0x056f00, "Copy protection key exchange failure - Authentication failure" },
- { 0x056f01, "Copy protection key exchange failure - Key not present" },
- { 0x056f02, "Copy protection key exchange failure - Key not established" },
- { 0x056f03, "Read of scrambled sector without authentication" },
- { 0x056f04, "Media region code is mismatched to logical unit" },
- { 0x056f05, "Drive region must be permanent / region reset count error" },
- { 0x057203, "Session fixation error - incomplete track in session" },
- { 0x057204, "Empty or partially written reserved track" },
- { 0x057205, "No more RZONE reservations are allowed" },
- { 0x05bf00, "Loss of streaming" },
- { 0x062800, "Not ready to ready transition, medium may have changed" },
- { 0x062900, "Power on, reset or hardware reset occurred" },
- { 0x062a00, "Parameters changed" },
- { 0x062a01, "Mode parameters changed" },
- { 0x062e00, "Insufficient time for operation" },
- { 0x063f00, "Logical unit operating conditions have changed" },
- { 0x063f01, "Microcode has been changed" },
- { 0x065a00, "Operator request or state change input (unspecified)" },
- { 0x065a01, "Operator medium removal request" },
- { 0x0bb900, "Play operation aborted" },
-
- /* Here we use 0xff for the key (not a valid key) to signify
- * that these can have _any_ key value associated with them... */
- { 0xff0401, "Logical unit is in process of becoming ready" },
- { 0xff0400, "Logical unit not ready, cause not reportable" },
- { 0xff0402, "Logical unit not ready, initializing command required" },
- { 0xff0403, "Logical unit not ready, manual intervention required" },
- { 0xff0500, "Logical unit does not respond to selection" },
- { 0xff0800, "Logical unit communication failure" },
- { 0xff0802, "Logical unit communication parity error" },
- { 0xff0801, "Logical unit communication time-out" },
- { 0xff2500, "Logical unit not supported" },
- { 0xff4c00, "Logical unit failed self-configuration" },
- { 0xff3e00, "Logical unit has not self-configured yet" },
-};
-#endif
-
-
-#endif /* _IDE_CD_H */
diff --git a/xen/drivers/ide/ide-disk.c b/xen/drivers/ide/ide-disk.c
deleted file mode 100644
index 42fe5313f3..0000000000
--- a/xen/drivers/ide/ide-disk.c
+++ /dev/null
@@ -1,1553 +0,0 @@
-/*
- * linux/drivers/ide/ide-disk.c Version 1.10 June 9, 2000
- *
- * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
- */
-
-/*
- * Mostly written by Mark Lord <mlord@pobox.com>
- * and Gadi Oxman <gadio@netvision.net.il>
- * and Andre Hedrick <andre@linux-ide.org>
- *
- * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
- *
- * Version 1.00 move disk only code from ide.c to ide-disk.c
- * support optional byte-swapping of all data
- * Version 1.01 fix previous byte-swapping code
- * Version 1.02 remove ", LBA" from drive identification msgs
- * Version 1.03 fix display of id->buf_size for big-endian
- * Version 1.04 add /proc configurable settings and S.M.A.R.T support
- * Version 1.05 add capacity support for ATA3 >= 8GB
- * Version 1.06 get boot-up messages to show full cyl count
- * Version 1.07 disable door-locking if it fails
- * Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB,
- * process of adding new ATA4 compliance.
- * fixed problems in allowing fdisk to see
- * the entire disk.
- * Version 1.09 added increment of rq->sector in ide_multwrite
- * added UDMA 3/4 reporting
- * Version 1.10 request queue changes, Ultra DMA 100
- * Version 1.11 added 48-bit lba
- * Version 1.12 adding taskfile io access method
- */
-
-#define IDEDISK_VERSION "1.12"
-
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
-#include <xen/config.h>
-#include <xen/module.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/timer.h>
-#include <xen/mm.h>
-#include <xen/interrupt.h>
-#include <xen/major.h>
-#include <xen/errno.h>
-#include <xen/genhd.h>
-#include <xen/slab.h>
-#include <xen/delay.h>
-#include <xen/ide.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_BLK_DEV_PDC4030
-#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
-#else
-#define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */
-#endif
-
-#ifdef CONFIG_IDE_TASKFILE_IO
-# undef __TASKFILE__IO /* define __TASKFILE__IO */
-#else /* CONFIG_IDE_TASKFILE_IO */
-# undef __TASKFILE__IO
-#endif /* CONFIG_IDE_TASKFILE_IO */
-
-#ifndef __TASKFILE__IO
-
-static void idedisk_bswap_data (void *buffer, int wcount)
-{
- u16 *p = buffer;
-
- while (wcount--) {
- *p = *p << 8 | *p >> 8; p++;
- *p = *p << 8 | *p >> 8; p++;
- }
-}
-
-static inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
-{
- ide_input_data(drive, buffer, wcount);
- if (drive->bswap)
- idedisk_bswap_data(buffer, wcount);
-}
-
-static inline void idedisk_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
-{
- if (drive->bswap) {
- idedisk_bswap_data(buffer, wcount);
- ide_output_data(drive, buffer, wcount);
- idedisk_bswap_data(buffer, wcount);
- } else
- ide_output_data(drive, buffer, wcount);
-}
-
-#endif /* __TASKFILE__IO */
-
-/*
- * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
- * value for this drive (from its reported identification information).
- *
- * Returns: 1 if lba_capacity looks sensible
- * 0 otherwise
- *
- * It is called only once for each drive.
- */
-static int lba_capacity_is_ok (struct hd_driveid *id)
-{
- unsigned long lba_sects, chs_sects, head, tail;
-
- if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) {
- printk("48-bit Drive: %llu \n", id->lba_capacity_2);
- return 1;
- }
-
- /*
- * The ATA spec tells large drives to return
- * C/H/S = 16383/16/63 independent of their size.
- * Some drives can be jumpered to use 15 heads instead of 16.
- * Some drives can be jumpered to use 4092 cyls instead of 16383.
- */
- if ((id->cyls == 16383
- || (id->cyls == 4092 && id->cur_cyls == 16383)) &&
- id->sectors == 63 &&
- (id->heads == 15 || id->heads == 16) &&
- id->lba_capacity >= 16383*63*id->heads)
- return 1;
-
- lba_sects = id->lba_capacity;
- chs_sects = id->cyls * id->heads * id->sectors;
-
- /* perform a rough sanity check on lba_sects: within 10% is OK */
- if ((lba_sects - chs_sects) < chs_sects/10)
- return 1;
-
- /* some drives have the word order reversed */
- head = ((lba_sects >> 16) & 0xffff);
- tail = (lba_sects & 0xffff);
- lba_sects = (head | (tail << 16));
- if ((lba_sects - chs_sects) < chs_sects/10) {
- id->lba_capacity = lba_sects;
- return 1; /* lba_capacity is (now) good */
- }
-
- return 0; /* lba_capacity value may be bad */
-}
-
-#ifndef __TASKFILE__IO
-
-/*
- * read_intr() is the handler for disk read/multread interrupts
- */
-static ide_startstop_t read_intr (ide_drive_t *drive)
-{
- byte stat;
- int i;
- unsigned int msect, nsect;
- struct request *rq;
-
- /* new way for dealing with premature shared PCI interrupts */
- if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
- if (stat & (ERR_STAT|DRQ_STAT)) {
- return ide_error(drive, "read_intr", stat);
- }
- /* no data yet, so wait for another interrupt */
- ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- msect = drive->mult_count;
-
-read_next:
- rq = HWGROUP(drive)->rq;
- if (msect) {
- if ((nsect = rq->current_nr_sectors) > msect)
- nsect = msect;
- msect -= nsect;
- } else
- nsect = 1;
- idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
-#ifdef DEBUG
- printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n",
- drive->name, rq->sector, rq->sector+nsect-1,
- (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect);
-#endif
- rq->sector += nsect;
- rq->buffer += nsect<<9;
- rq->errors = 0;
- i = (rq->nr_sectors -= nsect);
- if (((long)(rq->current_nr_sectors -= nsect)) <= 0)
- ide_end_request(1, HWGROUP(drive));
- if (i > 0) {
- if (msect)
- goto read_next;
- ide_set_handler (drive, &read_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- return ide_stopped;
-}
-
-/*
- * write_intr() is the handler for disk write interrupts
- */
-static ide_startstop_t write_intr (ide_drive_t *drive)
-{
- byte stat;
- int i;
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- struct request *rq = hwgroup->rq;
-
- if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
- printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat);
- } else {
-#ifdef DEBUG
- printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n",
- drive->name, rq->sector, (unsigned long) rq->buffer,
- rq->nr_sectors-1);
-#endif
- if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) {
- rq->sector++;
- rq->buffer += 512;
- rq->errors = 0;
- i = --rq->nr_sectors;
- --rq->current_nr_sectors;
- if (((long)rq->current_nr_sectors) <= 0)
- ide_end_request(1, hwgroup);
- if (i > 0) {
- idedisk_output_data (drive, rq->buffer, SECTOR_WORDS);
- ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- return ide_stopped;
- }
- return ide_stopped; /* the original code did this here (?) */
- }
- return ide_error(drive, "write_intr", stat);
-}
-
-/*
- * ide_multwrite() transfers a block of up to mcount sectors of data
- * to a drive as part of a disk multiple-sector write operation.
- *
- * Returns 0 on success.
- *
- * Note that we may be called from two contexts - the do_rw_disk context
- * and IRQ context. The IRQ can happen any time after we've output the
- * full "mcount" number of sectors, so we must make sure we update the
- * state _before_ we output the final part of the data!
- */
-int ide_multwrite (ide_drive_t *drive, unsigned int mcount)
-{
- ide_hwgroup_t *hwgroup= HWGROUP(drive);
- struct request *rq = &hwgroup->wrq;
-
- do {
- char *buffer;
- int nsect = rq->current_nr_sectors;
-
- if (nsect > mcount)
- nsect = mcount;
- mcount -= nsect;
- buffer = rq->buffer;
-
- rq->sector += nsect;
- rq->buffer += nsect << 9;
- rq->nr_sectors -= nsect;
- rq->current_nr_sectors -= nsect;
-
- /* Do we move to the next bh after this? */
- if (!rq->current_nr_sectors) {
- struct buffer_head *bh = rq->bh->b_reqnext;
-
- /* end early early we ran out of requests */
- if (!bh) {
- mcount = 0;
- } else {
- rq->bh = bh;
- rq->current_nr_sectors = bh->b_size >> 9;
- rq->buffer = bh->b_data;
- }
- }
-
- /*
- * Ok, we're all setup for the interrupt
- * re-entering us on the last transfer.
- */
- idedisk_output_data(drive, buffer, nsect<<7);
- } while (mcount);
-
- return 0;
-}
-
-/*
- * multwrite_intr() is the handler for disk multwrite interrupts
- */
-static ide_startstop_t multwrite_intr (ide_drive_t *drive)
-{
- byte stat;
- int i;
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- struct request *rq = &hwgroup->wrq;
-
- if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
- if (stat & DRQ_STAT) {
- /*
- * The drive wants data. Remember rq is the copy
- * of the request
- */
- if (rq->nr_sectors) {
- if (ide_multwrite(drive, drive->mult_count))
- return ide_stopped;
- ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- } else {
- /*
- * If the copy has all the blocks completed then
- * we can end the original request.
- */
- if (!rq->nr_sectors) { /* all done? */
- rq = hwgroup->rq;
- for (i = rq->nr_sectors; i > 0;){
- i -= rq->current_nr_sectors;
- ide_end_request(1, hwgroup);
- }
- return ide_stopped;
- }
- }
- return ide_stopped; /* the original code did this here (?) */
- }
- return ide_error(drive, "multwrite_intr", stat);
-}
-#endif /* __TASKFILE__IO */
-
-#ifdef __TASKFILE__IO
-
-static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block);
-static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block);
-static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block);
-
-/*
- * do_rw_disk() issues READ and WRITE commands to a disk,
- * using LBA if supported, or CHS otherwise, to address sectors.
- * It also takes care of issuing special DRIVE_CMDs.
- */
-static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
-{
- if (rq->cmd == READ)
- goto good_command;
- if (rq->cmd == WRITE)
- goto good_command;
-
- printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);
- ide_end_request(0, HWGROUP(drive));
- return ide_stopped;
-
-good_command:
-
-#ifdef CONFIG_BLK_DEV_PDC4030
- if (IS_PDC4030_DRIVE) {
- extern ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long);
- return promise_rw_disk(drive, rq, block);
- }
-#endif /* CONFIG_BLK_DEV_PDC4030 */
-
- if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) /* 48-bit LBA */
- return lba_48_rw_disk(drive, rq, (unsigned long long) block);
- if (drive->select.b.lba) /* 28-bit LBA */
- return lba_28_rw_disk(drive, rq, (unsigned long) block);
-
- /* 28-bit CHS : DIE DIE DIE piece of legacy crap!!! */
- return chs_rw_disk(drive, rq, (unsigned long) block);
-}
-
-static task_ioreg_t get_command (ide_drive_t *drive, int cmd)
-{
- int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
-
-#if 1
- lba48bit = drive->addressing;
-#endif
-
- if ((cmd == READ) && (drive->using_dma))
- return (lba48bit) ? WIN_READDMA_EXT : WIN_READDMA;
- else if ((cmd == READ) && (drive->mult_count))
- return (lba48bit) ? WIN_MULTREAD_EXT : WIN_MULTREAD;
- else if (cmd == READ)
- return (lba48bit) ? WIN_READ_EXT : WIN_READ;
- else if ((cmd == WRITE) && (drive->using_dma))
- return (lba48bit) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
- else if ((cmd == WRITE) && (drive->mult_count))
- return (lba48bit) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
- else if (cmd == WRITE)
- return (lba48bit) ? WIN_WRITE_EXT : WIN_WRITE;
- else
- return WIN_NOP;
-}
-
-static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- ide_task_t args;
-
- task_ioreg_t command = get_command(drive, rq->cmd);
- unsigned int track = (block / drive->sect);
- unsigned int sect = (block % drive->sect) + 1;
- unsigned int head = (track % drive->head);
- unsigned int cyl = (track / drive->head);
-
- memset(&taskfile, 0, sizeof(task_struct_t));
- memset(&hobfile, 0, sizeof(hob_struct_t));
-
- taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors;
- taskfile.sector_number = sect;
- taskfile.low_cylinder = cyl;
- taskfile.high_cylinder = (cyl>>8);
- taskfile.device_head = head;
- taskfile.device_head |= drive->select.all;
- taskfile.command = command;
-
-#ifdef DEBUG
- printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");
- if (lba) printk("LBAsect=%lld, ", block);
- else printk("CHS=%d/%d/%d, ", cyl, head, sect);
- printk("sectors=%ld, ", rq->nr_sectors);
- printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
-#endif
-
- memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
- memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
- args.command_type = ide_cmd_type_parser(&args);
- args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile);
- args.handler = ide_handler_parser(&taskfile, &hobfile);
- args.posthandler = NULL;
- args.rq = (struct request *) rq;
- args.block = block;
- rq->special = NULL;
- rq->special = (ide_task_t *)&args;
-
- return do_rw_taskfile(drive, &args);
-}
-
-static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- ide_task_t args;
-
- task_ioreg_t command = get_command(drive, rq->cmd);
-
- memset(&taskfile, 0, sizeof(task_struct_t));
- memset(&hobfile, 0, sizeof(hob_struct_t));
-
- taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors;
- taskfile.sector_number = block;
- taskfile.low_cylinder = (block>>=8);
- taskfile.high_cylinder = (block>>=8);
- taskfile.device_head = ((block>>8)&0x0f);
- taskfile.device_head |= drive->select.all;
- taskfile.command = command;
-
-
-#ifdef DEBUG
- printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");
- if (lba) printk("LBAsect=%lld, ", block);
- else printk("CHS=%d/%d/%d, ", cyl, head, sect);
- printk("sectors=%ld, ", rq->nr_sectors);
- printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
-#endif
-
- memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
- memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
- args.command_type = ide_cmd_type_parser(&args);
- args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile);
- args.handler = ide_handler_parser(&taskfile, &hobfile);
- args.posthandler = NULL;
- args.rq = (struct request *) rq;
- args.block = block;
- rq->special = NULL;
- rq->special = (ide_task_t *)&args;
-
- return do_rw_taskfile(drive, &args);
-}
-
-/*
- * 268435455 == 137439 MB or 28bit limit
- * 320173056 == 163929 MB or 48bit addressing
- * 1073741822 == 549756 MB or 48bit addressing fake drive
- */
-
-static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- ide_task_t args;
-
- task_ioreg_t command = get_command(drive, rq->cmd);
-
- memset(&taskfile, 0, sizeof(task_struct_t));
- memset(&hobfile, 0, sizeof(hob_struct_t));
-
- taskfile.sector_count = rq->nr_sectors;
- hobfile.sector_count = (rq->nr_sectors>>8);
-
- if (rq->nr_sectors == 65536) {
- taskfile.sector_count = 0x00;
- hobfile.sector_count = 0x00;
- }
-
- taskfile.sector_number = block; /* low lba */
- taskfile.low_cylinder = (block>>=8); /* mid lba */
- taskfile.high_cylinder = (block>>=8); /* hi lba */
- hobfile.sector_number = (block>>=8); /* low lba */
- hobfile.low_cylinder = (block>>=8); /* mid lba */
- hobfile.high_cylinder = (block>>=8); /* hi lba */
- taskfile.device_head = drive->select.all;
- hobfile.device_head = taskfile.device_head;
- hobfile.control = (drive->ctl|0x80);
- taskfile.command = command;
-
-#ifdef DEBUG
- printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");
- if (lba) printk("LBAsect=%lld, ", block);
- else printk("CHS=%d/%d/%d, ", cyl, head, sect);
- printk("sectors=%ld, ", rq->nr_sectors);
- printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
-#endif
-
- memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
- memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
- args.command_type = ide_cmd_type_parser(&args);
- args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile);
- args.handler = ide_handler_parser(&taskfile, &hobfile);
- args.posthandler = NULL;
- args.rq = (struct request *) rq;
- args.block = block;
- rq->special = NULL;
- rq->special = (ide_task_t *)&args;
-
- return do_rw_taskfile(drive, &args);
-}
-
-#else /* !__TASKFILE__IO */
-/*
- * do_rw_disk() issues READ and WRITE commands to a disk,
- * using LBA if supported, or CHS otherwise, to address sectors.
- * It also takes care of issuing special DRIVE_CMDs.
- */
-static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
-{
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
-
-#ifdef CONFIG_BLK_DEV_PDC4030
- if (drive->select.b.lba || IS_PDC4030_DRIVE) {
-#else /* !CONFIG_BLK_DEV_PDC4030 */
- if (drive->select.b.lba) {
-#endif /* CONFIG_BLK_DEV_PDC4030 */
-
- if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {
- task_ioreg_t tasklets[10];
-
- tasklets[0] = 0;
- tasklets[1] = 0;
- tasklets[2] = rq->nr_sectors;
- tasklets[3] = (rq->nr_sectors>>8);
- if (rq->nr_sectors == 65536) {
- tasklets[2] = 0x00;
- tasklets[3] = 0x00;
- }
- tasklets[4] = (task_ioreg_t) block;
- tasklets[5] = (task_ioreg_t) (block>>8);
- tasklets[6] = (task_ioreg_t) (block>>16);
- tasklets[7] = (task_ioreg_t) (block>>24);
- tasklets[8] = (task_ioreg_t) 0;
- tasklets[9] = (task_ioreg_t) 0;
-// tasklets[8] = (task_ioreg_t) (block>>32);
-// tasklets[9] = (task_ioreg_t) (block>>40);
-#ifdef DEBUG
- printk("[A]\n");
- printk("%s: %sing: LBAsect=%lu, sectors=%ld, buffer=0x%08lx, LBAsect=0x%012lx\n",
- drive->name,
- (rq->cmd==READ)?"read":"writ",
- block,
- rq->nr_sectors,
- (unsigned long) rq->buffer,
- block);
- printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n",
- drive->name, tasklets[3], tasklets[2],
- tasklets[9], tasklets[8], tasklets[7],
- tasklets[6], tasklets[5], tasklets[4]);
-#endif
- OUT_BYTE(tasklets[1], IDE_FEATURE_REG);
- OUT_BYTE(tasklets[3], IDE_NSECTOR_REG);
- OUT_BYTE(tasklets[7], IDE_SECTOR_REG);
- OUT_BYTE(tasklets[8], IDE_LCYL_REG);
- OUT_BYTE(tasklets[9], IDE_HCYL_REG);
-
- OUT_BYTE(tasklets[0], IDE_FEATURE_REG);
- OUT_BYTE(tasklets[2], IDE_NSECTOR_REG);
- OUT_BYTE(tasklets[4], IDE_SECTOR_REG);
- OUT_BYTE(tasklets[5], IDE_LCYL_REG);
- OUT_BYTE(tasklets[6], IDE_HCYL_REG);
- OUT_BYTE(0x00|drive->select.all,IDE_SELECT_REG);
- } else {
-#ifdef DEBUG
- printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n",
- drive->name, (rq->cmd==READ)?"read":"writ",
- block, rq->nr_sectors, (unsigned long) rq->buffer);
-#endif
- OUT_BYTE(0x00, IDE_FEATURE_REG);
- OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG);
- OUT_BYTE(block,IDE_SECTOR_REG);
- OUT_BYTE(block>>=8,IDE_LCYL_REG);
- OUT_BYTE(block>>=8,IDE_HCYL_REG);
- OUT_BYTE(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
- }
- } else {
- unsigned int sect,head,cyl,track;
- track = block / drive->sect;
- sect = block % drive->sect + 1;
- OUT_BYTE(sect,IDE_SECTOR_REG);
- head = track % drive->head;
- cyl = track / drive->head;
-
- OUT_BYTE(0x00, IDE_FEATURE_REG);
- OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG);
- OUT_BYTE(cyl,IDE_LCYL_REG);
- OUT_BYTE(cyl>>8,IDE_HCYL_REG);
- OUT_BYTE(head|drive->select.all,IDE_SELECT_REG);
-#ifdef DEBUG
- printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n",
- drive->name, (rq->cmd==READ)?"read":"writ", cyl,
- head, sect, rq->nr_sectors, (unsigned long) rq->buffer);
-#endif
- }
-#ifdef CONFIG_BLK_DEV_PDC4030
- if (IS_PDC4030_DRIVE) {
- extern ide_startstop_t do_pdc4030_io(ide_drive_t *, struct request *);
- return do_pdc4030_io (drive, rq);
- }
-#endif /* CONFIG_BLK_DEV_PDC4030 */
- if (rq->cmd == READ) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive)))
- return ide_started;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
- ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
- if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {
- OUT_BYTE(drive->mult_count ? WIN_MULTREAD_EXT : WIN_READ_EXT, IDE_COMMAND_REG);
- } else {
- OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG);
- }
- return ide_started;
- }
- if (rq->cmd == WRITE) {
- ide_startstop_t startstop;
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))
- return ide_started;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
- if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {
- OUT_BYTE(drive->mult_count ? WIN_MULTWRITE_EXT : WIN_WRITE_EXT, IDE_COMMAND_REG);
- } else {
- OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG);
- }
- if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
- printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name,
- drive->mult_count ? "MULTWRITE" : "WRITE");
- return startstop;
- }
- if (!drive->unmask)
- __cli(); /* local CPU only */
- if (drive->mult_count) {
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- /*
- * Ugh.. this part looks ugly because we MUST set up
- * the interrupt handler before outputting the first block
- * of data to be written. If we hit an error (corrupted buffer list)
- * in ide_multwrite(), then we need to remove the handler/timer
- * before returning. Fortunately, this NEVER happens (right?).
- *
- * Except when you get an error it seems...
- */
- hwgroup->wrq = *rq; /* scratchpad */
- ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL);
- if (ide_multwrite(drive, drive->mult_count)) {
- unsigned long flags;
- spin_lock_irqsave(&io_request_lock, flags);
- hwgroup->handler = NULL;
- del_timer(&hwgroup->timer);
- spin_unlock_irqrestore(&io_request_lock, flags);
- return ide_stopped;
- }
- } else {
- ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);
- idedisk_output_data(drive, rq->buffer, SECTOR_WORDS);
- }
- return ide_started;
- }
- printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);
- ide_end_request(0, HWGROUP(drive));
- return ide_stopped;
-}
-
-#endif /* __TASKFILE__IO */
-
-static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- MOD_INC_USE_COUNT;
- if (drive->removable && drive->usage == 1) {
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.command = WIN_DOORLOCK;
- check_disk_change(inode->i_rdev);
- /*
- * Ignore the return code from door_lock,
- * since the open() has already succeeded,
- * and the door_lock is irrelevant at this point.
- */
- if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))
- drive->doorlocking = 0;
- }
- return 0;
-}
-
-static int do_idedisk_flushcache(ide_drive_t *drive);
-
-static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- if (drive->removable && !drive->usage) {
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.command = WIN_DOORUNLOCK;
- invalidate_bdev(inode->i_bdev, 0);
- if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))
- drive->doorlocking = 0;
- }
- if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
- if (do_idedisk_flushcache(drive))
- printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
- drive->name);
- MOD_DEC_USE_COUNT;
-}
-
-static int idedisk_media_change (ide_drive_t *drive)
-{
- return drive->removable; /* if removable, always assume it was changed */
-}
-
-static void idedisk_revalidate (ide_drive_t *drive)
-{
- grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
- 1<<PARTN_BITS,
- current_capacity(drive));
-}
-
-/*
- * Queries for true maximum capacity of the drive.
- * Returns maximum LBA address (> 0) of the drive, 0 if failed.
- */
-static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
-{
- ide_task_t args;
- unsigned long addr = 0;
-
- if (!(drive->id->command_set_1 & 0x0400) &&
- !(drive->id->cfs_enable_2 & 0x0100))
- return addr;
-
- /* Create IDE/ATA command request structure */
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX;
- args.handler = task_no_data_intr;
-
- /* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
-
- /* if OK, compute maximum address value */
- if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
- addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
- | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16)
- | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8)
- | ((args.tfRegister[IDE_SECTOR_OFFSET] ));
- }
- addr++; /* since the return value is (maxlba - 1), we add 1 */
- return addr;
-}
-
-static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
-{
- ide_task_t args;
- unsigned long long addr = 0;
-
- /* Create IDE/ATA command request structure */
- memset(&args, 0, sizeof(ide_task_t));
-
- args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT;
- args.handler = task_no_data_intr;
-
- /* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
-
- /* if OK, compute maximum address value */
- if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
- u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |
- ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |
- (args.hobRegister[IDE_SECTOR_OFFSET_HOB]);
- u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
- ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
- (args.tfRegister[IDE_SECTOR_OFFSET]);
- addr = ((__u64)high << 24) | low;
- }
- addr++; /* since the return value is (maxlba - 1), we add 1 */
- return addr;
-}
-
-#ifdef CONFIG_IDEDISK_STROKE
-/*
- * Sets maximum virtual LBA address of the drive.
- * Returns new maximum virtual LBA address (> 0) or 0 on failure.
- */
-static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
-{
- ide_task_t args;
- unsigned long addr_set = 0;
-
- addr_req--;
- /* Create IDE/ATA command request structure */
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff);
- args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >> 8) & 0xff);
- args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff);
- args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX;
- args.handler = task_no_data_intr;
- /* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
- /* if OK, read new maximum address value */
- if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
- addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
- | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16)
- | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8)
- | ((args.tfRegister[IDE_SECTOR_OFFSET] ));
- }
- addr_set++;
- return addr_set;
-}
-
-static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
-{
- ide_task_t args;
- unsigned long long addr_set = 0;
-
- addr_req--;
- /* Create IDE/ATA command request structure */
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff);
- args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >>= 8) & 0xff);
- args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >>= 8) & 0xff);
- args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX_EXT;
- args.hobRegister[IDE_SECTOR_OFFSET_HOB] = ((addr_req >>= 8) & 0xff);
- args.hobRegister[IDE_LCYL_OFFSET_HOB] = ((addr_req >>= 8) & 0xff);
- args.hobRegister[IDE_HCYL_OFFSET_HOB] = ((addr_req >>= 8) & 0xff);
- args.hobRegister[IDE_SELECT_OFFSET_HOB] = 0x40;
- args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
- args.handler = task_no_data_intr;
- /* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
- /* if OK, compute maximum address value */
- if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
- u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |
- ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |
- (args.hobRegister[IDE_SECTOR_OFFSET_HOB]);
- u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
- ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
- (args.tfRegister[IDE_SECTOR_OFFSET]);
- addr_set = ((__u64)high << 24) | low;
- }
- return addr_set;
-}
-
-/*
- * Tests if the drive supports Host Protected Area feature.
- * Returns true if supported, false otherwise.
- */
-static inline int idedisk_supports_host_protected_area(ide_drive_t *drive)
-{
- int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0;
- printk("%s: host protected area => %d\n", drive->name, flag);
- return flag;
-}
-
-#endif /* CONFIG_IDEDISK_STROKE */
-
-/*
- * Compute drive->capacity, the full capacity of the drive
- * Called with drive->id != NULL.
- *
- * To compute capacity, this uses either of
- *
- * 1. CHS value set by user (whatever user sets will be trusted)
- * 2. LBA value from target drive (require new ATA feature)
- * 3. LBA value from system BIOS (new one is OK, old one may break)
- * 4. CHS value from system BIOS (traditional style)
- *
- * in above order (i.e., if value of higher priority is available,
- * reset will be ignored).
- */
-static void init_idedisk_capacity (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
- unsigned long capacity = drive->cyl * drive->head * drive->sect;
- unsigned long set_max = idedisk_read_native_max_address(drive);
- unsigned long long capacity_2 = capacity;
- unsigned long long set_max_ext;
-
- drive->capacity48 = 0;
- drive->select.b.lba = 0;
-
- if (id->cfs_enable_2 & 0x0400) {
- capacity_2 = id->lba_capacity_2;
- drive->head = drive->bios_head = 255;
- drive->sect = drive->bios_sect = 63;
- drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect);
- drive->select.b.lba = 1;
- set_max_ext = idedisk_read_native_max_address_ext(drive);
- if (set_max_ext > capacity_2) {
-#ifdef CONFIG_IDEDISK_STROKE
- set_max_ext = idedisk_read_native_max_address_ext(drive);
- set_max_ext = idedisk_set_max_address_ext(drive, set_max_ext);
- if (set_max_ext) {
- drive->capacity48 = capacity_2 = set_max_ext;
- drive->cyl = (unsigned int) set_max_ext / (drive->head * drive->sect);
- drive->select.b.lba = 1;
- drive->id->lba_capacity_2 = capacity_2;
- }
-#else /* !CONFIG_IDEDISK_STROKE */
- printk("%s: setmax_ext LBA %llu, native %llu\n",
- drive->name, set_max_ext, capacity_2);
-#endif /* CONFIG_IDEDISK_STROKE */
- }
- drive->bios_cyl = drive->cyl;
- drive->capacity48 = capacity_2;
- drive->capacity = (unsigned long) capacity_2;
- return;
- /* Determine capacity, and use LBA if the drive properly supports it */
- } else if ((id->capability & 2) && lba_capacity_is_ok(id)) {
- capacity = id->lba_capacity;
- drive->cyl = capacity / (drive->head * drive->sect);
- drive->select.b.lba = 1;
- }
-
- if (set_max > capacity) {
-#ifdef CONFIG_IDEDISK_STROKE
- set_max = idedisk_read_native_max_address(drive);
- set_max = idedisk_set_max_address(drive, set_max);
- if (set_max) {
- drive->capacity = capacity = set_max;
- drive->cyl = set_max / (drive->head * drive->sect);
- drive->select.b.lba = 1;
- drive->id->lba_capacity = capacity;
- }
-#else /* !CONFIG_IDEDISK_STROKE */
- printk("%s: setmax LBA %lu, native %lu\n",
- drive->name, set_max, capacity);
-#endif /* CONFIG_IDEDISK_STROKE */
- }
-
- drive->capacity = capacity;
-
- if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) {
- drive->capacity48 = id->lba_capacity_2;
- drive->head = 255;
- drive->sect = 63;
- drive->cyl = (unsigned long)(drive->capacity48) / (drive->head * drive->sect);
- }
-}
-
-static unsigned long idedisk_capacity (ide_drive_t *drive)
-{
- if (drive->id->cfs_enable_2 & 0x0400)
- return (drive->capacity48 - drive->sect0);
- return (drive->capacity - drive->sect0);
-}
-
-static ide_startstop_t idedisk_special (ide_drive_t *drive)
-{
- special_t *s = &drive->special;
-
- if (s->b.set_geometry) {
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- ide_handler_t *handler = NULL;
-
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-
- s->b.set_geometry = 0;
- taskfile.sector_number = drive->sect;
- taskfile.low_cylinder = drive->cyl;
- taskfile.high_cylinder = drive->cyl>>8;
- taskfile.device_head = ((drive->head-1)|drive->select.all)&0xBF;
- if (!IS_PDC4030_DRIVE) {
- taskfile.sector_count = drive->sect;
- taskfile.command = WIN_SPECIFY;
- handler = ide_handler_parser(&taskfile, &hobfile);
- }
- do_taskfile(drive, &taskfile, &hobfile, handler);
- } else if (s->b.recalibrate) {
- s->b.recalibrate = 0;
- if (!IS_PDC4030_DRIVE) {
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.sector_count = drive->sect;
- taskfile.command = WIN_RESTORE;
- do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile));
- }
- } else if (s->b.set_multmode) {
- s->b.set_multmode = 0;
- if (drive->id && drive->mult_req > drive->id->max_multsect)
- drive->mult_req = drive->id->max_multsect;
- if (!IS_PDC4030_DRIVE) {
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.sector_count = drive->mult_req;
- taskfile.command = WIN_SETMULT;
- do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile));
- }
- } else if (s->all) {
- int special = s->all;
- s->all = 0;
- printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special);
- return ide_stopped;
- }
- return IS_PDC4030_DRIVE ? ide_stopped : ide_started;
-}
-
-static void idedisk_pre_reset (ide_drive_t *drive)
-{
- int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
-
- drive->special.all = 0;
- drive->special.b.set_geometry = legacy;
- drive->special.b.recalibrate = legacy;
- if (OK_TO_RESET_CONTROLLER)
- drive->mult_count = 0;
- if (!drive->keep_settings && !drive->using_dma)
- drive->mult_req = 0;
- if (drive->mult_req != drive->mult_count)
- drive->special.b.set_multmode = 1;
-}
-
-#ifdef CONFIG_PROC_FS
-
-static int smart_enable(ide_drive_t *drive)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.feature = SMART_ENABLE;
- taskfile.low_cylinder = SMART_LCYL_PASS;
- taskfile.high_cylinder = SMART_HCYL_PASS;
- taskfile.command = WIN_SMART;
- return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
-}
-
-static int get_smart_values(ide_drive_t *drive, byte *buf)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.feature = SMART_READ_VALUES;
- taskfile.sector_count = 0x01;
- taskfile.low_cylinder = SMART_LCYL_PASS;
- taskfile.high_cylinder = SMART_HCYL_PASS;
- taskfile.command = WIN_SMART;
- (void) smart_enable(drive);
- return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
-}
-
-static int get_smart_thresholds(ide_drive_t *drive, byte *buf)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.feature = SMART_READ_THRESHOLDS;
- taskfile.sector_count = 0x01;
- taskfile.low_cylinder = SMART_LCYL_PASS;
- taskfile.high_cylinder = SMART_HCYL_PASS;
- taskfile.command = WIN_SMART;
- (void) smart_enable(drive);
- return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
-}
-
-static int proc_idedisk_read_cache
- (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- ide_drive_t *drive = (ide_drive_t *) data;
- char *out = page;
- int len;
-
- if (drive->id)
- len = sprintf(out,"%i\n", drive->id->buf_size / 2);
- else
- len = sprintf(out,"(none)\n");
- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
-static int proc_idedisk_read_smart_thresholds
- (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- ide_drive_t *drive = (ide_drive_t *)data;
- int len = 0, i = 0;
-
- if (!get_smart_thresholds(drive, page)) {
- unsigned short *val = (unsigned short *) page;
- char *out = ((char *)val) + (SECTOR_WORDS * 4);
- page = out;
- do {
- out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
- val += 1;
- } while (i < (SECTOR_WORDS * 2));
- len = out - page;
- }
- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
-static int proc_idedisk_read_smart_values
- (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- ide_drive_t *drive = (ide_drive_t *)data;
- int len = 0, i = 0;
-
- if (!get_smart_values(drive, page)) {
- unsigned short *val = (unsigned short *) page;
- char *out = ((char *)val) + (SECTOR_WORDS * 4);
- page = out;
- do {
- out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
- val += 1;
- } while (i < (SECTOR_WORDS * 2));
- len = out - page;
- }
- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
-static ide_proc_entry_t idedisk_proc[] = {
- { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
- { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
- { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL },
- { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL },
- { NULL, 0, NULL, NULL }
-};
-
-#else
-
-#define idedisk_proc NULL
-
-#endif /* CONFIG_PROC_FS */
-
-static int set_multcount(ide_drive_t *drive, int arg)
-{
-#ifdef __TASKFILE__IO
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
-
- if (drive->special.b.set_multmode)
- return -EBUSY;
-
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.sector_count = drive->mult_req;
- taskfile.command = WIN_SETMULT;
- drive->mult_req = arg;
- drive->special.b.set_multmode = 1;
- ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
-#else /* !__TASKFILE__IO */
- struct request rq;
-
- if (drive->special.b.set_multmode)
- return -EBUSY;
- ide_init_drive_cmd (&rq);
- rq.cmd = IDE_DRIVE_CMD;
- drive->mult_req = arg;
- drive->special.b.set_multmode = 1;
- (void) ide_do_drive_cmd (drive, &rq, ide_wait);
-#endif /* __TASKFILE__IO */
- return (drive->mult_count == arg) ? 0 : -EIO;
-}
-
-static int set_nowerr(ide_drive_t *drive, int arg)
-{
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
- drive->nowerr = arg;
- drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
- spin_unlock_irq(&io_request_lock);
- return 0;
-}
-
-static int write_cache (ide_drive_t *drive, int arg)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
- taskfile.command = WIN_SETFEATURES;
-
- if (!(drive->id->cfs_enable_2 & 0x3000))
- return 1;
-
- (void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
- drive->wcache = arg;
- return 0;
-}
-
-static int do_idedisk_standby (ide_drive_t *drive)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- taskfile.command = WIN_STANDBYNOW1;
- return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
-}
-
-static int do_idedisk_flushcache (ide_drive_t *drive)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- if (drive->id->cfs_enable_2 & 0x2400) {
- taskfile.command = WIN_FLUSH_CACHE_EXT;
- } else {
- taskfile.command = WIN_FLUSH_CACHE;
- }
- return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
-}
-
-static int set_acoustic (ide_drive_t *drive, int arg)
-{
- struct hd_drive_task_hdr taskfile;
- struct hd_drive_hob_hdr hobfile;
- memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-
- taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM;
- taskfile.sector_count = arg;
-
- taskfile.command = WIN_SETFEATURES;
- (void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
- drive->acoustic = arg;
- return 0;
-}
-
-static int probe_lba_addressing (ide_drive_t *drive, int arg)
-{
- drive->addressing = 0;
-
- if (!(drive->id->cfs_enable_2 & 0x0400))
- return -EIO;
-
- drive->addressing = arg;
- return 0;
-}
-
-static int set_lba_addressing (ide_drive_t *drive, int arg)
-{
- return (probe_lba_addressing(drive, arg));
-}
-
-static void idedisk_add_settings(ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
-#if 0
- int major = HWIF(drive)->major;
- int minor = drive->select.b.unit << PARTN_BITS;
-#endif
-
- ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL);
- ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
- ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
- ide_add_setting(drive, "address", SETTING_RW, HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, TYPE_INTA, 0, 2, 1, 1, &drive->addressing, set_lba_addressing);
- ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL);
- ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 1, &drive->mult_count, set_multcount);
- ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr);
-#if 0
- ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 1, &read_ahead[major], NULL);
- ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, 4096, PAGE_SIZE, 1024, &max_readahead[major][minor], NULL);
- ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 1, &max_sectors[major][minor], NULL);
-#endif
- ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL);
- ide_add_setting(drive, "wcache", SETTING_RW, HDIO_GET_WCACHE, HDIO_SET_WCACHE, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache);
- ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic);
- ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL);
- ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL);
-}
-
-static void idedisk_setup (ide_drive_t *drive)
-{
- int i;
-
- struct hd_driveid *id = drive->id;
- unsigned long capacity;
-
- idedisk_add_settings(drive);
-
- if (id == NULL)
- return;
-
- /*
- * CompactFlash cards and their brethern look just like hard drives
- * to us, but they are removable and don't have a doorlock mechanism.
- */
- if (drive->removable && !drive_is_flashcard(drive)) {
- /*
- * Removable disks (eg. SYQUEST); ignore 'WD' drives
- */
- if (id->model[0] != 'W' || id->model[1] != 'D') {
- drive->doorlocking = 1;
- }
- }
- for (i = 0; i < MAX_DRIVES; ++i) {
- ide_hwif_t *hwif = HWIF(drive);
-
- if (drive != &hwif->drives[i]) continue;
-#ifdef DEVFS_MUST_DIE
- hwif->gd->de_arr[i] = drive->de;
-#endif
- if (drive->removable)
- hwif->gd->flags[i] |= GENHD_FL_REMOVABLE;
- break;
- }
-
- /* Extract geometry if we did not already have one for the drive */
- if (!drive->cyl || !drive->head || !drive->sect) {
- drive->cyl = drive->bios_cyl = id->cyls;
- drive->head = drive->bios_head = id->heads;
- drive->sect = drive->bios_sect = id->sectors;
- }
-
- /* Handle logical geometry translation by the drive */
- if ((id->field_valid & 1) && id->cur_cyls &&
- id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
- drive->cyl = id->cur_cyls;
- drive->head = id->cur_heads;
- drive->sect = id->cur_sectors;
- }
-
- /* Use physical geometry if what we have still makes no sense */
- if (drive->head > 16 && id->heads && id->heads <= 16) {
- drive->cyl = id->cyls;
- drive->head = id->heads;
- drive->sect = id->sectors;
- }
-
- /* calculate drive capacity, and select LBA if possible */
- init_idedisk_capacity (drive);
-
- /*
- * if possible, give fdisk access to more of the drive,
- * by correcting bios_cyls:
- */
- capacity = idedisk_capacity (drive);
- if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) &&
- (!drive->forced_geom) && drive->bios_sect && drive->bios_head)
- drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head;
- printk (KERN_INFO "%s: %ld sectors", drive->name, capacity);
-
- /* Give size in megabytes (MB), not mebibytes (MiB). */
- /* We compute the exact rounded value, avoiding overflow. */
- printk (" (%ld MB)", (capacity - capacity/625 + 974)/1950);
-
- /* Only print cache size when it was specified */
- if (id->buf_size)
- printk (" w/%dKiB Cache", id->buf_size/2);
-
- printk(", CHS=%d/%d/%d",
- drive->bios_cyl, drive->bios_head, drive->bios_sect);
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (drive->using_dma)
- (void) HWIF(drive)->dmaproc(ide_dma_verbose, drive);
- else
-#endif /* CONFIG_BLK_DEV_IDEDMA */
- printk(" PIO (slow!)");
- printk("\n");
-
- drive->mult_count = 0;
- if (id->max_multsect) {
-#ifdef CONFIG_IDEDISK_MULTI_MODE
- id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
- id->multsect_valid = id->multsect ? 1 : 0;
- drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
- drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
-#else /* original, pre IDE-NFG, per request of AC */
- drive->mult_req = INITIAL_MULT_COUNT;
- if (drive->mult_req > id->max_multsect)
- drive->mult_req = id->max_multsect;
- if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
- drive->special.b.set_multmode = 1;
-#endif /* CONFIG_IDEDISK_MULTI_MODE */
- }
- drive->no_io_32bit = id->dword_io ? 1 : 0;
- if (drive->id->cfs_enable_2 & 0x3000)
- write_cache(drive, (id->cfs_enable_2 & 0x3000));
- (void) probe_lba_addressing(drive, 1);
-}
-
-static int idedisk_cleanup (ide_drive_t *drive)
-{
- if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
- if (do_idedisk_flushcache(drive))
- printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
- drive->name);
- return ide_unregister_subdriver(drive);
-}
-
-int idedisk_reinit(ide_drive_t *drive);
-
-/*
- * IDE subdriver functions, registered with ide.c
- */
-static ide_driver_t idedisk_driver = {
- name: "ide-disk",
- version: IDEDISK_VERSION,
- media: ide_disk,
- busy: 0,
- supports_dma: 1,
- supports_dsc_overlap: 0,
- cleanup: idedisk_cleanup,
- standby: do_idedisk_standby,
- flushcache: do_idedisk_flushcache,
- do_request: do_rw_disk,
- end_request: NULL,
- ioctl: NULL,
- open: idedisk_open,
- release: idedisk_release,
- media_change: idedisk_media_change,
- revalidate: idedisk_revalidate,
- pre_reset: idedisk_pre_reset,
- capacity: idedisk_capacity,
- special: idedisk_special,
- /*proc: idedisk_proc,*/
- reinit: idedisk_reinit,
- ata_prebuilder: NULL,
- atapi_prebuilder: NULL,
-};
-
-int idedisk_init (void);
-static ide_module_t idedisk_module = {
- IDE_DRIVER_MODULE,
- idedisk_init,
- &idedisk_driver,
- NULL
-};
-
-MODULE_DESCRIPTION("ATA DISK Driver");
-
-int idedisk_reinit (ide_drive_t *drive)
-{
- int failed = 0;
-
- MOD_INC_USE_COUNT;
-
- if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) {
- printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
- return 1;
- }
- DRIVER(drive)->busy++;
- idedisk_setup(drive);
- if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
- printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head);
- (void) idedisk_cleanup(drive);
- DRIVER(drive)->busy--;
- return 1;
- }
- DRIVER(drive)->busy--;
- failed--;
-
- ide_register_module(&idedisk_module);
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static void __exit idedisk_exit (void)
-{
- ide_drive_t *drive;
- int failed = 0;
-
- while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) {
- if (idedisk_cleanup (drive)) {
- printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
- failed++;
- }
- /* We must remove proc entries defined in this module.
- Otherwise we oops while accessing these entries */
-#ifdef CONFIG_PROC_FS
- if (drive->proc)
- ide_remove_proc_entries(drive->proc, idedisk_proc);
-#endif
- }
- ide_unregister_module(&idedisk_module);
-}
-
-int idedisk_init (void)
-{
- ide_drive_t *drive;
- int failed = 0;
-
- MOD_INC_USE_COUNT;
- while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) {
- if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) {
- printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
- continue;
- }
- DRIVER(drive)->busy++;
- idedisk_setup(drive);
- if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
- printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head);
- (void) idedisk_cleanup(drive);
- DRIVER(drive)->busy--;
- continue;
- }
- DRIVER(drive)->busy--;
- failed--;
- }
- ide_register_module(&idedisk_module);
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-module_init(idedisk_init);
-module_exit(idedisk_exit);
-MODULE_LICENSE("GPL");
diff --git a/xen/drivers/ide/ide-dma.c b/xen/drivers/ide/ide-dma.c
deleted file mode 100644
index 80fe970284..0000000000
--- a/xen/drivers/ide/ide-dma.c
+++ /dev/null
@@ -1,897 +0,0 @@
-/*
- * linux/drivers/ide/ide-dma.c Version 4.10 June 9, 2000
- *
- * Copyright (c) 1999-2000 Andre Hedrick <andre@linux-ide.org>
- * May be copied or modified under the terms of the GNU General Public License
- */
-
-/*
- * Special Thanks to Mark for his Six years of work.
- *
- * Copyright (c) 1995-1998 Mark Lord
- * May be copied or modified under the terms of the GNU General Public License
- */
-
-/*
- * This module provides support for the bus-master IDE DMA functions
- * of various PCI chipsets, including the Intel PIIX (i82371FB for
- * the 430 FX chipset), the PIIX3 (i82371SB for the 430 HX/VX and
- * 440 chipsets), and the PIIX4 (i82371AB for the 430 TX chipset)
- * ("PIIX" stands for "PCI ISA IDE Xcellerator").
- *
- * Pretty much the same code works for other IDE PCI bus-mastering chipsets.
- *
- * DMA is supported for all IDE devices (disk drives, cdroms, tapes, floppies).
- *
- * By default, DMA support is prepared for use, but is currently enabled only
- * for drives which already have DMA enabled (UltraDMA or mode 2 multi/single),
- * or which are recognized as "good" (see table below). Drives with only mode0
- * or mode1 (multi/single) DMA should also work with this chipset/driver
- * (eg. MC2112A) but are not enabled by default.
- *
- * Use "hdparm -i" to view modes supported by a given drive.
- *
- * The hdparm-3.5 (or later) utility can be used for manually enabling/disabling
- * DMA support, but must be (re-)compiled against this kernel version or later.
- *
- * To enable DMA, use "hdparm -d1 /dev/hd?" on a per-drive basis after booting.
- * If problems arise, ide.c will disable DMA operation after a few retries.
- * This error recovery mechanism works and has been extremely well exercised.
- *
- * IDE drives, depending on their vintage, may support several different modes
- * of DMA operation. The boot-time modes are indicated with a "*" in
- * the "hdparm -i" listing, and can be changed with *knowledgeable* use of
- * the "hdparm -X" feature. There is seldom a need to do this, as drives
- * normally power-up with their "best" PIO/DMA modes enabled.
- *
- * Testing has been done with a rather extensive number of drives,
- * with Quantum & Western Digital models generally outperforming the pack,
- * and Fujitsu & Conner (and some Seagate which are really Conner) drives
- * showing more lackluster throughput.
- *
- * Keep an eye on /var/adm/messages for "DMA disabled" messages.
- *
- * Some people have reported trouble with Intel Zappa motherboards.
- * This can be fixed by upgrading the AMI BIOS to version 1.00.04.BS0,
- * available from ftp://ftp.intel.com/pub/bios/10004bs0.exe
- * (thanks to Glen Morrell <glen@spin.Stanford.edu> for researching this).
- *
- * Thanks to "Christopher J. Reimer" <reimer@doe.carleton.ca> for
- * fixing the problem with the BIOS on some Acer motherboards.
- *
- * Thanks to "Benoit Poulot-Cazajous" <poulot@chorus.fr> for testing
- * "TX" chipset compatibility and for providing patches for the "TX" chipset.
- *
- * Thanks to Christian Brunner <chb@muc.de> for taking a good first crack
- * at generic DMA -- his patches were referred to when preparing this code.
- *
- * Most importantly, thanks to Robert Bringman <rob@mars.trion.com>
- * for supplying a Promise UDMA board & WD UDMA drive for this work!
- *
- * And, yes, Intel Zappa boards really *do* use both PIIX IDE ports.
- *
- * check_drive_lists(ide_drive_t *drive, int good_bad)
- *
- * ATA-66/100 and recovery functions, I forgot the rest......
- * SELECT_READ_WRITE(hwif,drive,func) for active tuning based on IO direction.
- *
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/timer.h>
-#include <xen/mm.h>
-#include <xen/interrupt.h>
-#include <xen/pci.h>
-#include <xen/init.h>
-#include <xen/ide.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-/*
- * Long lost data from 2.0.34 that is now in 2.0.39
- *
- * This was used in ./drivers/block/triton.c to do DMA Base address setup
- * when PnP failed. Oh the things we forget. I believe this was part
- * of SFF-8038i that has been withdrawn from public access... :-((
- */
-#define DEFAULT_BMIBA 0xe800 /* in case BIOS did not init it */
-#define DEFAULT_BMCRBA 0xcc00 /* VIA's default value */
-#define DEFAULT_BMALIBA 0xd400 /* ALI's default value */
-
-extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
-
-#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
-
-struct drive_list_entry {
- char * id_model;
- char * id_firmware;
-};
-
-struct drive_list_entry drive_whitelist [] = {
-
- { "Micropolis 2112A" , "ALL" },
- { "CONNER CTMA 4000" , "ALL" },
- { "CONNER CTT8000-A" , "ALL" },
- { "ST34342A" , "ALL" },
- { 0 , 0 }
-};
-
-struct drive_list_entry drive_blacklist [] = {
-
- { "WDC AC11000H" , "ALL" },
- { "WDC AC22100H" , "ALL" },
- { "WDC AC31000H" , "ALL" },
- { "WDC AC32500H" , "ALL" },
- { "WDC AC33100H" , "ALL" },
- { "WDC AC31600H" , "ALL" },
- { "WDC AC32100H" , "24.09P07" },
- { "WDC AC23200L" , "21.10N21" },
- { "Compaq CRD-8241B" , "ALL" },
- { "CRD-8400B" , "ALL" },
- { "CRD-8480B", "ALL" },
- { "CRD-8480C", "ALL" },
- { "CRD-8482B", "ALL" },
- { "CRD-84" , "ALL" },
- { "SanDisk SDP3B" , "ALL" },
- { "SanDisk SDP3B-64" , "ALL" },
- { "SANYO CD-ROM CRD" , "ALL" },
- { "HITACHI CDR-8" , "ALL" },
- { "HITACHI CDR-8335" , "ALL" },
- { "HITACHI CDR-8435" , "ALL" },
- { "Toshiba CD-ROM XM-6202B" , "ALL" },
- { "CD-532E-A" , "ALL" },
- { "E-IDE CD-ROM CR-840", "ALL" },
- { "CD-ROM Drive/F5A", "ALL" },
- { "RICOH CD-R/RW MP7083A", "ALL" },
- { "WPI CDD-820", "ALL" },
- { "SAMSUNG CD-ROM SC-148C", "ALL" },
- { "SAMSUNG CD-ROM SC-148F", "ALL" },
- { "SAMSUNG CD-ROM SC", "ALL" },
- { "SanDisk SDP3B-64" , "ALL" },
- { "SAMSUNG CD-ROM SN-124", "ALL" },
- { "PLEXTOR CD-R PX-W8432T", "ALL" },
- { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" },
- { "_NEC DV5800A", "ALL" },
- { 0 , 0 }
-
-};
-
-int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
-{
- for ( ; drive_table->id_model ; drive_table++)
- if ((!strcmp(drive_table->id_model, id->model)) &&
- ((!strstr(drive_table->id_firmware, id->fw_rev)) ||
- (!strcmp(drive_table->id_firmware, "ALL"))))
- return 1;
- return 0;
-}
-
-#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */
-
-/*
- * good_dma_drives() lists the model names (from "hdparm -i")
- * of drives which do not support mode2 DMA but which are
- * known to work fine with this interface under Linux.
- */
-const char *good_dma_drives[] = {"Micropolis 2112A",
- "CONNER CTMA 4000",
- "CONNER CTT8000-A",
- "ST34342A", /* for Sun Ultra */
- NULL};
-
-/*
- * bad_dma_drives() lists the model names (from "hdparm -i")
- * of drives which supposedly support (U)DMA but which are
- * known to corrupt data with this interface under Linux.
- *
- * This is an empirical list. Its generated from bug reports. That means
- * while it reflects actual problem distributions it doesn't answer whether
- * the drive or the controller, or cabling, or software, or some combination
- * thereof is the fault. If you don't happen to agree with the kernel's
- * opinion of your drive - use hdparm to turn DMA on.
- */
-const char *bad_dma_drives[] = {"WDC AC11000H",
- "WDC AC22100H",
- "WDC AC32100H",
- "WDC AC32500H",
- "WDC AC33100H",
- "WDC AC31600H",
- NULL};
-
-#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */
-
-/*
- * Our Physical Region Descriptor (PRD) table should be large enough
- * to handle the biggest I/O request we are likely to see. Since requests
- * can have no more than 256 sectors, and since the typical blocksize is
- * two or more sectors, we could get by with a limit of 128 entries here for
- * the usual worst case. Most requests seem to include some contiguous blocks,
- * further reducing the number of table entries required.
- *
- * The driver reverts to PIO mode for individual requests that exceed
- * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling
- * 100% of all crazy scenarios here is not necessary.
- *
- * As it turns out though, we must allocate a full 4KB page for this,
- * so the two PRD tables (ide0 & ide1) will each get half of that,
- * allowing each to have about 256 entries (8 bytes each) from this.
- */
-#define PRD_BYTES 8
-#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES))
-
-/*
- * dma_intr() is the handler for disk read/write DMA interrupts
- */
-ide_startstop_t ide_dma_intr (ide_drive_t *drive)
-{
- int i;
- byte stat, dma_stat;
-
- dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
- stat = GET_STAT(); /* get drive status */
- if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
- if (!dma_stat) {
- struct request *rq = HWGROUP(drive)->rq;
- rq = HWGROUP(drive)->rq;
- for (i = rq->nr_sectors; i > 0;) {
- i -= rq->current_nr_sectors;
- ide_end_request(1, HWGROUP(drive));
- }
- return ide_stopped;
- }
- printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n",
- drive->name, dma_stat);
- }
- return ide_error(drive, "dma_intr", stat);
-}
-
-static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq)
-{
- struct buffer_head *bh;
- struct scatterlist *sg = hwif->sg_table;
- unsigned long lastdataend = ~0UL;
- int nents = 0;
-
- if (hwif->sg_dma_active)
- BUG();
-
- if (rq->cmd == READ)
- hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
- else
- hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-
- bh = rq->bh;
- do {
- struct scatterlist *sge;
-
- /*
- * continue segment from before?
- */
- if (virt_to_phys(bh->b_data) == lastdataend) {
- sg[nents - 1].length += bh->b_size;
- lastdataend += bh->b_size;
- continue;
- }
-
- /*
- * start new segment
- */
- if (nents >= PRD_ENTRIES)
- return 0;
-
- sge = &sg[nents];
- memset(sge, 0, sizeof(*sge));
- sge->address = bh->b_data;
- sge->length = bh->b_size;
- lastdataend = virt_to_phys(bh->b_data) + bh->b_size;
- nents++;
- } while ((bh = bh->b_reqnext) != NULL);
-
- return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
-}
-
-static int ide_raw_build_sglist (ide_hwif_t *hwif, struct request *rq)
-{
- struct scatterlist *sg = hwif->sg_table;
- int nents = 0;
- ide_task_t *args = rq->special;
- unsigned char *virt_addr = rq->buffer;
- int sector_count = rq->nr_sectors;
-
-// if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA) ||
-// (args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA_EXT))
- if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
- hwif->sg_dma_direction = PCI_DMA_TODEVICE;
- else
- hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-
- if (sector_count > 128) {
- memset(&sg[nents], 0, sizeof(*sg));
- sg[nents].address = virt_addr;
- sg[nents].length = 128 * SECTOR_SIZE;
- nents++;
- virt_addr = virt_addr + (128 * SECTOR_SIZE);
- sector_count -= 128;
- }
- memset(&sg[nents], 0, sizeof(*sg));
- sg[nents].address = virt_addr;
- sg[nents].length = sector_count * SECTOR_SIZE;
- nents++;
-
- return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
-}
-
-/*
- * ide_build_dmatable() prepares a dma request.
- * Returns 0 if all went okay, returns 1 otherwise.
- * May also be invoked from trm290.c
- */
-int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
-{
- unsigned int *table = HWIF(drive)->dmatable_cpu;
-#ifdef CONFIG_BLK_DEV_TRM290
- unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290);
-#else
- const int is_trm290_chipset = 0;
-#endif
- unsigned int count = 0;
- int i;
- struct scatterlist *sg;
-
- if (HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE)
- HWIF(drive)->sg_nents = i = ide_raw_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
- else
- HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
-
- if (!i)
- return 0;
-
- sg = HWIF(drive)->sg_table;
- while (i) {
- u32 cur_addr;
- u32 cur_len;
-
- cur_addr = sg_dma_address(sg);
- cur_len = sg_dma_len(sg);
-
- /*
- * Fill in the dma table, without crossing any 64kB boundaries.
- * Most hardware requires 16-bit alignment of all blocks,
- * but the trm290 requires 32-bit alignment.
- */
-
- while (cur_len) {
- u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
-
- if (count++ >= PRD_ENTRIES)
- BUG();
-
- if (bcount > cur_len)
- bcount = cur_len;
- *table++ = cpu_to_le32(cur_addr);
- xcount = bcount & 0xffff;
- if (is_trm290_chipset)
- xcount = ((xcount >> 2) - 1) << 16;
- if (xcount == 0x0000) {
- /*
- * Most chipsets correctly interpret a length
- * of 0x0000 as 64KB, but at least one
- * (e.g. CS5530) misinterprets it as zero (!).
- * So here we break the 64KB entry into two
- * 32KB entries instead.
- */
- if (count++ >= PRD_ENTRIES)
- goto use_pio_instead;
-
- *table++ = cpu_to_le32(0x8000);
- *table++ = cpu_to_le32(cur_addr + 0x8000);
- xcount = 0x8000;
- }
- *table++ = cpu_to_le32(xcount);
- cur_addr += bcount;
- cur_len -= bcount;
- }
-
- sg++;
- i--;
- }
-
- if (count) {
- if (!is_trm290_chipset)
- *--table |= cpu_to_le32(0x80000000);
- return count;
- }
- printk("%s: empty DMA table?\n", drive->name);
-use_pio_instead:
- pci_unmap_sg(HWIF(drive)->pci_dev,
- HWIF(drive)->sg_table,
- HWIF(drive)->sg_nents,
- HWIF(drive)->sg_dma_direction);
- HWIF(drive)->sg_dma_active = 0;
- return 0; /* revert to PIO for this request */
-}
-
-/* Teardown mappings after DMA has completed. */
-void ide_destroy_dmatable (ide_drive_t *drive)
-{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
- struct scatterlist *sg = HWIF(drive)->sg_table;
- int nents = HWIF(drive)->sg_nents;
-
- pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
- HWIF(drive)->sg_dma_active = 0;
-}
-
-/*
- * For both Blacklisted and Whitelisted drives.
- * This is setup to be called as an extern for future support
- * to other special driver code.
- */
-int check_drive_lists (ide_drive_t *drive, int good_bad)
-{
- struct hd_driveid *id = drive->id;
-
-#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
- if (good_bad) {
- return in_drive_list(id, drive_whitelist);
- } else {
- int blacklist = in_drive_list(id, drive_blacklist);
- if (blacklist)
- printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model);
- return(blacklist);
- }
-#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */
- const char **list;
-
- if (good_bad) {
- /* Consult the list of known "good" drives */
- list = good_dma_drives;
- while (*list) {
- if (!strcmp(*list++,id->model))
- return 1;
- }
- } else {
- /* Consult the list of known "bad" drives */
- list = bad_dma_drives;
- while (*list) {
- if (!strcmp(*list++,id->model)) {
- printk("%s: Disabling (U)DMA for %s\n",
- drive->name, id->model);
- return 1;
- }
- }
- }
-#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */
- return 0;
-}
-
-int report_drive_dmaing (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
-
- if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
- (id->dma_ultra & (id->dma_ultra >> 14) & 3)) {
- if ((id->dma_ultra >> 15) & 1) {
- printk(", UDMA(mode 7)"); /* UDMA BIOS-enabled! */
- } else {
- printk(", UDMA(133)"); /* UDMA BIOS-enabled! */
- }
- } else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
- (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
- if ((id->dma_ultra >> 13) & 1) {
- printk(", UDMA(100)"); /* UDMA BIOS-enabled! */
- } else if ((id->dma_ultra >> 12) & 1) {
- printk(", UDMA(66)"); /* UDMA BIOS-enabled! */
- } else {
- printk(", UDMA(44)"); /* UDMA BIOS-enabled! */
- }
- } else if ((id->field_valid & 4) &&
- (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
- if ((id->dma_ultra >> 10) & 1) {
- printk(", UDMA(33)"); /* UDMA BIOS-enabled! */
- } else if ((id->dma_ultra >> 9) & 1) {
- printk(", UDMA(25)"); /* UDMA BIOS-enabled! */
- } else {
- printk(", UDMA(16)"); /* UDMA BIOS-enabled! */
- }
- } else if (id->field_valid & 4) {
- printk(", (U)DMA"); /* Can be BIOS-enabled! */
- } else {
- printk(", DMA");
- }
- return 1;
-}
-
-static int config_drive_for_dma (ide_drive_t *drive)
-{
- int config_allows_dma = 1;
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
-
-#ifdef CONFIG_IDEDMA_ONLYDISK
- if (drive->media != ide_disk)
- config_allows_dma = 0;
-#endif
-
- if (id && (id->capability & 1) && hwif->autodma && config_allows_dma) {
- /* Consult the list of known "bad" drives */
- if (ide_dmaproc(ide_dma_bad_drive, drive))
- return hwif->dmaproc(ide_dma_off, drive);
-
- /* Enable DMA on any drive that has UltraDMA (mode 6/7/?) enabled */
- if ((id->field_valid & 4) && (eighty_ninty_three(drive)))
- if ((id->dma_ultra & (id->dma_ultra >> 14) & 2))
- return hwif->dmaproc(ide_dma_on, drive);
- /* Enable DMA on any drive that has UltraDMA (mode 3/4/5) enabled */
- if ((id->field_valid & 4) && (eighty_ninty_three(drive)))
- if ((id->dma_ultra & (id->dma_ultra >> 11) & 7))
- return hwif->dmaproc(ide_dma_on, drive);
- /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
- if (id->field_valid & 4) /* UltraDMA */
- if ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
- return hwif->dmaproc(ide_dma_on, drive);
- /* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */
- if (id->field_valid & 2) /* regular DMA */
- if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404)
- return hwif->dmaproc(ide_dma_on, drive);
- /* Consult the list of known "good" drives */
- if (ide_dmaproc(ide_dma_good_drive, drive))
- return hwif->dmaproc(ide_dma_on, drive);
- }
- return hwif->dmaproc(ide_dma_off_quietly, drive);
-}
-
-#ifndef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
-/*
- * 1 dmaing, 2 error, 4 intr
- */
-static int dma_timer_expiry (ide_drive_t *drive)
-{
- byte dma_stat = inb(HWIF(drive)->dma_base+2);
-
-#ifdef DEBUG
- printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat);
-#endif /* DEBUG */
-
-#if 0
- HWGROUP(drive)->expiry = NULL; /* one free ride for now */
-#endif
-
- if (dma_stat & 2) { /* ERROR */
- byte stat = GET_STAT();
- return ide_error(drive, "dma_timer_expiry", stat);
- }
- if (dma_stat & 1) /* DMAing */
- return WAIT_CMD;
- return 0;
-}
-#else /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
-static ide_startstop_t ide_dma_timeout_revovery (ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- ide_hwif_t *hwif = HWIF(drive);
- int enable_dma = drive->using_dma;
- unsigned long flags;
- ide_startstop_t startstop;
-
- spin_lock_irqsave(&io_request_lock, flags);
- hwgroup->handler = NULL;
- del_timer(&hwgroup->timer);
- spin_unlock_irqrestore(&io_request_lock, flags);
-
- drive->waiting_for_dma = 0;
-
- startstop = ide_do_reset(drive);
-
- if ((enable_dma) && !(drive->using_dma))
- (void) hwif->dmaproc(ide_dma_on, drive);
-
- return startstop;
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
-
-#if 0
-static inline void ide_toggle_bounce(ide_drive_t *drive, int on)
-{
- dma64_addr_t addr = BLK_BOUNCE_HIGH;
-
- if (HWIF(drive)->no_highio || HWIF(drive)->pci_dev == NULL)
- return;
-
- if (on && drive->media == ide_disk) {
- if (!PCI_DMA_BUS_IS_PHYS)
- addr = BLK_BOUNCE_ANY;
- else
- addr = HWIF(drive)->pci_dev->dma_mask;
- }
-
- blk_queue_bounce_limit(&drive->queue, addr);
-}
-#endif
-
-/*
- * ide_dmaproc() initiates/aborts DMA read/write operations on a drive.
- *
- * The caller is assumed to have selected the drive and programmed the drive's
- * sector address using CHS or LBA. All that remains is to prepare for DMA
- * and then issue the actual read/write DMA/PIO command to the drive.
- *
- * For ATAPI devices, we just prepare for DMA and return. The caller should
- * then issue the packet command to the drive and call us again with
- * ide_dma_begin afterwards.
- *
- * Returns 0 if all went well.
- * Returns 1 if DMA read/write could not be started, in which case
- * the caller should revert to PIO for the current request.
- * May also be invoked from trm290.c
- */
-int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
-{
-// ide_hwgroup_t *hwgroup = HWGROUP(drive);
- ide_hwif_t *hwif = HWIF(drive);
- unsigned long dma_base = hwif->dma_base;
- byte unit = (drive->select.b.unit & 0x01);
- unsigned int count, reading = 0/*, set_high = 1*/;
- byte dma_stat;
-
- switch (func) {
- case ide_dma_off:
- printk("%s: DMA disabled\n", drive->name);
- case ide_dma_off_quietly:
- /*set_high = 0;*/
- outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
- case ide_dma_on:
- drive->using_dma = (func == ide_dma_on);
- if (drive->using_dma)
- outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
- /*ide_toggle_bounce(drive, set_high);*/
- return 0;
- case ide_dma_check:
- return config_drive_for_dma (drive);
- case ide_dma_read:
- reading = 1 << 3;
- case ide_dma_write:
- SELECT_READ_WRITE(hwif,drive,func);
- if (!(count = ide_build_dmatable(drive, func)))
- return 1; /* try PIO instead of DMA */
- outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */
- outb(reading, dma_base); /* specify r/w */
- outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
- drive->waiting_for_dma = 1;
- if (drive->media != ide_disk)
- return 0;
-#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
- ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, NULL); /* issue cmd to drive */
-#else /* !CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
- ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */
-#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
- if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) &&
- (drive->addressing == 1)) {
- ide_task_t *args = HWGROUP(drive)->rq->special;
- OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG);
- } else if (drive->addressing) {
- OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
- } else {
- OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
- }
- return HWIF(drive)->dmaproc(ide_dma_begin, drive);
- case ide_dma_begin:
- /* Note that this is done *after* the cmd has
- * been issued to the drive, as per the BM-IDE spec.
- * The Promise Ultra33 doesn't work correctly when
- * we do this part before issuing the drive cmd.
- */
- outb(inb(dma_base)|1, dma_base); /* start DMA */
- return 0;
- case ide_dma_end: /* returns 1 on error, 0 otherwise */
- drive->waiting_for_dma = 0;
- outb(inb(dma_base)&~1, dma_base); /* stop DMA */
- dma_stat = inb(dma_base+2); /* get DMA status */
- outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
- ide_destroy_dmatable(drive); /* purge DMA mappings */
- return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */
- case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
- dma_stat = inb(dma_base+2);
-#if 0 /* do not set unless you know what you are doing */
- if (dma_stat & 4) {
- byte stat = GET_STAT();
- outb(dma_base+2, dma_stat & 0xE4);
- }
-#endif
- return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
- case ide_dma_bad_drive:
- case ide_dma_good_drive:
- return check_drive_lists(drive, (func == ide_dma_good_drive));
- case ide_dma_verbose:
- return report_drive_dmaing(drive);
- case ide_dma_timeout:
- // FIXME: Many IDE chipsets do not permit command file register access
- // FIXME: while the bus-master function is still active.
- // FIXME: To prevent deadlock with those chipsets, we must be extremely
- // FIXME: careful here (and in ide_intr() as well) to NOT access any
- // FIXME: registers from the 0x1Fx/0x17x sets before terminating the
- // FIXME: bus-master operation via the bus-master control reg.
- // FIXME: Otherwise, chipset deadlock will occur, and some systems will
- // FIXME: lock up completely!!
-#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
- /*
- * Have to issue an abort and requeue the request
- * DMA engine got turned off by a goofy ASIC, and
- * we have to clean up the mess, and here is as good
- * as any. Do it globally for all chipsets.
- */
- outb(0x00, dma_base); /* stop DMA */
- dma_stat = inb(dma_base+2); /* get DMA status */
- outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
- printk("%s: %s: Lets do it again!" \
- "stat = 0x%02x, dma_stat = 0x%02x\n",
- drive->name, ide_dmafunc_verbose(func),
- GET_STAT(), dma_stat);
-
- if (dma_stat & 0xF0)
- return ide_dma_timeout_revovery(drive);
-
- printk("%s: %s: (restart_request) Lets do it again!" \
- "stat = 0x%02x, dma_stat = 0x%02x\n",
- drive->name, ide_dmafunc_verbose(func),
- GET_STAT(), dma_stat);
-
- return restart_request(drive); // BUG: return types do not match!!
-//#else
-// return HWGROUP(drive)->handler(drive);
-#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
- case ide_dma_retune:
- case ide_dma_lostirq:
- printk("ide_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func);
- return 1;
- default:
- printk("ide_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
- return 1;
- }
-}
-
-/*
- * Needed for allowing full modular support of ide-driver
- */
-int ide_release_dma (ide_hwif_t *hwif)
-{
- if (hwif->dmatable_cpu) {
- pci_free_consistent(hwif->pci_dev,
- PRD_ENTRIES * PRD_BYTES,
- hwif->dmatable_cpu,
- hwif->dmatable_dma);
- hwif->dmatable_cpu = NULL;
- }
- if (hwif->sg_table) {
- kfree(hwif->sg_table);
- hwif->sg_table = NULL;
- }
- if ((hwif->dma_extra) && (hwif->channel == 0))
- release_region((hwif->dma_base + 16), hwif->dma_extra);
- release_region(hwif->dma_base, 8);
- return 1;
-}
-
-/*
- * This can be called for a dynamically installed interface. Don't __init it
- */
-
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
-{
- printk(" %s: BM-DMA at 0x%04lx-0x%04lx", hwif->name, dma_base, dma_base + num_ports - 1);
- if (check_region(dma_base, num_ports)) {
- printk(" -- ERROR, PORT ADDRESSES ALREADY IN USE\n");
- return;
- }
- request_region(dma_base, num_ports, hwif->name);
- hwif->dma_base = dma_base;
- hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
- PRD_ENTRIES * PRD_BYTES,
- &hwif->dmatable_dma);
- if (hwif->dmatable_cpu == NULL)
- goto dma_alloc_failure;
-
- hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,
- GFP_KERNEL);
- if (hwif->sg_table == NULL) {
- pci_free_consistent(hwif->pci_dev, PRD_ENTRIES * PRD_BYTES,
- hwif->dmatable_cpu, hwif->dmatable_dma);
- goto dma_alloc_failure;
- }
-
- hwif->dmaproc = &ide_dmaproc;
-
- if (hwif->chipset != ide_trm290) {
- byte dma_stat = inb(dma_base+2);
- printk(", BIOS settings: %s:%s, %s:%s",
- hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
- hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
- }
- printk("\n");
- return;
-
-dma_alloc_failure:
- printk(" -- ERROR, UNABLE TO ALLOCATE DMA TABLES\n");
-}
-
-/*
- * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
- */
-unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name)
-{
- unsigned long dma_base = 0;
- struct pci_dev *dev = hwif->pci_dev;
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
- int second_chance = 0;
-
-second_chance_to_dma:
-#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
-
- if (hwif->mate && hwif->mate->dma_base) {
- dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
- } else {
- dma_base = pci_resource_start(dev, 4);
- if (!dma_base) {
- printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base);
- dma_base = 0;
- }
- }
-
-#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
- if ((!dma_base) && (!second_chance)) {
- unsigned long set_bmiba = 0;
- second_chance++;
- switch(dev->vendor) {
- case PCI_VENDOR_ID_AL:
- set_bmiba = DEFAULT_BMALIBA; break;
- case PCI_VENDOR_ID_VIA:
- set_bmiba = DEFAULT_BMCRBA; break;
- case PCI_VENDOR_ID_INTEL:
- set_bmiba = DEFAULT_BMIBA; break;
- default:
- return dma_base;
- }
- pci_write_config_dword(dev, 0x20, set_bmiba|1);
- goto second_chance_to_dma;
- }
-#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */
-
- if (dma_base) {
- if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */
- request_region(dma_base+16, extra, name);
- dma_base += hwif->channel ? 8 : 0;
- hwif->dma_extra = extra;
-
- switch(dev->device) {
- case PCI_DEVICE_ID_AL_M5219:
- case PCI_DEVICE_ID_AMD_VIPER_7409:
- case PCI_DEVICE_ID_CMD_643:
- outb(inb(dma_base+2) & 0x60, dma_base+2);
- if (inb(dma_base+2) & 0x80) {
- printk("%s: simplex device: DMA forced\n", name);
- }
- break;
- default:
- /*
- * If the device claims "simplex" DMA,
- * this means only one of the two interfaces
- * can be trusted with DMA at any point in time.
- * So we should enable DMA only on one of the
- * two interfaces.
- */
- if ((inb(dma_base+2) & 0x80)) { /* simplex device? */
- if ((!hwif->drives[0].present && !hwif->drives[1].present) ||
- (hwif->mate && hwif->mate->dma_base)) {
- printk("%s: simplex device: DMA disabled\n", name);
- dma_base = 0;
- }
- }
- }
- }
- return dma_base;
-}
diff --git a/xen/drivers/ide/ide-features.c b/xen/drivers/ide/ide-features.c
deleted file mode 100644
index 97c7b1c403..0000000000
--- a/xen/drivers/ide/ide-features.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * linux/drivers/block/ide-features.c Version 0.04 June 9, 2000
- *
- * Copyright (C) 1999-2000 Linus Torvalds & authors (see below)
- *
- * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
- *
- * Extracts if ide.c to address the evolving transfer rate code for
- * the SETFEATURES_XFER callouts. Various parts of any given function
- * are credited to previous ATA-IDE maintainers.
- *
- * Auto-CRC downgrade for Ultra DMA(ing)
- *
- * May be copied or modified under the terms of the GNU General Public License
- */
-
-#include <xen/config.h>
-#define __NO_VERSION__
-#include <xen/module.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/timer.h>
-#include <xen/mm.h>
-#include <xen/interrupt.h>
-#include <xen/major.h>
-#include <xen/errno.h>
-#include <xen/genhd.h>
-#include <xen/blkpg.h>
-#include <xen/slab.h>
-#include <xen/pci.h>
-#include <xen/delay.h>
-#include <xen/hdreg.h>
-#include <xen/ide.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-
-/*
- * A Verbose noise maker for debugging on the attempted transfer rates.
- */
-char *ide_xfer_verbose (byte xfer_rate)
-{
- switch(xfer_rate) {
- case XFER_UDMA_7: return("UDMA 7");
- case XFER_UDMA_6: return("UDMA 6");
- case XFER_UDMA_5: return("UDMA 5");
- case XFER_UDMA_4: return("UDMA 4");
- case XFER_UDMA_3: return("UDMA 3");
- case XFER_UDMA_2: return("UDMA 2");
- case XFER_UDMA_1: return("UDMA 1");
- case XFER_UDMA_0: return("UDMA 0");
- case XFER_MW_DMA_2: return("MW DMA 2");
- case XFER_MW_DMA_1: return("MW DMA 1");
- case XFER_MW_DMA_0: return("MW DMA 0");
- case XFER_SW_DMA_2: return("SW DMA 2");
- case XFER_SW_DMA_1: return("SW DMA 1");
- case XFER_SW_DMA_0: return("SW DMA 0");
- case XFER_PIO_4: return("PIO 4");
- case XFER_PIO_3: return("PIO 3");
- case XFER_PIO_2: return("PIO 2");
- case XFER_PIO_1: return("PIO 1");
- case XFER_PIO_0: return("PIO 0");
- case XFER_PIO_SLOW: return("PIO SLOW");
- default: return("XFER ERROR");
- }
-}
-
-/*
- *
- */
-char *ide_media_verbose (ide_drive_t *drive)
-{
- switch (drive->media) {
- case ide_scsi: return("scsi ");
- case ide_disk: return("disk ");
- case ide_optical: return("optical");
- case ide_cdrom: return("cdrom ");
- case ide_tape: return("tape ");
- case ide_floppy: return("floppy ");
- default: return("???????");
- }
-}
-
-/*
- * A Verbose noise maker for debugging on the attempted dmaing calls.
- */
-char *ide_dmafunc_verbose (ide_dma_action_t dmafunc)
-{
- switch (dmafunc) {
- case ide_dma_read: return("ide_dma_read");
- case ide_dma_write: return("ide_dma_write");
- case ide_dma_begin: return("ide_dma_begin");
- case ide_dma_end: return("ide_dma_end:");
- case ide_dma_check: return("ide_dma_check");
- case ide_dma_on: return("ide_dma_on");
- case ide_dma_off: return("ide_dma_off");
- case ide_dma_off_quietly: return("ide_dma_off_quietly");
- case ide_dma_test_irq: return("ide_dma_test_irq");
- case ide_dma_bad_drive: return("ide_dma_bad_drive");
- case ide_dma_good_drive: return("ide_dma_good_drive");
- case ide_dma_verbose: return("ide_dma_verbose");
- case ide_dma_retune: return("ide_dma_retune");
- case ide_dma_lostirq: return("ide_dma_lostirq");
- case ide_dma_timeout: return("ide_dma_timeout");
- default: return("unknown");
- }
-}
-
-/*
- *
- */
-byte ide_auto_reduce_xfer (ide_drive_t *drive)
-{
- if (!drive->crc_count)
- return drive->current_speed;
- drive->crc_count = 0;
-
- switch(drive->current_speed) {
- case XFER_UDMA_7: return XFER_UDMA_6;
- case XFER_UDMA_6: return XFER_UDMA_5;
- case XFER_UDMA_5: return XFER_UDMA_4;
- case XFER_UDMA_4: return XFER_UDMA_3;
- case XFER_UDMA_3: return XFER_UDMA_2;
- case XFER_UDMA_2: return XFER_UDMA_1;
- case XFER_UDMA_1: return XFER_UDMA_0;
- /*
- * OOPS we do not goto non Ultra DMA modes
- * without iCRC's available we force
- * the system to PIO and make the user
- * invoke the ATA-1 ATA-2 DMA modes.
- */
- case XFER_UDMA_0:
- default: return XFER_PIO_4;
- }
-}
-
-/*
- * Update the
- */
-int ide_driveid_update (ide_drive_t *drive)
-{
- /*
- * Re-read drive->id for possible DMA mode
- * change (copied from ide-probe.c)
- */
- struct hd_driveid *id;
- unsigned long timeout, flags;
-
- SELECT_MASK(HWIF(drive), drive, 1);
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
- ide_delay_50ms();
- OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG);
- timeout = jiffies + WAIT_WORSTCASE;
- do {
- if (0 < (signed long)(jiffies - timeout)) {
- SELECT_MASK(HWIF(drive), drive, 0);
- return 0; /* drive timed-out */
- }
- ide_delay_50ms(); /* give drive a breather */
- } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT);
- ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */
- if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
- SELECT_MASK(HWIF(drive), drive, 0);
- printk("%s: CHECK for good STATUS\n", drive->name);
- return 0;
- }
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only; some systems need this */
- SELECT_MASK(HWIF(drive), drive, 0);
- id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
- if (!id) {
- __restore_flags(flags); /* local CPU only */
- return 0;
- }
- ide_input_data(drive, id, SECTOR_WORDS);
- (void) GET_STAT(); /* clear drive IRQ */
- ide__sti(); /* local CPU only */
- __restore_flags(flags); /* local CPU only */
- ide_fix_driveid(id);
- if (id) {
- drive->id->dma_ultra = id->dma_ultra;
- drive->id->dma_mword = id->dma_mword;
- drive->id->dma_1word = id->dma_1word;
- /* anything more ? */
- kfree(id);
- }
-
- return 1;
-}
-
-/*
- * Verify that we are doing an approved SETFEATURES_XFER with respect
- * to the hardware being able to support request. Since some hardware
- * can improperly report capabilties, we check to see if the host adapter
- * in combination with the device (usually a disk) properly detect
- * and acknowledge each end of the ribbon.
- */
-int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
-{
- if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
- (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) &&
- (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) {
- if (!HWIF(drive)->udma_four) {
- printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", HWIF(drive)->name);
- return 1;
- }
-#ifndef CONFIG_IDEDMA_IVB
- if ((drive->id->hw_config & 0x6000) == 0) {
-#else /* !CONFIG_IDEDMA_IVB */
- if (((drive->id->hw_config & 0x2000) == 0) ||
- ((drive->id->hw_config & 0x4000) == 0)) {
-#endif /* CONFIG_IDEDMA_IVB */
- printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name);
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER.
- * 1 : Safe to update drive->id DMA registers.
- * 0 : OOPs not allowed.
- */
-int set_transfer (ide_drive_t *drive, ide_task_t *args)
-{
- if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
- (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) &&
- (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) &&
- (drive->id->dma_ultra ||
- drive->id->dma_mword ||
- drive->id->dma_1word))
- return 1;
-
- return 0;
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-/*
- * All hosts that use the 80c ribbon mus use!
- */
-byte eighty_ninty_three (ide_drive_t *drive)
-{
-#ifdef CONFIG_BLK_DEV_IDEPCI
- if (HWIF(drive)->pci_devid.vid==0x105a)
- return(HWIF(drive)->udma_four);
-#endif
- /* PDC202XX: that's because some HDD will return wrong info */
- return ((byte) ((HWIF(drive)->udma_four) &&
-#ifndef CONFIG_IDEDMA_IVB
- (drive->id->hw_config & 0x4000) &&
-#endif /* CONFIG_IDEDMA_IVB */
- (drive->id->hw_config & 0x6000)) ? 1 : 0);
-}
-#endif // CONFIG_BLK_DEV_IDEDMA
-
-/*
- * Similar to ide_wait_stat(), except it never calls ide_error internally.
- * This is a kludge to handle the new ide_config_drive_speed() function,
- * and should not otherwise be used anywhere. Eventually, the tuneproc's
- * should be updated to return ide_startstop_t, in which case we can get
- * rid of this abomination again. :) -ml
- *
- * It is gone..........
- *
- * const char *msg == consider adding for verbose errors.
- */
-int ide_config_drive_speed (ide_drive_t *drive, byte speed)
-{
- ide_hwif_t *hwif = HWIF(drive);
- int i, error = 1;
- byte stat;
-
-#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
- byte unit = (drive->select.b.unit & 0x01);
- outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2);
-#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
-
- /*
- * Don't use ide_wait_cmd here - it will
- * attempt to set_geometry and recalibrate,
- * but for some reason these don't work at
- * this point (lost interrupt).
- */
- /*
- * Select the drive, and issue the SETFEATURES command
- */
- disable_irq(hwif->irq); /* disable_irq_nosync ?? */
- udelay(1);
- SELECT_DRIVE(HWIF(drive), drive);
- SELECT_MASK(HWIF(drive), drive, 0);
- udelay(1);
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
- OUT_BYTE(speed, IDE_NSECTOR_REG);
- OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
- OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
- if ((IDE_CONTROL_REG) && (drive->quirk_list == 2))
- OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
- udelay(1);
- /*
- * Wait for drive to become non-BUSY
- */
- if ((stat = GET_STAT()) & BUSY_STAT) {
- unsigned long flags, timeout;
- __save_flags(flags); /* local CPU only */
- ide__sti(); /* local CPU only -- for jiffies */
- timeout = jiffies + WAIT_CMD;
- while ((stat = GET_STAT()) & BUSY_STAT) {
- if (0 < (signed long)(jiffies - timeout))
- break;
- }
- __restore_flags(flags); /* local CPU only */
- }
-
- /*
- * Allow status to settle, then read it again.
- * A few rare drives vastly violate the 400ns spec here,
- * so we'll wait up to 10usec for a "good" status
- * rather than expensively fail things immediately.
- * This fix courtesy of Matthew Faupel & Niccolo Rigacci.
- */
- for (i = 0; i < 10; i++) {
- udelay(1);
- if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) {
- error = 0;
- break;
- }
- }
-
- SELECT_MASK(HWIF(drive), drive, 0);
-
- enable_irq(hwif->irq);
-
- if (error) {
- (void) ide_dump_status(drive, "set_drive_speed_status", stat);
- return error;
- }
-
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_1word &= ~0x0F00;
-
-#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
- if (speed > XFER_PIO_4) {
- outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2);
- } else {
- outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2);
- }
-#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
-
- switch(speed) {
- case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break;
- case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break;
- case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break;
- case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break;
- case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break;
- case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break;
- case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break;
- case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break;
- case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
- case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
- case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
- case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
- case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
- case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
- default: break;
- }
- return error;
-}
-
-EXPORT_SYMBOL(ide_auto_reduce_xfer);
-EXPORT_SYMBOL(ide_driveid_update);
-EXPORT_SYMBOL(ide_ata66_check);
-EXPORT_SYMBOL(set_transfer);
-#ifdef CONFIG_BLK_DEV_IDEDMA
-EXPORT_SYMBOL(eighty_ninty_three);
-#endif // CONFIG_BLK_DEV_IDEDMA
-EXPORT_SYMBOL(ide_config_drive_speed);
-
diff --git a/xen/drivers/ide/ide-geometry.c b/xen/drivers/ide/ide-geometry.c
deleted file mode 100644
index 1413d26fdc..0000000000
--- a/xen/drivers/ide/ide-geometry.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * linux/drivers/ide/ide-geometry.c
- */
-#include <xen/config.h>
-#include <xen/ide.h>
-#include <asm/mc146818rtc.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_BLK_DEV_IDE
-
-/*
- * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
- * controller that is BIOS compatible with ST-506, and thus showing up in our
- * BIOS table, but not register compatible, and therefore not present in CMOS.
- *
- * Furthermore, we will assume that our ST-506 drives <if any> are the primary
- * drives in the system -- the ones reflected as drive 1 or 2. The first
- * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
- * nibble. This will be either a 4 bit drive type or 0xf indicating use byte
- * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value
- * means we have an AT controller hard disk for that drive.
- *
- * Of course, there is no guarantee that either drive is actually on the
- * "primary" IDE interface, but we don't bother trying to sort that out here.
- * If a drive is not actually on the primary interface, then these parameters
- * will be ignored. This results in the user having to supply the logical
- * drive geometry as a boot parameter for each drive not on the primary i/f.
- */
-/*
- * The only "perfect" way to handle this would be to modify the setup.[cS] code
- * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
- * for us during initialization. I have the necessary docs -- any takers? -ml
- */
-/*
- * I did this, but it doesnt work - there is no reasonable way to find the
- * correspondence between the BIOS numbering of the disks and the Linux
- * numbering. -aeb
- *
- * The code below is bad. One of the problems is that drives 1 and 2
- * may be SCSI disks (even when IDE disks are present), so that
- * the geometry we read here from BIOS is attributed to the wrong disks.
- * Consequently, also the former "drive->present = 1" below was a mistake.
- *
- * Eventually the entire routine below should be removed.
- *
- * 17-OCT-2000 rjohnson@analogic.com Added spin-locks for reading CMOS
- * chip.
- */
-
-void probe_cmos_for_drives (ide_hwif_t *hwif)
-{
-#ifdef __i386__
- extern struct drive_info_struct drive_info;
- byte cmos_disks, *BIOS = (byte *) &drive_info;
- int unit;
- unsigned long flags;
-
-#ifdef CONFIG_BLK_DEV_PDC4030
- if (hwif->chipset == ide_pdc4030 && hwif->channel != 0)
- return;
-#endif /* CONFIG_BLK_DEV_PDC4030 */
- spin_lock_irqsave(&rtc_lock, flags);
- cmos_disks = CMOS_READ(0x12);
- spin_unlock_irqrestore(&rtc_lock, flags);
- /* Extract drive geometry from CMOS+BIOS if not already setup */
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- if ((cmos_disks & (0xf0 >> (unit*4)))
- && !drive->present && !drive->nobios) {
- unsigned short cyl = *(unsigned short *)BIOS;
- unsigned char head = *(BIOS+2);
- unsigned char sect = *(BIOS+14);
- if (cyl > 0 && head > 0 && sect > 0 && sect < 64) {
- drive->cyl = drive->bios_cyl = cyl;
- drive->head = drive->bios_head = head;
- drive->sect = drive->bios_sect = sect;
- drive->ctl = *(BIOS+8);
- } else {
- printk("hd%c: C/H/S=%d/%d/%d from BIOS ignored\n",
- unit+'a', cyl, head, sect);
- }
- }
- BIOS += 16;
- }
-#endif
-}
-#endif /* CONFIG_BLK_DEV_IDE */
-
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-
-/*
- * If heads is nonzero: find a translation with this many heads and S=63.
- * Otherwise: find out how OnTrack Disk Manager would translate the disk.
- */
-static void
-ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s) {
- static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
- const byte *headp = dm_head_vals;
- unsigned long total;
-
- /*
- * The specs say: take geometry as obtained from Identify,
- * compute total capacity C*H*S from that, and truncate to
- * 1024*255*63. Now take S=63, H the first in the sequence
- * 4, 8, 16, 32, 64, 128, 255 such that 63*H*1024 >= total.
- * [Please tell aeb@cwi.nl in case this computes a
- * geometry different from what OnTrack uses.]
- */
- total = DRIVER(drive)->capacity(drive);
-
- *s = 63;
-
- if (heads) {
- *h = heads;
- *c = total / (63 * heads);
- return;
- }
-
- while (63 * headp[0] * 1024 < total && headp[1] != 0)
- headp++;
- *h = headp[0];
- *c = total / (63 * headp[0]);
-}
-
-/*
- * This routine is called from the partition-table code in pt/msdos.c.
- * It has two tasks:
- * (i) to handle Ontrack DiskManager by offsetting everything by 63 sectors,
- * or to handle EZdrive by remapping sector 0 to sector 1.
- * (ii) to invent a translated geometry.
- * Part (i) is suppressed if the user specifies the "noremap" option
- * on the command line.
- * Part (ii) is suppressed if the user specifies an explicit geometry.
- *
- * The ptheads parameter is either 0 or tells about the number of
- * heads shown by the end of the first nonempty partition.
- * If this is either 16, 32, 64, 128, 240 or 255 we'll believe it.
- *
- * The xparm parameter has the following meaning:
- * 0 = convert to CHS with fewer than 1024 cyls
- * using the same method as Ontrack DiskManager.
- * 1 = same as "0", plus offset everything by 63 sectors.
- * -1 = similar to "0", plus redirect sector 0 to sector 1.
- * 2 = convert to a CHS geometry with "ptheads" heads.
- *
- * Returns 0 if the translation was not possible, if the device was not
- * an IDE disk drive, or if a geometry was "forced" on the commandline.
- * Returns 1 if the geometry translation was successful.
- */
-int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg)
-{
- ide_drive_t *drive;
- const char *msg1 = "";
- int heads = 0;
- int c, h, s;
- int transl = 1; /* try translation */
- int ret = 0;
-
- drive = get_info_ptr(i_rdev);
- if (!drive)
- return 0;
-
- /* remap? */
- if (drive->remap_0_to_1 != 2) {
- if (xparm == 1) { /* DM */
- drive->sect0 = 63;
- msg1 = " [remap +63]";
- ret = 1;
- } else if (xparm == -1) { /* EZ-Drive */
- if (drive->remap_0_to_1 == 0) {
- drive->remap_0_to_1 = 1;
- msg1 = " [remap 0->1]";
- ret = 1;
- }
- }
- }
-
- /* There used to be code here that assigned drive->id->CHS
- to drive->CHS and that to drive->bios_CHS. However,
- some disks have id->C/H/S = 4092/16/63 but are larger than 2.1 GB.
- In such cases that code was wrong. Moreover,
- there seems to be no reason to do any of these things. */
-
- /* translate? */
- if (drive->forced_geom)
- transl = 0;
-
- /* does ptheads look reasonable? */
- if (ptheads == 32 || ptheads == 64 || ptheads == 128 ||
- ptheads == 240 || ptheads == 255)
- heads = ptheads;
-
- if (xparm == 2) {
- if (!heads ||
- (drive->bios_head >= heads && drive->bios_sect == 63))
- transl = 0;
- }
- if (xparm == -1) {
- if (drive->bios_head > 16)
- transl = 0; /* we already have a translation */
- }
-
- if (transl) {
- ontrack(drive, heads, &c, &h, &s);
- drive->bios_cyl = c;
- drive->bios_head = h;
- drive->bios_sect = s;
- ret = 1;
- }
-
- drive->part[0].nr_sects = current_capacity(drive);
-
- if (ret)
- printk("%s%s [%d/%d/%d]", msg, msg1,
- drive->bios_cyl, drive->bios_head, drive->bios_sect);
- return ret;
-}
-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
diff --git a/xen/drivers/ide/ide-pci.c b/xen/drivers/ide/ide-pci.c
deleted file mode 100644
index 3196a37949..0000000000
--- a/xen/drivers/ide/ide-pci.c
+++ /dev/null
@@ -1,1016 +0,0 @@
-/*
- * linux/drivers/ide/ide-pci.c Version 1.05 June 9, 2000
- *
- * Copyright (c) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- *
- * Copyright (c) 1995-1998 Mark Lord
- * May be copied or modified under the terms of the GNU General Public License
- */
-
-/*
- * This module provides support for automatic detection and
- * configuration of all PCI IDE interfaces present in a system.
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/kernel.h>
-#include <xen/timer.h>
-#include <xen/mm.h>
-#include <xen/interrupt.h>
-#include <xen/pci.h>
-#include <xen/init.h>
-#include <xen/ide.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#define DEVID_PIIXa ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0})
-#define DEVID_PIIXb ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1})
-#define DEVID_MPIIX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX})
-#define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1})
-#define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB})
-#define DEVID_ICH0 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1})
-#define DEVID_PIIX4E2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1})
-#define DEVID_ICH ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1})
-#define DEVID_PIIX4U2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1})
-#define DEVID_PIIX4NX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX})
-#define DEVID_ICH2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9})
-#define DEVID_ICH2M ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8})
-#define DEVID_ICH3M ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10})
-#define DEVID_ICH3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11})
-#define DEVID_ICH4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11})
-#define DEVID_CICH ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11})
-#define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561})
-#define DEVID_MR_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1})
-#define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1})
-#define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246})
-#define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262})
-#define DEVID_PDC20265 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265})
-#define DEVID_PDC20267 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267})
-#define DEVID_PDC20268 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268})
-#define DEVID_PDC20270 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270})
-#define DEVID_PDC20269 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269})
-#define DEVID_PDC20275 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275})
-#define DEVID_PDC20276 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276})
-#define DEVID_RZ1000 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000})
-#define DEVID_RZ1001 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001})
-#define DEVID_SAMURAI ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE})
-#define DEVID_CMD640 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640})
-#define DEVID_CMD643 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643})
-#define DEVID_CMD646 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646})
-#define DEVID_CMD648 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648})
-#define DEVID_CMD649 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649})
-#define DEVID_CMD680 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680})
-#define DEVID_SIS5513 ((ide_pci_devid_t){PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513})
-#define DEVID_OPTI621 ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621})
-#define DEVID_OPTI621V ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558})
-#define DEVID_OPTI621X ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825})
-#define DEVID_TRM290 ((ide_pci_devid_t){PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290})
-#define DEVID_NS87410 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410})
-#define DEVID_NS87415 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415})
-#define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565})
-#define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF})
-#define DEVID_AEC6260 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860})
-#define DEVID_AEC6260R ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R})
-#define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})
-#define DEVID_UM8673F ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F})
-#define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A})
-#define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF})
-#define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343})
-#define DEVID_HPT366 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366})
-#define DEVID_ALI15X3 ((ide_pci_devid_t){PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229})
-#define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693})
-#define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013})
-#define DEVID_CS5530 ((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE})
-#define DEVID_AMD7401 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401})
-#define DEVID_AMD7409 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409})
-#define DEVID_AMD7411 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411})
-#define DEVID_AMD7441 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7441})
-#define DEVID_PDCADMA ((ide_pci_devid_t){PCI_VENDOR_ID_PDC, PCI_DEVICE_ID_PDC_ADMA100})
-#define DEVID_SLC90E66 ((ide_pci_devid_t){PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1})
-#define DEVID_OSB4 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE})
-#define DEVID_CSB5 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE})
-#define DEVID_ITE8172G ((ide_pci_devid_t){PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G})
-
-#define IDE_IGNORE ((void *)-1)
-#define IDE_NO_DRIVER ((void *)-2)
-
-#ifdef CONFIG_BLK_DEV_AEC62XX
-extern unsigned int pci_init_aec62xx(struct pci_dev *, const char *);
-extern unsigned int ata66_aec62xx(ide_hwif_t *);
-extern void ide_init_aec62xx(ide_hwif_t *);
-extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long);
-#define PCI_AEC62XX &pci_init_aec62xx
-#define ATA66_AEC62XX &ata66_aec62xx
-#define INIT_AEC62XX &ide_init_aec62xx
-#define DMA_AEC62XX &ide_dmacapable_aec62xx
-#else
-#define PCI_AEC62XX NULL
-#define ATA66_AEC62XX NULL
-#define INIT_AEC62XX IDE_NO_DRIVER
-#define DMA_AEC62XX NULL
-#endif
-
-#ifdef CONFIG_BLK_DEV_ALI15X3
-extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *);
-extern unsigned int ata66_ali15x3(ide_hwif_t *);
-extern void ide_init_ali15x3(ide_hwif_t *);
-extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long);
-#define PCI_ALI15X3 &pci_init_ali15x3
-#define ATA66_ALI15X3 &ata66_ali15x3
-#define INIT_ALI15X3 &ide_init_ali15x3
-#define DMA_ALI15X3 &ide_dmacapable_ali15x3
-#else
-#define PCI_ALI15X3 NULL
-#define ATA66_ALI15X3 NULL
-#define INIT_ALI15X3 IDE_NO_DRIVER
-#define DMA_ALI15X3 NULL
-#endif
-
-#ifdef CONFIG_BLK_DEV_AMD74XX
-extern unsigned int pci_init_amd74xx(struct pci_dev *, const char *);
-extern unsigned int ata66_amd74xx(ide_hwif_t *);
-extern void ide_init_amd74xx(ide_hwif_t *);
-extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long);
-#define PCI_AMD74XX &pci_init_amd74xx
-#define ATA66_AMD74XX &ata66_amd74xx
-#define INIT_AMD74XX &ide_init_amd74xx
-#define DMA_AMD74XX &ide_dmacapable_amd74xx
-#else
-#define PCI_AMD74XX NULL
-#define ATA66_AMD74XX NULL
-#define INIT_AMD74XX IDE_NO_DRIVER
-#define DMA_AMD74XX NULL
-#endif
-
-#ifdef CONFIG_BLK_DEV_CMD64X
-extern unsigned int pci_init_cmd64x(struct pci_dev *, const char *);
-extern unsigned int ata66_cmd64x(ide_hwif_t *);
-extern void ide_init_cmd64x(ide_hwif_t *);
-extern void ide_dmacapable_cmd64x(ide_hwif_t *, unsigned long);
-#define PCI_CMD64X &pci_init_cmd64x
-#define ATA66_CMD64X &ata66_cmd64x
-#define INIT_CMD64X &ide_init_cmd64x
-#else
-#define PCI_CMD64X NULL
-#define ATA66_CMD64X NULL
-#ifdef __sparc_v9__
-#define INIT_CMD64X IDE_IGNORE
-#else
-#define INIT_CMD64X IDE_NO_DRIVER
-#endif
-#endif
-
-#ifdef CONFIG_BLK_DEV_CY82C693
-extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *);
-extern void ide_init_cy82c693(ide_hwif_t *);
-#define PCI_CY82C693 &pci_init_cy82c693
-#define INIT_CY82C693 &ide_init_cy82c693
-#else
-#define PCI_CY82C693 NULL
-#define INIT_CY82C693 IDE_NO_DRIVER
-#endif
-
-#ifdef CONFIG_BLK_DEV_CS5530
-extern unsigned int pci_init_cs5530(struct pci_dev *, const char *);
-extern void ide_init_cs5530(ide_hwif_t *);
-#define PCI_CS5530 &pci_init_cs5530
-#define INIT_CS5530 &ide_init_cs5530
-#else
-#define PCI_CS5530 NULL
-#define INIT_CS5530 IDE_NO_DRIVER
-#endif
-
-#ifdef CONFIG_BLK_DEV_HPT34X
-extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *);
-extern void ide_init_hpt34x(ide_hwif_t *);
-#define PCI_HPT34X &pci_init_hpt34x
-#define INIT_HPT34X &ide_init_hpt34x
-#else
-#define PCI_HPT34X NULL
-#define INIT_HPT34X IDE_IGNORE
-#endif
-
-#ifdef CONFIG_BLK_DEV_HPT366
-extern byte hpt363_shared_irq;
-extern byte hpt363_shared_pin;
-extern unsigned int pci_init_hpt366(struct pci_dev *, const char *);
-extern unsigned int ata66_hpt366(ide_hwif_t *);
-extern void ide_init_hpt366(ide_hwif_t *);
-extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long);
-#define PCI_HPT366 &pci_init_hpt366
-#define ATA66_HPT366 &ata66_hpt366
-#define INIT_HPT366 &ide_init_hpt366
-#define DMA_HPT366 &ide_dmacapable_hpt366
-#else
-static byte hpt363_shared_irq;
-static byte hpt363_shared_pin;
-#define PCI_HPT366 NULL
-#define ATA66_HPT366 NULL
-#define INIT_HPT366 IDE_NO_DRIVER
-#define DMA_HPT366 NULL
-#endif
-
-#ifdef CONFIG_BLK_DEV_NS87415
-extern void ide_init_ns87415(ide_hwif_t *);
-#define INIT_NS87415 &ide_init_ns87415
-#else
-#define INIT_NS87415 IDE_IGNORE
-#endif
-
-#ifdef CONFIG_BLK_DEV_OPTI621
-extern void ide_init_opti621(ide_hwif_t *);
-#define INIT_OPTI621 &ide_init_opti621
-#else
-#define INIT_OPTI621 IDE_NO_DRIVER
-#endif
-
-#ifdef CONFIG_BLK_DEV_PDC_ADMA
-extern unsigned int pci_init_pdcadma(struct pci_dev *, const char *);
-extern unsigned int ata66_pdcadma(ide_hwif_t *);
-extern void ide_init_pdcadma(ide_hwif_t *);
-extern void ide_dmacapable_pdcadma(ide_hwif_t *, unsigned long);
-#define PCI_PDCADMA &pci_init_pdcadma
-#define ATA66_PDCADMA &ata66_pdcadma
-#define INIT_PDCADMA &ide_init_pdcadma
-#define DMA_PDCADMA &ide_dmacapable_pdcadma
-#else
-#define PCI_PDCADMA IDE_IGNORE
-#define ATA66_PDCADMA IDE_IGNORE
-#define INIT_PDCADMA IDE_IGNORE
-#define DMA_PDCADMA IDE_IGNORE
-#endif
-
-#ifdef CONFIG_BLK_DEV_PDC202XX
-extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *);
-extern unsigned int ata66_pdc202xx(ide_hwif_t *);
-extern void ide_init_pdc202xx(ide_hwif_t *);
-#define PCI_PDC202XX &pci_init_pdc202xx
-#define ATA66_PDC202XX &ata66_pdc202xx
-#define INIT_PDC202XX &ide_init_pdc202xx
-#else
-#define PCI_PDC202XX NULL
-#define ATA66_PDC202XX NULL
-#define INIT_PDC202XX NULL
-#endif
-
-#ifdef CONFIG_BLK_DEV_PIIX
-extern unsigned int pci_init_piix(struct pci_dev *, const char *);
-extern unsigned int ata66_piix(ide_hwif_t *);
-extern void ide_init_piix(ide_hwif_t *);
-#define PCI_PIIX &pci_init_piix
-#define ATA66_PIIX &ata66_piix
-#define INIT_PIIX &ide_init_piix
-#else
-#define PCI_PIIX NULL
-#define ATA66_PIIX NULL
-#define INIT_PIIX IDE_NO_DRIVER
-#endif
-
-#ifdef CONFIG_BLK_DEV_IT8172
-extern unsigned int pci_init_it8172(struct pci_dev *, const char *);
-extern unsigned int ata66_it8172(ide_hwif_t *);
-extern void ide_init_it8172(ide_hwif_t *);
-#define PCI_IT8172 &pci_init_it8172
-#define INIT_IT8172 &ide_init_it8172
-#else
-#define PCI_IT8172 NULL
-#define ATA66_IT8172 NULL
-#define INIT_IT8172 NULL
-#endif
-
-#ifdef CONFIG_BLK_DEV_RZ1000
-extern void ide_init_rz1000(ide_hwif_t *);
-#define INIT_RZ1000 &ide_init_rz1000
-#else
-#define INIT_RZ1000 IDE_IGNORE
-#endif
-
-#define INIT_SAMURAI NULL
-
-#ifdef CONFIG_BLK_DEV_SVWKS
-extern unsigned int pci_init_svwks(struct pci_dev *, const char *);
-extern unsigned int ata66_svwks(ide_hwif_t *);
-extern void ide_init_svwks(ide_hwif_t *);
-#define PCI_SVWKS &pci_init_svwks
-#define ATA66_SVWKS &ata66_svwks
-#define INIT_SVWKS &ide_init_svwks
-#else
-#define PCI_SVWKS NULL
-#define ATA66_SVWKS NULL
-#define INIT_SVWKS IDE_NO_DRIVER
-#endif
-
-#ifdef CONFIG_BLK_DEV_SIS5513
-extern unsigned int pci_init_sis5513(struct pci_dev *, const char *);
-extern unsigned int ata66_sis5513(ide_hwif_t *);
-extern void ide_init_sis5513(ide_hwif_t *);
-#define PCI_SIS5513 &pci_init_sis5513
-#define ATA66_SIS5513 &ata66_sis5513
-#define INIT_SIS5513 &ide_init_sis5513
-#else
-#define PCI_SIS5513 NULL
-#define ATA66_SIS5513 NULL
-#define INIT_SIS5513 IDE_NO_DRIVER
-#endif
-
-#ifdef CONFIG_BLK_DEV_SLC90E66
-extern unsigned int pci_init_slc90e66(struct pci_dev *, const char *);
-extern unsigned int ata66_slc90e66(ide_hwif_t *);
-extern void ide_init_slc90e66(ide_hwif_t *);
-#define PCI_SLC90E66 &pci_init_slc90e66
-#define ATA66_SLC90E66 &ata66_slc90e66
-#define INIT_SLC90E66 &ide_init_slc90e66
-#else
-#define PCI_SLC90E66 NULL
-#define ATA66_SLC90E66 NULL
-#define INIT_SLC90E66 IDE_NO_DRIVER
-#endif
-
-#ifdef CONFIG_BLK_DEV_SL82C105
-extern unsigned int pci_init_sl82c105(struct pci_dev *, const char *);
-extern void dma_init_sl82c105(ide_hwif_t *, unsigned long);
-extern void ide_init_sl82c105(ide_hwif_t *);
-#define PCI_W82C105 &pci_init_sl82c105
-#define DMA_W82C105 &dma_init_sl82c105
-#define INIT_W82C105 &ide_init_sl82c105
-#else
-#define PCI_W82C105 NULL
-#define DMA_W82C105 NULL
-#define INIT_W82C105 IDE_IGNORE
-#endif
-
-#ifdef CONFIG_BLK_DEV_TRM290
-extern void ide_init_trm290(ide_hwif_t *);
-#define INIT_TRM290 &ide_init_trm290
-#else
-#define INIT_TRM290 IDE_IGNORE
-#endif
-
-#ifdef CONFIG_BLK_DEV_VIA82CXXX
-extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *);
-extern unsigned int ata66_via82cxxx(ide_hwif_t *);
-extern void ide_init_via82cxxx(ide_hwif_t *);
-extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long);
-#define PCI_VIA82CXXX &pci_init_via82cxxx
-#define ATA66_VIA82CXXX &ata66_via82cxxx
-#define INIT_VIA82CXXX &ide_init_via82cxxx
-#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx
-#else
-#define PCI_VIA82CXXX NULL
-#define ATA66_VIA82CXXX NULL
-#define INIT_VIA82CXXX IDE_NO_DRIVER
-#define DMA_VIA82CXXX NULL
-#endif
-
-typedef struct ide_pci_enablebit_s {
- byte reg; /* byte pci reg holding the enable-bit */
- byte mask; /* mask to isolate the enable-bit */
- byte val; /* value of masked reg when "enabled" */
-} ide_pci_enablebit_t;
-
-typedef struct ide_pci_device_s {
- ide_pci_devid_t devid;
- char *name;
- unsigned int (*init_chipset)(struct pci_dev *dev, const char *name);
- unsigned int (*ata66_check)(ide_hwif_t *hwif);
- void (*init_hwif)(ide_hwif_t *hwif);
- void (*dma_init)(ide_hwif_t *hwif, unsigned long dmabase);
- ide_pci_enablebit_t enablebits[2];
- byte bootable;
- unsigned int extra;
-} ide_pci_device_t;
-
-static ide_pci_device_t ide_pci_chipsets[] __initdata = {
- {DEVID_PIIXa, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIXb, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_MPIIX, "MPIIX", NULL, NULL, INIT_PIIX, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIX3, "PIIX3", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIX4, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_ICH0, "ICH0", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIX4E2, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_ICH, "ICH", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIX4U2, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_PIIX4NX, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_ICH2, "ICH2", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_ICH2M, "ICH2M", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_ICH3M, "ICH3M", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_ICH3, "ICH3", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_ICH4, "ICH4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_CICH, "C-ICH", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_MR_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 },
- {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 },
-#ifndef CONFIG_PDC202XX_FORCE
- {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 },
- {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 },
- {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 },
- {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 },
-#else /* !CONFIG_PDC202XX_FORCE */
- {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 },
- {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 },
- {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 },
- {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 },
-#endif
- {DEVID_PDC20268,"PDC20268", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
- /* Promise used a different PCI ident for the raid card apparently to try and
- prevent Linux detecting it and using our own raid code. We want to detect
- it for the ataraid drivers, so we have to list both here.. */
- {DEVID_PDC20270,"PDC20270", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
- {DEVID_PDC20269,"PDC20269", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
- {DEVID_PDC20275,"PDC20275", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
- {DEVID_PDC20276,"PDC20276", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
- {DEVID_RZ1000, "RZ1000", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_RZ1001, "RZ1001", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_SAMURAI, "SAMURAI", NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_CMD640, "CMD640", NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_NS87410, "NS87410", NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 },
- {DEVID_SIS5513, "SIS5513", PCI_SIS5513, ATA66_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 },
- {DEVID_CMD643, "CMD643", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_CMD646, "CMD646", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_CMD648, "CMD648", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_CMD649, "CMD649", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
-#ifndef CONFIG_BLK_DEV_CMD680
- {DEVID_CMD680, "CMD680", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
-#else /* CONFIG_BLK_DEV_CMD680 */
- {DEVID_CMD680, "CMD680", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
-#endif /* !CONFIG_BLK_DEV_CMD680 */
- {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_OPTI621, "OPTI621", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 },
- {DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 },
- {DEVID_TRM290, "TRM290", NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_NS87415, "NS87415", NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_AEC6210, "AEC6210", PCI_AEC62XX, NULL, INIT_AEC62XX, DMA_AEC62XX, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 },
- {DEVID_AEC6260, "AEC6260", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 },
- {DEVID_AEC6260R,"AEC6260R", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 },
- {DEVID_W82C105, "W82C105", PCI_W82C105, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 },
- {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_HPT34X, "HPT34X", PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 },
- {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 },
- {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_CS5530, "CS5530", PCI_CS5530, NULL, INIT_CS5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_AMD7401, "AMD7401", NULL, NULL, NULL, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 },
- {DEVID_AMD7409, "AMD7409", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 },
- {DEVID_AMD7411, "AMD7411", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 },
- {DEVID_AMD7441, "AMD7441", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 },
- {DEVID_PDCADMA, "PDCADMA", PCI_PDCADMA, ATA66_PDCADMA, INIT_PDCADMA, DMA_PDCADMA, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
- {DEVID_SLC90E66,"SLC90E66", PCI_SLC90E66, ATA66_SLC90E66, INIT_SLC90E66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
- {DEVID_OSB4, "ServerWorks OSB4", PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_CSB5, "ServerWorks CSB5", PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_ITE8172G,"IT8172G", PCI_IT8172, NULL, INIT_IT8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 },
- {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }};
-
-/*
- * This allows offboard ide-pci cards the enable a BIOS, verify interrupt
- * settings of split-mirror pci-config space, place chipset into init-mode,
- * and/or preserve an interrupt if the card is not native ide support.
- */
-static unsigned int __init ide_special_settings (struct pci_dev *dev, const char *name)
-{
- switch(dev->device) {
- case PCI_DEVICE_ID_TTI_HPT366:
- case PCI_DEVICE_ID_PROMISE_20246:
- case PCI_DEVICE_ID_PROMISE_20262:
- case PCI_DEVICE_ID_PROMISE_20265:
- case PCI_DEVICE_ID_PROMISE_20267:
- case PCI_DEVICE_ID_PROMISE_20268:
- case PCI_DEVICE_ID_PROMISE_20270:
- case PCI_DEVICE_ID_PROMISE_20269:
- case PCI_DEVICE_ID_PROMISE_20275:
- case PCI_DEVICE_ID_PROMISE_20276:
- case PCI_DEVICE_ID_ARTOP_ATP850UF:
- case PCI_DEVICE_ID_ARTOP_ATP860:
- case PCI_DEVICE_ID_ARTOP_ATP860R:
- return dev->irq;
- default:
- break;
- }
- return 0;
-}
-
-/*
- * Match a PCI IDE port against an entry in ide_hwifs[],
- * based on io_base port if possible.
- */
-static ide_hwif_t __init *ide_match_hwif (unsigned long io_base, byte bootable, const char *name)
-{
- int h;
- ide_hwif_t *hwif;
-
- /*
- * Look for a hwif with matching io_base specified using
- * parameters to ide_setup().
- */
- for (h = 0; h < MAX_HWIFS; ++h) {
- hwif = &ide_hwifs[h];
- if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
- if (hwif->chipset == ide_generic)
- return hwif; /* a perfect match */
- }
- }
- /*
- * Look for a hwif with matching io_base default value.
- * If chipset is "ide_unknown", then claim that hwif slot.
- * Otherwise, some other chipset has already claimed it.. :(
- */
- for (h = 0; h < MAX_HWIFS; ++h) {
- hwif = &ide_hwifs[h];
- if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
- if (hwif->chipset == ide_unknown)
- return hwif; /* match */
- printk("%s: port 0x%04lx already claimed by %s\n", name, io_base, hwif->name);
- return NULL; /* already claimed */
- }
- }
- /*
- * Okay, there is no hwif matching our io_base,
- * so we'll just claim an unassigned slot.
- * Give preference to claiming other slots before claiming ide0/ide1,
- * just in case there's another interface yet-to-be-scanned
- * which uses ports 1f0/170 (the ide0/ide1 defaults).
- *
- * Unless there is a bootable card that does not use the standard
- * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag.
- */
- if (bootable) {
- for (h = 0; h < MAX_HWIFS; ++h) {
- hwif = &ide_hwifs[h];
- if (hwif->chipset == ide_unknown)
- return hwif; /* pick an unused entry */
- }
- } else {
- for (h = 2; h < MAX_HWIFS; ++h) {
- hwif = ide_hwifs + h;
- if (hwif->chipset == ide_unknown)
- return hwif; /* pick an unused entry */
- }
- }
- for (h = 0; h < 2; ++h) {
- hwif = ide_hwifs + h;
- if (hwif->chipset == ide_unknown)
- return hwif; /* pick an unused entry */
- }
- printk("%s: too many IDE interfaces, no room in table\n", name);
- return NULL;
-}
-
-static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
-{
- byte reg, progif = 0;
-
- /*
- * Place both IDE interfaces into PCI "native" mode:
- */
- if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) {
- if ((progif & 0xa) != 0xa) {
- printk("%s: device not capable of full native PCI mode\n", name);
- return 1;
- }
- printk("%s: placing both ports into native PCI mode\n", name);
- (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
- if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) {
- printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif);
- return 1;
- }
- }
- /*
- * Setup base registers for IDE command/control spaces for each interface:
- */
- for (reg = 0; reg < 4; reg++) {
- struct resource *res = dev->resource + reg;
- if ((res->flags & IORESOURCE_IO) == 0)
- continue;
- if (!res->start) {
- printk("%s: Missing I/O address #%d\n", name, reg);
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * ide_setup_pci_device() looks at the primary/secondary interfaces
- * on a PCI IDE device and, if they are enabled, prepares the IDE driver
- * for use with them. This generic code works for most PCI chipsets.
- *
- * One thing that is not standardized is the location of the
- * primary/secondary interface "enable/disable" bits. For chipsets that
- * we "know" about, this information is in the ide_pci_device_t struct;
- * for all other chipsets, we just assume both interfaces are enabled.
- */
-static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d)
-{
- unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0;
- unsigned short pcicmd = 0, tried_config = 0;
- byte tmp = 0;
- ide_hwif_t *hwif, *mate = NULL;
- unsigned int class_rev;
- static int secondpdc = 0;
-
-#ifdef CONFIG_IDEDMA_AUTO
- if (!noautodma)
- autodma = 1;
-#endif
-
- if (d->init_hwif == IDE_NO_DRIVER) {
- printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", d->name);
- d->init_hwif = NULL;
- }
-
- if (pci_enable_device(dev)) {
- if(pci_enable_device_bars(dev, 1<<4))
- {
- printk(KERN_WARNING "%s: (ide_setup_pci_device:) Could not enable device.\n", d->name);
- return;
- }
- printk(KERN_INFO "%s: BIOS setup was incomplete.\n", d->name);
- }
-
-check_if_enabled:
- if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {
- printk("%s: error accessing PCI regs\n", d->name);
- return;
- }
- if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */
- /*
- * PnP BIOS was *supposed* to have set this device up for us,
- * but we can do it ourselves, so long as the BIOS has assigned an IRQ
- * (or possibly the device is using a "legacy header" for IRQs).
- * Maybe the user deliberately *disabled* the device,
- * but we'll eventually ignore it again if no drives respond.
- */
- if (tried_config++
- || ide_setup_pci_baseregs(dev, d->name)
- || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
- printk("%s: device disabled (BIOS)\n", d->name);
- return;
- }
- autodma = 0; /* default DMA off if we had to configure it here */
- goto check_if_enabled;
- }
- if (tried_config)
- printk("%s: device enabled (Linux)\n", d->name);
-
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
-
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) {
- /* see comments in hpt34x.c on why..... */
- char *chipset_names[] = {"HPT343", "HPT345"};
- strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]);
- d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD;
- }
-
- printk("%s: chipset revision %d\n", d->name, class_rev);
-
- /*
- * Can we trust the reported IRQ?
- */
- pciirq = dev->irq;
-
- if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID)
- {
- /* By rights we want to ignore these, but the Promise Fastrak
- * people have some strange ideas about proprietary so we have
- * to act otherwise on those. The supertrak however we need
- * to skip
- */
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265))
- {
- printk(KERN_INFO "ide: Found promise 20265 in RAID mode.\n");
- if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL &&
- dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960)
- {
- printk(KERN_INFO "ide: Skipping Promise PDC20265 attached to I2O RAID controller.\n");
- return;
- }
- }
- /* Its attached to something else, just a random bridge.
- Suspect a fastrak and fall through */
- }
-
- if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
- printk("%s: not 100%% native mode: will probe irqs later\n", d->name);
- /*
- * This allows offboard ide-pci cards the enable a BIOS,
- * verify interrupt settings of split-mirror pci-config
- * space, place chipset into init-mode, and/or preserve
- * an interrupt if the card is not native ide support.
- */
- pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : ide_special_settings(dev, d->name);
- } else if (tried_config) {
- printk("%s: will probe irqs later\n", d->name);
- pciirq = 0;
- } else if (!pciirq) {
- printk("%s: bad irq (%d): will probe later\n", d->name, pciirq);
- pciirq = 0;
- } else {
- if (d->init_chipset)
- (void) d->init_chipset(dev, d->name);
-#ifdef __sparc__
- printk("%s: 100%% native mode on irq %s\n",
- d->name, __irq_itoa(pciirq));
-#else
- printk("%s: 100%% native mode on irq %d\n", d->name, pciirq);
-#endif
- }
-
- /*
- * Set up the IDE ports
- */
- for (port = 0; port <= 1; ++port) {
- unsigned long base = 0, ctl = 0;
- ide_pci_enablebit_t *e = &(d->enablebits[port]);
-
- /*
- * If this is a Promise FakeRaid controller, the 2nd controller will be marked as
- * disabled while it is actually there and enabled by the bios for raid purposes.
- * Skip the normal "is it enabled" test for those.
- */
- if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && (secondpdc++==1) && (port==1) )
- goto controller_ok;
- if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) && (secondpdc++==1) && (port==1) )
- goto controller_ok;
-
- if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
- continue; /* port not enabled */
-controller_ok:
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03))
- return;
- if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) {
- ctl = dev->resource[(2*port)+1].start;
- base = dev->resource[2*port].start;
- if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) ||
- !(base & PCI_BASE_ADDRESS_IO_MASK)) {
- printk("%s: IO baseregs (BIOS) are reported as MEM, report to <andre@linux-ide.org>.\n", d->name);
-#if 0
- /* FIXME! This really should check that it really gets the IO/MEM part right! */
- continue;
-#endif
- }
- }
- if ((ctl && !base) || (base && !ctl)) {
- printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port);
- continue;
- }
- if (!ctl)
- ctl = port ? 0x374 : 0x3f4; /* use default value */
- if (!base)
- base = port ? 0x170 : 0x1f0; /* use default value */
- if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL)
- continue; /* no room in ide_hwifs[] */
- if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
- ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL);
- memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
- hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
- }
- hwif->chipset = ide_pci;
- hwif->pci_dev = dev;
- hwif->pci_devid = d->devid;
- hwif->channel = port;
- if (!hwif->irq)
- hwif->irq = pciirq;
- if (mate) {
- hwif->mate = mate;
- mate->mate = hwif;
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210)) {
- hwif->serialized = 1;
- mate->serialized = 1;
- }
- }
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8673F)) {
- hwif->irq = hwif->channel ? 15 : 14;
- goto bypass_umc_dma;
- }
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_MPIIX))
- goto bypass_piix_dma;
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDCADMA))
- goto bypass_legacy_dma;
- if (hwif->udma_four) {
- printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name);
- } else {
- hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0;
- }
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_PIIX4NX) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_VIA_IDE) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_MR_IDE) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_VP_IDE))
- autodma = 0;
- if (autodma)
- hwif->autodma = 1;
-
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20270) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20269) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20275) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20276) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD646) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD648) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD649) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD680) ||
- IDE_PCI_DEVID_EQ(d->devid, DEVID_OSB4) ||
- ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
- unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name);
- if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
- /*
- * Set up BM-DMA capability (PnP BIOS should have done this)
- */
- if (!IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530))
- hwif->autodma = 0; /* default DMA off if we had to configure it here */
- (void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER);
- if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
- printk("%s: %s error updating PCICMD\n", hwif->name, d->name);
- dma_base = 0;
- }
- }
- if (dma_base) {
- if (d->dma_init) {
- d->dma_init(hwif, dma_base);
- } else {
- ide_setup_dma(hwif, dma_base, 8);
- }
- } else {
- printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name);
- }
- }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-bypass_legacy_dma:
-bypass_piix_dma:
-bypass_umc_dma:
- if (d->init_hwif) /* Call chipset-specific routine for each enabled hwif */
- d->init_hwif(hwif);
- mate = hwif;
- at_least_one_hwif_enabled = 1;
- }
- if (!at_least_one_hwif_enabled)
- printk("%s: neither IDE port enabled (BIOS)\n", d->name);
-}
-
-static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d)
-{
- struct pci_dev *dev2 = NULL, *findev;
- ide_pci_device_t *d2;
-
- if ((dev->bus->self &&
- dev->bus->self->vendor == PCI_VENDOR_ID_DEC) &&
- (dev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) {
- if (PCI_SLOT(dev->devfn) & 2) {
- return;
- }
- d->extra = 0;
- pci_for_each_dev(findev) {
- if ((findev->vendor == dev->vendor) &&
- (findev->device == dev->device) &&
- (PCI_SLOT(findev->devfn) & 2)) {
- byte irq = 0, irq2 = 0;
- dev2 = findev;
- pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
- pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2);
- if (irq != irq2) {
- dev2->irq = dev->irq;
- pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq);
- }
-
- }
- }
- }
-
- printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
- ide_setup_pci_device(dev, d);
- if (!dev2)
- return;
- d2 = d;
- printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn);
- ide_setup_pci_device(dev2, d2);
-}
-
-static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d)
-{
- struct pci_dev *dev2 = NULL, *findev;
- ide_pci_device_t *d2;
- unsigned char pin1 = 0, pin2 = 0;
- unsigned int class_rev;
- char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A", "HPT372"};
-
- if (PCI_FUNC(dev->devfn) & 1)
- return;
-
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
- if (class_rev > 5)
- class_rev = 5;
-
- strcpy(d->name, chipset_names[class_rev]);
-
- switch(class_rev) {
- case 4:
- case 3: printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
- ide_setup_pci_device(dev, d);
- return;
- default: break;
- }
-
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
- pci_for_each_dev(findev) {
- if ((findev->vendor == dev->vendor) &&
- (findev->device == dev->device) &&
- ((findev->devfn - dev->devfn) == 1) &&
- (PCI_FUNC(findev->devfn) & 1)) {
- dev2 = findev;
- pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
- hpt363_shared_pin = (pin1 != pin2) ? 1 : 0;
- hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0;
- if (hpt363_shared_pin && hpt363_shared_irq) {
- d->bootable = ON_BOARD;
- printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2);
-#if 0
- /* I forgot why I did this once, but it fixed something. */
- pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq);
- printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2);
- pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0);
-#endif
- }
- break;
- }
- }
- printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
- ide_setup_pci_device(dev, d);
- if (!dev2)
- return;
- d2 = d;
- printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn);
- ide_setup_pci_device(dev2, d2);
-}
-
-/*
- * ide_scan_pcibus() gets invoked at boot time from ide.c.
- * It finds all PCI IDE controllers and calls ide_setup_pci_device for them.
- */
-void __init ide_scan_pcidev (struct pci_dev *dev)
-{
- ide_pci_devid_t devid;
- ide_pci_device_t *d;
-
- devid.vid = dev->vendor;
- devid.did = dev->device;
- for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d);
- if (d->init_hwif == IDE_IGNORE)
- printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name);
- else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1))
- return;
- else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
- return; /* CY82C693 is more than only a IDE controller */
- else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_ITE8172G) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
- return; /* IT8172G is also more than only an IDE controller */
- else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1))
- return; /* UM8886A/BF pair */
- else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366))
- hpt366_device_order_fixup(dev, d);
- else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20270))
- pdc20270_device_order_fixup(dev, d);
- else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
- if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL))
- printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n",
- d->name, dev->bus->number, dev->devfn, devid.vid, devid.did);
- else
- printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
- ide_setup_pci_device(dev, d);
- }
-}
-
-void __init ide_scan_pcibus (int scan_direction)
-{
- struct pci_dev *dev;
-
- if (!scan_direction) {
- pci_for_each_dev(dev) {
- ide_scan_pcidev(dev);
- }
- } else {
- pci_for_each_dev_reverse(dev) {
- ide_scan_pcidev(dev);
- }
- }
-}
diff --git a/xen/drivers/ide/ide-probe.c b/xen/drivers/ide/ide-probe.c
deleted file mode 100644
index f6d77e4e7a..0000000000
--- a/xen/drivers/ide/ide-probe.c
+++ /dev/null
@@ -1,1066 +0,0 @@
-/*
- * linux/drivers/ide/ide-probe.c Version 1.07 March 18, 2001
- *
- * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
- */
-
-/*
- * Mostly written by Mark Lord <mlord@pobox.com>
- * and Gadi Oxman <gadio@netvision.net.il>
- * and Andre Hedrick <andre@linux-ide.org>
- *
- * See linux/MAINTAINERS for address of current maintainer.
- *
- * This is the IDE probe module, as evolved from hd.c and ide.c.
- *
- * Version 1.00 move drive probing code from ide.c to ide-probe.c
- * Version 1.01 fix compilation problem for m68k
- * Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot
- * by Andrea Arcangeli
- * Version 1.03 fix for (hwif->chipset == ide_4drives)
- * Version 1.04 fixed buggy treatments of known flash memory cards
- *
- * Version 1.05 fix for (hwif->chipset == ide_pdc4030)
- * added ide6/7/8/9
- * allowed for secondary flash card to be detectable
- * with new flag : drive->ata_flash : 1;
- * Version 1.06 stream line request queue and prep for cascade project.
- * Version 1.07 max_sect <= 255; slower disks would get behind and
- * then fall over when they get to 256. Paul G.
- */
-
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
-#include <xen/config.h>
-#include <xen/module.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/timer.h>
-#include <xen/mm.h>
-#include <xen/interrupt.h>
-#include <xen/major.h>
-#include <xen/errno.h>
-#include <xen/genhd.h>
-#include <xen/slab.h>
-#include <xen/delay.h>
-#include <xen/ide.h>
-#include <xen/spinlock.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#define IDE_PROBE_TRACE 0
-
-static inline void do_identify (ide_drive_t *drive, byte cmd)
-{
- int bswap = 1;
- struct hd_driveid *id;
-
- if (IDE_PROBE_TRACE)
- {
- printk (KERN_ALERT "ide-probe::do_identify\n");
- }
-
- id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC); /* called with interrupts disabled! */
- if (!id) {
- printk(KERN_WARNING "(ide-probe::do_identify) Out of memory.\n");
- goto err_kmalloc;
- }
-
- ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */
- ide__sti(); /* local CPU only */
- ide_fix_driveid(id);
-
- if (id->word156 == 0x4d42) {
- printk("%s: drive->id->word156 == 0x%04x \n", drive->name, drive->id->word156);
- }
-
- if (!drive->forced_lun)
- drive->last_lun = id->last_lun & 0x7;
-#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
- /*
- * EATA SCSI controllers do a hardware ATA emulation:
- * Ignore them if there is a driver for them available.
- */
- if ((id->model[0] == 'P' && id->model[1] == 'M')
- || (id->model[0] == 'S' && id->model[1] == 'K')) {
- printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);
- goto err_misc;
- }
-#endif /* CONFIG_SCSI_EATA_DMA || CONFIG_SCSI_EATA_PIO */
-
- /*
- * WIN_IDENTIFY returns little-endian info,
- * WIN_PIDENTIFY *usually* returns little-endian info.
- */
- if (cmd == WIN_PIDENTIFY) {
- if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */
- || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */
- || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */
- bswap ^= 1; /* Vertos drives may still be weird */
- }
- ide_fixstring (id->model, sizeof(id->model), bswap);
- ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap);
- ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap);
-
- if (strstr(id->model, "E X A B Y T E N E S T"))
- goto err_misc;
-
- id->model[sizeof(id->model)-1] = '\0'; /* we depend on this a lot! */
- printk("%s: %s, ", drive->name, id->model);
- drive->present = 1;
-
- /*
- * Check for an ATAPI device
- */
- if (cmd == WIN_PIDENTIFY) {
- byte type = (id->config >> 8) & 0x1f;
- printk("ATAPI ");
-#ifdef CONFIG_BLK_DEV_PDC4030
- if (HWIF(drive)->channel == 1 && HWIF(drive)->chipset == ide_pdc4030) {
- printk(" -- not supported on 2nd Promise port\n");
- goto err_misc;
- }
-#endif /* CONFIG_BLK_DEV_PDC4030 */
- switch (type) {
- case ide_floppy:
- if (!strstr(id->model, "CD-ROM")) {
- if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP"))
- printk("cdrom or floppy?, assuming ");
- if (drive->media != ide_cdrom) {
- printk ("FLOPPY");
- break;
- }
- }
- type = ide_cdrom; /* Early cdrom models used zero */
- case ide_cdrom:
- drive->removable = 1;
-#ifdef CONFIG_PPC
- /* kludge for Apple PowerBook internal zip */
- if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) {
- printk ("FLOPPY");
- type = ide_floppy;
- break;
- }
-#endif
- printk ("CD/DVD-ROM");
- break;
- case ide_tape:
- printk ("TAPE");
- break;
- case ide_optical:
- printk ("OPTICAL");
- drive->removable = 1;
- break;
- default:
- printk("UNKNOWN (type %d)", type);
- break;
- }
- printk (" drive\n");
- drive->media = type;
- return;
- }
-
- /*
- * Not an ATAPI device: looks like a "regular" hard disk
- */
- if (id->config & (1<<7))
- drive->removable = 1;
- /*
- * Prevent long system lockup probing later for non-existant
- * slave drive if the hwif is actually a flash memory card of some variety:
- */
- if (drive_is_flashcard(drive)) {
- ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit];
- if (!mate->ata_flash) {
- mate->present = 0;
- mate->noprobe = 1;
- }
- }
- drive->media = ide_disk;
- printk("ATA DISK drive\n");
- QUIRK_LIST(HWIF(drive),drive);
- return;
-
-err_misc:
- kfree(id);
-err_kmalloc:
- drive->present = 0;
- return;
-}
-
-/*
- * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive
- * and waits for a response. It also monitors irqs while this is
- * happening, in hope of automatically determining which one is
- * being used by the interface.
- *
- * Returns: 0 device was identified
- * 1 device timed-out (no response to identify request)
- * 2 device aborted the command (refused to identify itself)
- */
-static int actual_try_to_identify (ide_drive_t *drive, byte cmd)
-{
- int rc;
- ide_ioreg_t hd_status;
- unsigned long timeout;
- byte s, a;
-
- if (IDE_PROBE_TRACE)
- {
- printk (KERN_ALERT "ide-probe::actual_try_to_identify\n");
- }
-
- if (IDE_CONTROL_REG) {
- /* take a deep breath */
- ide_delay_50ms();
- a = IN_BYTE(IDE_ALTSTATUS_REG);
- s = IN_BYTE(IDE_STATUS_REG);
- if ((a ^ s) & ~INDEX_STAT) {
- printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a);
- hd_status = IDE_STATUS_REG; /* ancient Seagate drives, broken interfaces */
- } else {
- hd_status = IDE_ALTSTATUS_REG; /* use non-intrusive polling */
- }
- } else {
- ide_delay_50ms();
- hd_status = IDE_STATUS_REG;
- }
-
- /* set features register for atapi identify command to be sure of reply */
- if ((cmd == WIN_PIDENTIFY))
- OUT_BYTE(0,IDE_FEATURE_REG); /* disable dma & overlap */
-
-#if CONFIG_BLK_DEV_PDC4030
- if (HWIF(drive)->chipset == ide_pdc4030) {
- /* DC4030 hosted drives need their own identify... */
- extern int pdc4030_identify(ide_drive_t *);
- if (pdc4030_identify(drive)) {
- return 1;
- }
- } else
-#endif /* CONFIG_BLK_DEV_PDC4030 */
- OUT_BYTE(cmd,IDE_COMMAND_REG); /* ask drive for ID */
- timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
- timeout += jiffies;
- do {
- if (0 < (signed long)(jiffies - timeout)) {
- return 1; /* drive timed-out */
- }
- ide_delay_50ms(); /* give drive a breather */
- } while (IN_BYTE(hd_status) & BUSY_STAT);
-
- ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */
- if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
- unsigned long flags;
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only; some systems need this */
- do_identify(drive, cmd); /* drive returned ID */
- rc = 0; /* drive responded with ID */
- (void) GET_STAT(); /* clear drive IRQ */
- __restore_flags(flags); /* local CPU only */
- } else
- rc = 2; /* drive refused ID */
- return rc;
-}
-
-static int try_to_identify (ide_drive_t *drive, byte cmd)
-{
- int retval;
- int autoprobe = 0;
- unsigned long cookie = 0;
-
- if (IDE_PROBE_TRACE)
- {
- printk (KERN_ALERT "ide-probe::try_to_identify\n");
- }
-
- if (IDE_CONTROL_REG && !HWIF(drive)->irq) {
- autoprobe = 1;
- cookie = probe_irq_on();
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */
- }
-
- retval = actual_try_to_identify(drive, cmd);
-
- if (autoprobe) {
- int irq;
- OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */
- (void) GET_STAT(); /* clear drive IRQ */
- udelay(5);
- irq = probe_irq_off(cookie);
- if (!HWIF(drive)->irq) {
- if (irq > 0) {
- HWIF(drive)->irq = irq;
- } else { /* Mmmm.. multiple IRQs.. don't know which was ours */
- printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie);
-#ifdef CONFIG_BLK_DEV_CMD640
-#ifdef CMD640_DUMP_REGS
- if (HWIF(drive)->chipset == ide_cmd640) {
- printk("%s: Hmmm.. probably a driver problem.\n", drive->name);
- CMD640_DUMP_REGS;
- }
-#endif /* CMD640_DUMP_REGS */
-#endif /* CONFIG_BLK_DEV_CMD640 */
- }
- }
- }
- return retval;
-}
-
-
-/*
- * do_probe() has the difficult job of finding a drive if it exists,
- * without getting hung up if it doesn't exist, without trampling on
- * ethernet cards, and without leaving any IRQs dangling to haunt us later.
- *
- * If a drive is "known" to exist (from CMOS or kernel parameters),
- * but does not respond right away, the probe will "hang in there"
- * for the maximum wait time (about 30 seconds), otherwise it will
- * exit much more quickly.
- *
- * Returns: 0 device was identified
- * 1 device timed-out (no response to identify request)
- * 2 device aborted the command (refused to identify itself)
- * 3 bad status from device (possible for ATAPI drives)
- * 4 probe was not attempted because failure was obvious
- */
-static int do_probe (ide_drive_t *drive, byte cmd)
-{
- int rc;
- ide_hwif_t *hwif = HWIF(drive);
-
- if (IDE_PROBE_TRACE)
- {
- printk (KERN_ALERT "ide-probe::do_probe\n");
- }
-
- if (drive->present) { /* avoid waiting for inappropriate probes */
- if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY))
- return 4;
- }
-#ifdef DEBUG
- printk("probing for %s: present=%d, media=%d, probetype=%s\n",
- drive->name, drive->present, drive->media,
- (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
-#endif
- ide_delay_50ms(); /* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */
- SELECT_DRIVE(hwif,drive);
- ide_delay_50ms();
- if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) {
- if (drive->select.b.unit != 0) {
- SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */
- ide_delay_50ms(); /* allow BUSY_STAT to assert & clear */
- }
- return 3; /* no i/f present: mmm.. this should be a 4 -ml */
- }
-
- if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT)
- || drive->present || cmd == WIN_PIDENTIFY)
- {
- if ((rc = try_to_identify(drive,cmd))) /* send cmd and wait */
- rc = try_to_identify(drive,cmd); /* failed: try again */
- if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) {
- unsigned long timeout;
- printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT());
- ide_delay_50ms();
- OUT_BYTE (drive->select.all, IDE_SELECT_REG);
- ide_delay_50ms();
- OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
- timeout = jiffies;
- while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE))
- ide_delay_50ms();
- rc = try_to_identify(drive, cmd);
- }
- if (rc == 1)
- printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT());
- (void) GET_STAT(); /* ensure drive irq is clear */
- } else {
- rc = 3; /* not present or maybe ATAPI */
- }
- if (drive->select.b.unit != 0) {
- SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */
- ide_delay_50ms();
- (void) GET_STAT(); /* ensure drive irq is clear */
- }
- return rc;
-}
-
-/*
- *
- */
-static void enable_nest (ide_drive_t *drive)
-{
- unsigned long timeout;
-
- if (IDE_PROBE_TRACE)
- {
- printk (KERN_ALERT "ide-probe::enable_nest\n");
- }
-
- printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model);
- SELECT_DRIVE(HWIF(drive), drive);
- ide_delay_50ms();
- OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
- timeout = jiffies + WAIT_WORSTCASE;
- do {
- if (time_after(jiffies, timeout)) {
- printk("failed (timeout)\n");
- return;
- }
- ide_delay_50ms();
- } while (GET_STAT() & BUSY_STAT);
- ide_delay_50ms();
- if (!OK_STAT(GET_STAT(), 0, BAD_STAT))
- printk("failed (status = 0x%02x)\n", GET_STAT());
- else
- printk("success\n");
- if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */
- (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */
- }
-}
-
-/*
- * probe_for_drive() tests for existence of a given drive using do_probe().
- *
- * Returns: 0 no device was found
- * 1 device was found (note: drive->present might still be 0)
- */
-static inline byte probe_for_drive (ide_drive_t *drive)
-{
- if (IDE_PROBE_TRACE)
- {
- printk (KERN_ALERT "ide-probe::probe_for_drive\n");
- }
-
- if (drive->noprobe) /* skip probing? */
- return drive->present;
- if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */
- (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */
- }
- if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T"))
- enable_nest(drive);
- if (!drive->present)
- return 0; /* drive not found */
- if (drive->id == NULL) { /* identification failed? */
- if (drive->media == ide_disk) {
- printk ("%s: non-IDE drive, CHS=%d/%d/%d\n",
- drive->name, drive->cyl, drive->head, drive->sect);
- } else if (drive->media == ide_cdrom) {
- printk("%s: ATAPI cdrom (?)\n", drive->name);
- } else {
- drive->present = 0; /* nuke it */
- }
- }
- return 1; /* drive was found */
-}
-
-/*
- * Calculate the region that this interface occupies,
- * handling interfaces where the registers may not be
- * ordered sanely. We deal with the CONTROL register
- * separately.
- */
-static int hwif_check_regions (ide_hwif_t *hwif)
-{
- int region_errors = 0;
-
- hwif->straight8 = 0;
- region_errors = ide_check_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_ERROR_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_LCYL_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_HCYL_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_SELECT_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_STATUS_OFFSET], 1);
-
- if (hwif->io_ports[IDE_CONTROL_OFFSET])
- region_errors += ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
-#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
- if (hwif->io_ports[IDE_IRQ_OFFSET])
- region_errors += ide_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1);
-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
- /*
- * If any errors are return, we drop the hwif interface.
- */
- return(region_errors);
-}
-
-static void hwif_register (ide_hwif_t *hwif)
-{
- if (((unsigned long)hwif->io_ports[IDE_DATA_OFFSET] | 7) ==
- ((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) {
- ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name);
- hwif->straight8 = 1;
- goto jump_straight8;
- }
-
- if (hwif->io_ports[IDE_DATA_OFFSET])
- ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_ERROR_OFFSET])
- ide_request_region(hwif->io_ports[IDE_ERROR_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_NSECTOR_OFFSET])
- ide_request_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_SECTOR_OFFSET])
- ide_request_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_LCYL_OFFSET])
- ide_request_region(hwif->io_ports[IDE_LCYL_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_HCYL_OFFSET])
- ide_request_region(hwif->io_ports[IDE_HCYL_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_SELECT_OFFSET])
- ide_request_region(hwif->io_ports[IDE_SELECT_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_STATUS_OFFSET])
- ide_request_region(hwif->io_ports[IDE_STATUS_OFFSET], 1, hwif->name);
-
-jump_straight8:
- if (hwif->io_ports[IDE_CONTROL_OFFSET])
- ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name);
-#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
- if (hwif->io_ports[IDE_IRQ_OFFSET])
- ide_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name);
-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
-}
-
-/*
- * This routine only knows how to look for drive units 0 and 1
- * on an interface, so any setting of MAX_DRIVES > 2 won't work here.
- */
-static void probe_hwif (ide_hwif_t *hwif)
-{
- unsigned int unit;
- unsigned long flags;
-
- if (IDE_PROBE_TRACE)
- {
- printk (KERN_ALERT "ide-probe::probe_hwif\n");
- }
-
- if (hwif->noprobe)
- return;
-#ifdef CONFIG_BLK_DEV_IDE
- if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) {
- extern void probe_cmos_for_drives(ide_hwif_t *);
-
- probe_cmos_for_drives (hwif);
- }
-#endif
-
- if ((hwif->chipset != ide_4drives || !hwif->mate->present) &&
-#if CONFIG_BLK_DEV_PDC4030
- (hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&
-#endif /* CONFIG_BLK_DEV_PDC4030 */
- (hwif_check_regions(hwif))) {
- int msgout = 0;
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present) {
- drive->present = 0;
- printk("%s: ERROR, PORTS ALREADY IN USE\n", drive->name);
- msgout = 1;
- }
- }
- if (!msgout)
- printk("%s: ports already in use, skipping probe\n", hwif->name);
- return;
- }
-
- __save_flags(flags); /* local CPU only */
- __sti(); /* local CPU only; needed for jiffies and irq probing */
- /*
- * Second drive should only exist if first drive was found,
- * but a lot of cdrom drives are configured as single slaves.
- */
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- (void) probe_for_drive (drive);
- if (drive->present && !hwif->present) {
- hwif->present = 1;
- if (hwif->chipset != ide_4drives || !hwif->mate->present) {
- hwif_register(hwif);
- }
- }
- }
- if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) {
- unsigned long timeout = jiffies + WAIT_WORSTCASE;
- byte stat;
-
- printk("%s: reset\n", hwif->name);
- OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
- udelay(10);
- OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
- do {
- ide_delay_50ms();
- stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
- } while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies));
-
- }
- __restore_flags(flags); /* local CPU only */
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present) {
- ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
- if (tuneproc != NULL && drive->autotune == 1)
- tuneproc(drive, 255); /* auto-tune PIO mode */
- }
- }
-}
-
-#if MAX_HWIFS > 1
-/*
- * save_match() is used to simplify logic in init_irq() below.
- *
- * A loophole here is that we may not know about a particular
- * hwif's irq until after that hwif is actually probed/initialized..
- * This could be a problem for the case where an hwif is on a
- * dual interface that requires serialization (eg. cmd640) and another
- * hwif using one of the same irqs is initialized beforehand.
- *
- * This routine detects and reports such situations, but does not fix them.
- */
-static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
-{
- ide_hwif_t *m = *match;
-
- if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
- if (!new->hwgroup)
- return;
- printk("%s: potential irq problem with %s and %s\n", hwif->name, new->name, m->name);
- }
- if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
- *match = new;
-}
-#endif /* MAX_HWIFS > 1 */
-
-/*
- * init request queue
- */
-static void ide_init_queue(ide_drive_t *drive)
-{
- request_queue_t *q = &drive->queue;
-
- q->queuedata = HWGROUP(drive);
- blk_init_queue(q, do_ide_request);
-
- if (drive->media == ide_disk) {
-#ifdef CONFIG_BLK_DEV_ELEVATOR_NOOP
- elevator_init(&q->elevator, ELEVATOR_NOOP);
-#endif
- }
-}
-
-/*
- * This routine sets up the irq for an ide interface, and creates a new
- * hwgroup for the irq/hwif if none was previously assigned.
- *
- * Much of the code is for correctly detecting/handling irq sharing
- * and irq serialization situations. This is somewhat complex because
- * it handles static as well as dynamic (PCMCIA) IDE interfaces.
- *
- * The SA_INTERRUPT in sa_flags means ide_intr() is always entered with
- * interrupts completely disabled. This can be bad for interrupt latency,
- * but anything else has led to problems on some machines. We re-enable
- * interrupts as much as we can safely do in most places.
- */
-static int init_irq (ide_hwif_t *hwif)
-{
- unsigned long flags;
- unsigned int index;
- ide_hwgroup_t *hwgroup, *new_hwgroup;
- ide_hwif_t *match = NULL;
-
-
- /* Allocate the buffer and potentially sleep first */
-
- new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
-
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
-
- hwif->hwgroup = NULL;
-#if MAX_HWIFS > 1
- /*
- * Group up with any other hwifs that share our irq(s).
- */
- for (index = 0; index < MAX_HWIFS; index++) {
- ide_hwif_t *h = &ide_hwifs[index];
- if (h->hwgroup) { /* scan only initialized hwif's */
- if (hwif->irq == h->irq) {
- hwif->sharing_irq = h->sharing_irq = 1;
- if (hwif->chipset != ide_pci || h->chipset != ide_pci) {
- save_match(hwif, h, &match);
- }
- }
- if (hwif->serialized) {
- if (hwif->mate && hwif->mate->irq == h->irq)
- save_match(hwif, h, &match);
- }
- if (h->serialized) {
- if (h->mate && hwif->irq == h->mate->irq)
- save_match(hwif, h, &match);
- }
- }
- }
-#endif /* MAX_HWIFS > 1 */
- /*
- * If we are still without a hwgroup, then form a new one
- */
- if (match) {
- hwgroup = match->hwgroup;
- if(new_hwgroup)
- kfree(new_hwgroup);
- } else {
- hwgroup = new_hwgroup;
- if (!hwgroup) {
- restore_flags(flags); /* all CPUs */
- return 1;
- }
- memset(hwgroup, 0, sizeof(ide_hwgroup_t));
- hwgroup->hwif = hwif->next = hwif;
- hwgroup->rq = NULL;
- hwgroup->handler = NULL;
- hwgroup->drive = NULL;
- hwgroup->busy = 0;
- init_timer(&hwgroup->timer);
- hwgroup->timer.function = &ide_timer_expiry;
- hwgroup->timer.data = (unsigned long) hwgroup;
- }
-
- /*
- * Allocate the irq, if not already obtained for another hwif
- */
- if (!match || match->irq != hwif->irq) {
-#ifdef CONFIG_IDEPCI_SHARE_IRQ
- int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_SHIRQ : SA_INTERRUPT;
-#else /* !CONFIG_IDEPCI_SHARE_IRQ */
- int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;
-#endif /* CONFIG_IDEPCI_SHARE_IRQ */
-
- if (hwif->io_ports[IDE_CONTROL_OFFSET])
- OUT_BYTE(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]); /* clear nIEN */
-
- if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) {
- if (!match)
- kfree(hwgroup);
- restore_flags(flags); /* all CPUs */
- return 1;
- }
- }
-
- /*
- * Everything is okay, so link us into the hwgroup
- */
- hwif->hwgroup = hwgroup;
- hwif->next = hwgroup->hwif->next;
- hwgroup->hwif->next = hwif;
-
- for (index = 0; index < MAX_DRIVES; ++index) {
- ide_drive_t *drive = &hwif->drives[index];
- if (!drive->present)
- continue;
- if (!hwgroup->drive)
- hwgroup->drive = drive;
- drive->next = hwgroup->drive->next;
- hwgroup->drive->next = drive;
- ide_init_queue(drive);
- }
- if (!hwgroup->hwif) {
- hwgroup->hwif = HWIF(hwgroup->drive);
-#ifdef DEBUG
- printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name);
-#endif
- }
- restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */
-
-#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
- printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
- hwif->io_ports[IDE_DATA_OFFSET],
- hwif->io_ports[IDE_DATA_OFFSET]+7,
- hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);
-#elif defined(__sparc__)
- printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", hwif->name,
- hwif->io_ports[IDE_DATA_OFFSET],
- hwif->io_ports[IDE_DATA_OFFSET]+7,
- hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq));
-#else
- printk("%s at %p on irq 0x%08x", hwif->name,
- hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);
-#endif /* __mc68000__ && CONFIG_APUS */
- if (match)
- printk(" (%sed with %s)",
- hwif->sharing_irq ? "shar" : "serializ", match->name);
- printk("\n");
- return 0;
-}
-
-/*
- * init_gendisk() (as opposed to ide_geninit) is called for each major device,
- * after probing for drives, to allocate partition tables and other data
- * structures needed for the routines in genhd.c. ide_geninit() gets called
- * somewhat later, during the partition check.
- */
-static void init_gendisk (ide_hwif_t *hwif)
-{
- struct gendisk *gd;
- unsigned int unit, units, minors;
- int *bs, *max_sect; /* , *max_ra; */
-#ifdef DEVFS_MUST_DIE
- extern devfs_handle_t ide_devfs_handle;
-#endif
-
-#if 1
- units = MAX_DRIVES;
-#else
- /* figure out maximum drive number on the interface */
- for (units = MAX_DRIVES; units > 0; --units) {
- if (hwif->drives[units-1].present)
- break;
- }
-#endif
-
- minors = units * (1<<PARTN_BITS);
- gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
- if (!gd)
- goto err_kmalloc_gd;
- gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
- if (!gd->sizes)
- goto err_kmalloc_gd_sizes;
- gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
- if (!gd->part)
- goto err_kmalloc_gd_part;
- bs = kmalloc (minors*sizeof(int), GFP_KERNEL);
- if (!bs)
- goto err_kmalloc_bs;
- max_sect = kmalloc (minors*sizeof(int), GFP_KERNEL);
- if (!max_sect)
- goto err_kmalloc_max_sect;
-#if 0
- max_ra = kmalloc (minors*sizeof(int), GFP_KERNEL);
- if (!max_ra)
- goto err_kmalloc_max_ra;
-#endif
-
- memset(gd->part, 0, minors * sizeof(struct hd_struct));
-
- /* cdroms and msdos f/s are examples of non-1024 blocksizes */
- blksize_size[hwif->major] = bs;
- max_sectors[hwif->major] = max_sect;
- /*max_readahead[hwif->major] = max_ra;*/
- for (unit = 0; unit < minors; ++unit) {
- *bs++ = BLOCK_SIZE;
- /*
- * IDE can do up to 128K per request == 256
- */
- *max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : 128);
- /* *max_ra++ = vm_max_readahead; */
- }
-
- for (unit = 0; unit < units; ++unit)
- hwif->drives[unit].part = &gd->part[unit << PARTN_BITS];
-
- gd->major = hwif->major; /* our major device number */
- gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */
- gd->minor_shift = PARTN_BITS; /* num bits for partitions */
- gd->max_p = 1<<PARTN_BITS; /* 1 + max partitions / drive */
- gd->nr_real = units; /* current num real drives */
- gd->real_devices= hwif; /* ptr to internal data */
- gd->next = NULL; /* linked list of major devs */
- gd->fops = ide_fops; /* file operations */
- gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
- if (gd->flags)
- memset (gd->flags, 0, sizeof *gd->flags * units);
-#ifdef DEVFS_MUST_DIE
- gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
- if (gd->de_arr)
- memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
-#endif
-
- hwif->gd = gd;
- add_gendisk(gd);
-
- for (unit = 0; unit < units; ++unit) {
-#if 1
- char name[64];
- ide_add_generic_settings(hwif->drives + unit);
- hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit);
- sprintf (name, "host%d/bus%d/target%d/lun%d",
- (hwif->channel && hwif->mate) ?
- hwif->mate->index : hwif->index,
- hwif->channel, unit, hwif->drives[unit].lun);
-#ifdef DEVFS_MUST_DIE
- if (hwif->drives[unit].present)
- hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
-#endif
-#else
- if (hwif->drives[unit].present) {
- char name[64];
-
- ide_add_generic_settings(hwif->drives + unit);
- hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit);
- sprintf (name, "host%d/bus%d/target%d/lun%d",
- (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index,
- hwif->channel, unit, hwif->drives[unit].lun);
- hwif->drives[unit].de =
- devfs_mk_dir (ide_devfs_handle, name, NULL);
- }
-#endif
- }
- return;
-
-#if 0
-err_kmalloc_max_ra:
- kfree(max_sect);
-#endif
-err_kmalloc_max_sect:
- kfree(bs);
-err_kmalloc_bs:
- kfree(gd->part);
-err_kmalloc_gd_part:
- kfree(gd->sizes);
-err_kmalloc_gd_sizes:
- kfree(gd);
-err_kmalloc_gd:
- printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n");
- return;
-}
-
-static int hwif_init (ide_hwif_t *hwif)
-{
- if (!hwif->present)
- return 0;
- if (!hwif->irq) {
- if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
- {
- printk("%s: DISABLED, NO IRQ\n", hwif->name);
- return (hwif->present = 0);
- }
- }
-#ifdef CONFIG_BLK_DEV_HD
- if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
- printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name);
- return (hwif->present = 0);
- }
-#endif /* CONFIG_BLK_DEV_HD */
-
- hwif->present = 0; /* we set it back to 1 if all is ok below */
-
-#ifdef DEVFS_MUST_DIE
- if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) {
- printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major);
- return (hwif->present = 0);
- }
-#endif
-
- if (init_irq(hwif)) {
- int i = hwif->irq;
- /*
- * It failed to initialise. Find the default IRQ for
- * this port and try that.
- */
- if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
- printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i);
- (void) unregister_blkdev (hwif->major, hwif->name);
- return (hwif->present = 0);
- }
- if (init_irq(hwif)) {
- printk("%s: probed IRQ %d and default IRQ %d failed.\n",
- hwif->name, i, hwif->irq);
- (void) unregister_blkdev (hwif->major, hwif->name);
- return (hwif->present = 0);
- }
- printk("%s: probed IRQ %d failed, using default.\n",
- hwif->name, hwif->irq);
- }
-
- init_gendisk(hwif);
- blk_dev[hwif->major].data = hwif;
- blk_dev[hwif->major].queue = ide_get_queue;
-#if 0
- read_ahead[hwif->major] = 8; /* (4kB) */
-#endif
- hwif->present = 1; /* success */
-
-#if (DEBUG_SPINLOCK > 0)
-{
- static int done = 0;
- if (!done++)
- printk("io_request_lock is %p\n", &io_request_lock); /* FIXME */
-}
-#endif
- return hwif->present;
-}
-
-void export_ide_init_queue (ide_drive_t *drive)
-{
- ide_init_queue(drive);
-}
-
-byte export_probe_for_drive (ide_drive_t *drive)
-{
- return probe_for_drive(drive);
-}
-
-EXPORT_SYMBOL(export_ide_init_queue);
-EXPORT_SYMBOL(export_probe_for_drive);
-
-int ideprobe_init (void);
-static ide_module_t ideprobe_module = {
- IDE_PROBE_MODULE,
- ideprobe_init,
- NULL
-};
-
-int ideprobe_init (void)
-{
- unsigned int index;
- int probe[MAX_HWIFS];
-
- if (IDE_PROBE_TRACE)
- {
- printk (KERN_ALERT "ide-probe::ideprobe_init\n");
- }
-
- MOD_INC_USE_COUNT;
- memset(probe, 0, MAX_HWIFS * sizeof(int));
- for (index = 0; index < MAX_HWIFS; ++index)
- probe[index] = !ide_hwifs[index].present;
-
- /*
- * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports
- */
- for (index = 0; index < MAX_HWIFS; ++index)
- if (probe[index])
- probe_hwif(&ide_hwifs[index]);
- for (index = 0; index < MAX_HWIFS; ++index)
- if (probe[index])
- hwif_init(&ide_hwifs[index]);
- if (!ide_probe)
- ide_probe = &ideprobe_module;
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-#ifdef MODULE
-extern int (*ide_xlate_1024_hook)(kdev_t, int, int, const char *);
-
-int init_module (void)
-{
- unsigned int index;
-
- for (index = 0; index < MAX_HWIFS; ++index)
- ide_unregister(index);
- ideprobe_init();
- create_proc_ide_interfaces();
- ide_xlate_1024_hook = ide_xlate_1024;
- return 0;
-}
-
-void cleanup_module (void)
-{
- ide_probe = NULL;
- ide_xlate_1024_hook = 0;
-}
-MODULE_LICENSE("GPL");
-#endif /* MODULE */
diff --git a/xen/drivers/ide/ide-taskfile.c b/xen/drivers/ide/ide-taskfile.c
deleted file mode 100644
index 2cfeaf6ba6..0000000000
--- a/xen/drivers/ide/ide-taskfile.c
+++ /dev/null
@@ -1,1733 +0,0 @@
-/*
- * linux/drivers/ide/ide-taskfile.c Version 0.20 Oct 11, 2000
- *
- * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
- * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
- *
- * May be copied or modified under the terms of the GNU General Public License
- *
- * IDE_DEBUG(__LINE__);
- */
-
-#include <xen/config.h>
-#define __NO_VERSION__
-#include <xen/module.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/timer.h>
-#include <xen/mm.h>
-#include <xen/interrupt.h>
-#include <xen/major.h>
-#include <xen/errno.h>
-#include <xen/genhd.h>
-#include <xen/blkpg.h>
-#include <xen/slab.h>
-#include <xen/pci.h>
-#include <xen/delay.h>
-#include <xen/hdreg.h>
-#include <xen/ide.h>
-
-#include <asm/domain_page.h>
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-
-#ifdef CONFIG_IDE_TASKFILE_IO
-# define __TASKFILE__IO
-#else /* CONFIG_IDE_TASKFILE_IO */
-# undef __TASKFILE__IO
-#endif /* CONFIG_IDE_TASKFILE_IO */
-
-#define DEBUG_TASKFILE 0 /* unset when fixed */
-
-#if DEBUG_TASKFILE
-#define DTF(x...) printk(##x)
-#else
-#define DTF(x...)
-#endif
-
-inline u32 task_read_24 (ide_drive_t *drive)
-{
- return (IN_BYTE(IDE_HCYL_REG)<<16) |
- (IN_BYTE(IDE_LCYL_REG)<<8) |
- IN_BYTE(IDE_SECTOR_REG);
-}
-
-static void ata_bswap_data (void *buffer, int wcount)
-{
- u16 *p = buffer;
-
- while (wcount--) {
- *p = *p << 8 | *p >> 8; p++;
- *p = *p << 8 | *p >> 8; p++;
- }
-}
-
-#if SUPPORT_VLB_SYNC
-/*
- * Some localbus EIDE interfaces require a special access sequence
- * when using 32-bit I/O instructions to transfer data. We call this
- * the "vlb_sync" sequence, which consists of three successive reads
- * of the sector count register location, with interrupts disabled
- * to ensure that the reads all happen together.
- */
-static inline void task_vlb_sync (ide_ioreg_t port) {
- (void) inb (port);
- (void) inb (port);
- (void) inb (port);
-}
-#endif /* SUPPORT_VLB_SYNC */
-
-/*
- * This is used for most PIO data transfers *from* the IDE interface
- */
-void ata_input_data (ide_drive_t *drive, void *vbuffer, unsigned int wcount)
-{
- byte io_32bit = drive->io_32bit;
-
- void *buffer = map_domain_mem(virt_to_phys(vbuffer));
-
- if (io_32bit) {
-#if SUPPORT_VLB_SYNC
- if (io_32bit & 2) {
- unsigned long flags;
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only */
- task_vlb_sync(IDE_NSECTOR_REG);
- insl(IDE_DATA_REG, buffer, wcount);
- __restore_flags(flags); /* local CPU only */
- } else
-#endif /* SUPPORT_VLB_SYNC */
- insl(IDE_DATA_REG, buffer, wcount);
- } else {
-#if SUPPORT_SLOW_DATA_PORTS
- if (drive->slow) {
- unsigned short *ptr = (unsigned short *) buffer;
- while (wcount--) {
- *ptr++ = inw_p(IDE_DATA_REG);
- *ptr++ = inw_p(IDE_DATA_REG);
- }
- } else
-#endif /* SUPPORT_SLOW_DATA_PORTS */
- insw(IDE_DATA_REG, buffer, wcount<<1);
- }
-
- unmap_domain_mem(buffer);
-}
-
-/*
- * This is used for most PIO data transfers *to* the IDE interface
- */
-void ata_output_data (ide_drive_t *drive, void *vbuffer, unsigned int wcount)
-{
- byte io_32bit = drive->io_32bit;
-
- void *buffer = map_domain_mem(virt_to_phys(vbuffer));
-
- if (io_32bit) {
-#if SUPPORT_VLB_SYNC
- if (io_32bit & 2) {
- unsigned long flags;
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only */
- task_vlb_sync(IDE_NSECTOR_REG);
- outsl(IDE_DATA_REG, buffer, wcount);
- __restore_flags(flags); /* local CPU only */
- } else
-#endif /* SUPPORT_VLB_SYNC */
- outsl(IDE_DATA_REG, buffer, wcount);
- } else {
-#if SUPPORT_SLOW_DATA_PORTS
- if (drive->slow) {
- unsigned short *ptr = (unsigned short *) buffer;
- while (wcount--) {
- outw_p(*ptr++, IDE_DATA_REG);
- outw_p(*ptr++, IDE_DATA_REG);
- }
- } else
-#endif /* SUPPORT_SLOW_DATA_PORTS */
- outsw(IDE_DATA_REG, buffer, wcount<<1);
- }
-
- unmap_domain_mem(buffer);
-}
-
-
-static inline void taskfile_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
-{
- ata_input_data(drive, buffer, wcount);
- if (drive->bswap)
- ata_bswap_data(buffer, wcount);
-}
-
-static inline void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
-{
- if (drive->bswap) {
- ata_bswap_data(buffer, wcount);
- ata_output_data(drive, buffer, wcount);
- ata_bswap_data(buffer, wcount);
- } else {
- ata_output_data(drive, buffer, wcount);
- }
-}
-
-ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
-{
- task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
- hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
- struct hd_driveid *id = drive->id;
- byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
-
- printk(KERN_ALERT "do_rw_taskfile\n");
-
- /* (ks/hs): Moved to start, do not use for multiple out commands */
- if (task->handler != task_mulout_intr) {
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
- SELECT_MASK(HWIF(drive), drive, 0);
- }
-
- if ((id->command_set_2 & 0x0400) &&
- (id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- OUT_BYTE(hobfile->feature, IDE_FEATURE_REG);
- OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG);
- OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG);
- OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG);
- OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG);
- }
-
- OUT_BYTE(taskfile->feature, IDE_FEATURE_REG);
- OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG);
- /* refers to number of sectors to transfer */
- OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG);
- /* refers to sector offset or start sector */
- OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG);
- OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG);
-
- OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
- if (task->handler != NULL) {
-#if 0
- ide_set_handler (drive, task->handler, WAIT_CMD, NULL);
- OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
- /*
- * warning check for race between handler and prehandler for
- * writing first block of data. however since we are well
- * inside the boundaries of the seek, we should be okay.
- */
- if (task->prehandler != NULL) {
- return task->prehandler(drive, task->rq);
- }
-#else
- ide_startstop_t startstop;
-
- ide_set_handler (drive, task->handler, WAIT_CMD, NULL);
- OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
-
- if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
- printk(KERN_ERR "%s: no DRQ after issuing %s\n",
- drive->name,
- drive->mult_count ? "MULTWRITE" : "WRITE");
- return startstop;
- }
- /* (ks/hs): Fixed Multi Write */
- if ((taskfile->command != WIN_MULTWRITE) &&
- (taskfile->command != WIN_MULTWRITE_EXT)) {
- struct request *rq = HWGROUP(drive)->rq;
- /* For Write_sectors we need to stuff the first sector */
- taskfile_output_data(drive, rq->buffer, SECTOR_WORDS);
- rq->current_nr_sectors--;
- } else {
- /* Stuff first sector(s) by implicitly calling the handler */
- if (!(drive_is_ready(drive))) {
- /* FIXME: Replace hard-coded 100, error handling? */
- int i;
- for (i=0; i<100; i++) {
- if (drive_is_ready(drive))
- break;
- }
- }
- return task->handler(drive);
- }
-#endif
- } else {
- /* for dma commands we down set the handler */
- if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive)));
- }
-
- return ide_started;
-}
-
-void do_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, ide_handler_t *handler)
-{
- struct hd_driveid *id = drive->id;
- byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
-
- /* (ks/hs): Moved to start, do not use for multiple out commands */
- if (*handler != task_mulout_intr) {
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
- SELECT_MASK(HWIF(drive), drive, 0);
- }
-
- if ((id->command_set_2 & 0x0400) &&
- (id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- OUT_BYTE(hobfile->feature, IDE_FEATURE_REG);
- OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG);
- OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG);
- OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG);
- OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG);
- }
-
- OUT_BYTE(taskfile->feature, IDE_FEATURE_REG);
- OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG);
- /* refers to number of sectors to transfer */
- OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG);
- /* refers to sector offset or start sector */
- OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG);
- OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG);
-
- OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
- if (handler != NULL) {
- ide_set_handler (drive, handler, WAIT_CMD, NULL);
- OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
- } else {
- /* for dma commands we down set the handler */
- if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive)));
- }
-}
-
-#if 0
-ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
-{
- task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
- hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
- struct hd_driveid *id = drive->id;
-
- /*
- * (KS) Check taskfile in/out flags.
- * If set, then execute as it is defined.
- * If not set, then define default settings.
- * The default values are:
- * write and read all taskfile registers (except data)
- * write and read the hob registers (sector,nsector,lcyl,hcyl)
- */
- if (task->tf_out_flags.all == 0) {
- task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS;
- if ((id->command_set_2 & 0x0400) &&
- (id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- task->tf_out_flags.all != (IDE_HOB_STD_OUT_FLAGS << 8);
- }
- }
-
- if (task->tf_in_flags.all == 0) {
- task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
- if ((id->command_set_2 & 0x0400) &&
- (id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- task->tf_in_flags.all != (IDE_HOB_STD_IN_FLAGS << 8);
- }
- }
-
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
- SELECT_MASK(HWIF(drive), drive, 0);
-
- if (task->tf_out_flags.b.data) {
- unsigned short data = taskfile->data + (hobfile->data << 8);
- OUT_WORD (data, IDE_DATA_REG);
- }
-
- /* (KS) send hob registers first */
- if (task->tf_out_flags.b.nsector_hob)
- OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG);
- if (task->tf_out_flags.b.sector_hob)
- OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG);
- if (task->tf_out_flags.b.lcyl_hob)
- OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG);
- if (task->tf_out_flags.b.hcyl_hob)
- OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG);
-
-
- /* (KS) Send now the standard registers */
- if (task->tf_out_flags.b.error_feature)
- OUT_BYTE(taskfile->feature, IDE_FEATURE_REG);
- /* refers to number of sectors to transfer */
- if (task->tf_out_flags.b.nsector)
- OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG);
- /* refers to sector offset or start sector */
- if (task->tf_out_flags.b.sector)
- OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG);
- if (task->tf_out_flags.b.lcyl)
- OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG);
- if (task->tf_out_flags.b.hcyl)
- OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG);
-
- /*
- * (KS) Do not modify the specified taskfile. We want to have a
- * universal pass through, so we must execute ALL specified values.
- *
- * (KS) The drive head register is mandatory.
- * Don't care about the out flags !
- */
- OUT_BYTE(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
- if (task->handler != NULL) {
-#if 0
- ide_set_handler (drive, task->handler, WAIT_CMD, NULL);
- OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
- /*
- * warning check for race between handler and prehandler for
- * writing first block of data. however since we are well
- * inside the boundaries of the seek, we should be okay.
- */
- if (task->prehandler != NULL) {
- return task->prehandler(drive, task->rq);
- }
-#else
- ide_startstop_t startstop;
-
- ide_set_handler (drive, task->handler, WAIT_CMD, NULL);
-
- /*
- * (KS) The drive command register is also mandatory.
- * Don't care about the out flags !
- */
- OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
-
- if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
- printk(KERN_ERR "%s: no DRQ after issuing %s\n",
- drive->name,
- drive->mult_count ? "MULTWRITE" : "WRITE");
- return startstop;
- }
- /* (ks/hs): Fixed Multi Write */
- if ((taskfile->command != WIN_MULTWRITE) &&
- (taskfile->command != WIN_MULTWRITE_EXT)) {
- struct request *rq = HWGROUP(drive)->rq;
- /* For Write_sectors we need to stuff the first sector */
- taskfile_output_data(drive, rq->buffer, SECTOR_WORDS);
- rq->current_nr_sectors--;
- } else {
- /* Stuff first sector(s) by implicitly calling the handler */
- if (!(drive_is_ready(drive))) {
- /* FIXME: Replace hard-coded 100, error handling? */
- int i;
- for (i=0; i<100; i++) {
- if (drive_is_ready(drive))
- break;
- }
- }
- return task->handler(drive);
- }
-#endif
- } else {
- /* for dma commands we down set the handler */
- if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive)));
- }
-
- return ide_started;
-}
-#endif
-
-#if 0
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
- */
-byte taskfile_dump_status (ide_drive_t *drive, const char *msg, byte stat)
-{
- unsigned long flags;
- byte err = 0;
-
- __save_flags (flags); /* local CPU only */
- ide__sti(); /* local CPU only */
- printk("%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
- printk(" { ");
- if (stat & BUSY_STAT)
- printk("Busy ");
- else {
- if (stat & READY_STAT) printk("DriveReady ");
- if (stat & WRERR_STAT) printk("DeviceFault ");
- if (stat & SEEK_STAT) printk("SeekComplete ");
- if (stat & DRQ_STAT) printk("DataRequest ");
- if (stat & ECC_STAT) printk("CorrectedError ");
- if (stat & INDEX_STAT) printk("Index ");
- if (stat & ERR_STAT) printk("Error ");
- }
- printk("}");
-#endif /* FANCY_STATUS_DUMPS */
- printk("\n");
- if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
- err = GET_ERR();
- printk("%s: %s: error=0x%02x", drive->name, msg, err);
-#if FANCY_STATUS_DUMPS
- if (drive->media == ide_disk) {
- printk(" { ");
- if (err & ABRT_ERR) printk("DriveStatusError ");
- if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector ");
- if (err & ECC_ERR) printk("UncorrectableError ");
- if (err & ID_ERR) printk("SectorIdNotFound ");
- if (err & TRK0_ERR) printk("TrackZeroNotFound ");
- if (err & MARK_ERR) printk("AddrMarkNotFound ");
- printk("}");
- if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
- if ((drive->id->command_set_2 & 0x0400) &&
- (drive->id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- __u64 sectors = 0;
- u32 low = 0, high = 0;
- low = task_read_24(drive);
- OUT_BYTE(0x80, IDE_CONTROL_REG);
- high = task_read_24(drive);
- sectors = ((__u64)high << 24) | low;
- printk(", LBAsect=%lld", sectors);
- } else {
- byte cur = IN_BYTE(IDE_SELECT_REG);
- if (cur & 0x40) { /* using LBA? */
- printk(", LBAsect=%ld", (unsigned long)
- ((cur&0xf)<<24)
- |(IN_BYTE(IDE_HCYL_REG)<<16)
- |(IN_BYTE(IDE_LCYL_REG)<<8)
- | IN_BYTE(IDE_SECTOR_REG));
- } else {
- printk(", CHS=%d/%d/%d",
- (IN_BYTE(IDE_HCYL_REG)<<8) +
- IN_BYTE(IDE_LCYL_REG),
- cur & 0xf,
- IN_BYTE(IDE_SECTOR_REG));
- }
- }
- if (HWGROUP(drive)->rq)
- printk(", sector=%llu", (__u64) HWGROUP(drive)->rq->sector);
- }
- }
-#endif /* FANCY_STATUS_DUMPS */
- printk("\n");
- }
- __restore_flags (flags); /* local CPU only */
- return err;
-}
-
-/*
- * Clean up after success/failure of an explicit taskfile operation.
- */
-void ide_end_taskfile (ide_drive_t *drive, byte stat, byte err)
-{
- unsigned long flags;
- struct request *rq;
- ide_task_t *args;
- task_ioreg_t command;
-
- spin_lock_irqsave(&io_request_lock, flags);
- rq = HWGROUP(drive)->rq;
- spin_unlock_irqrestore(&io_request_lock, flags);
- args = (ide_task_t *) rq->special;
-
- command = args->tfRegister[IDE_COMMAND_OFFSET];
-
- rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
-
- args->tfRegister[IDE_ERROR_OFFSET] = err;
- args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG);
- args->tfRegister[IDE_SECTOR_OFFSET] = IN_BYTE(IDE_SECTOR_REG);
- args->tfRegister[IDE_LCYL_OFFSET] = IN_BYTE(IDE_LCYL_REG);
- args->tfRegister[IDE_HCYL_OFFSET] = IN_BYTE(IDE_HCYL_REG);
- args->tfRegister[IDE_SELECT_OFFSET] = IN_BYTE(IDE_SELECT_REG);
- args->tfRegister[IDE_STATUS_OFFSET] = stat;
- if ((drive->id->command_set_2 & 0x0400) &&
- (drive->id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
- args->hobRegister[IDE_FEATURE_OFFSET_HOB] = IN_BYTE(IDE_FEATURE_REG);
- args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = IN_BYTE(IDE_NSECTOR_REG);
- args->hobRegister[IDE_SECTOR_OFFSET_HOB] = IN_BYTE(IDE_SECTOR_REG);
- args->hobRegister[IDE_LCYL_OFFSET_HOB] = IN_BYTE(IDE_LCYL_REG);
- args->hobRegister[IDE_HCYL_OFFSET_HOB] = IN_BYTE(IDE_HCYL_REG);
- }
-
-/* taskfile_settings_update(drive, args, command); */
-
- spin_lock_irqsave(&io_request_lock, flags);
- blkdev_dequeue_request(rq);
- HWGROUP(drive)->rq = NULL;
- end_that_request_last(rq);
- spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-/*
- * try_to_flush_leftover_data() is invoked in response to a drive
- * unexpectedly having its DRQ_STAT bit set. As an alternative to
- * resetting the drive, this routine tries to clear the condition
- * by read a sector's worth of data from the drive. Of course,
- * this may not help if the drive is *waiting* for data from *us*.
- */
-void task_try_to_flush_leftover_data (ide_drive_t *drive)
-{
- int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS;
-
- if (drive->media != ide_disk)
- return;
- while (i > 0) {
- u32 buffer[16];
- unsigned int wcount = (i > 16) ? 16 : i;
- i -= wcount;
- taskfile_input_data (drive, buffer, wcount);
- }
-}
-
-/*
- * taskfile_error() takes action based on the error returned by the drive.
- */
-ide_startstop_t taskfile_error (ide_drive_t *drive, const char *msg, byte stat)
-{
- struct request *rq;
- byte err;
-
- err = taskfile_dump_status(drive, msg, stat);
- if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
- return ide_stopped;
- /* retry only "normal" I/O: */
- if (rq->cmd == IDE_DRIVE_TASKFILE) {
- rq->errors = 1;
- ide_end_taskfile(drive, stat, err);
- return ide_stopped;
- }
- if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */
- rq->errors |= ERROR_RESET;
- } else {
- if (drive->media == ide_disk && (stat & ERR_STAT)) {
- /* err has different meaning on cdrom and tape */
- if (err == ABRT_ERR) {
- if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY)
- return ide_stopped; /* some newer drives don't support WIN_SPECIFY */
- } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) {
- drive->crc_count++; /* UDMA crc error -- just retry the operation */
- } else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */
- rq->errors = ERROR_MAX;
- else if (err & TRK0_ERR) /* help it find track zero */
- rq->errors |= ERROR_RECAL;
- }
- if ((stat & DRQ_STAT) && rq->cmd != WRITE)
- task_try_to_flush_leftover_data(drive);
- }
- if (GET_STAT() & (BUSY_STAT|DRQ_STAT))
- OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */
-
- if (rq->errors >= ERROR_MAX) {
- if (drive->driver != NULL)
- DRIVER(drive)->end_request(0, HWGROUP(drive));
- else
- ide_end_request(0, HWGROUP(drive));
- } else {
- if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
- ++rq->errors;
- return ide_do_reset(drive);
- }
- if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
- drive->special.b.recalibrate = 1;
- ++rq->errors;
- }
- return ide_stopped;
-}
-#endif
-
-/*
- * Handler for special commands without a data phase from ide-disk
- */
-
-/*
- * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
- */
-ide_startstop_t set_multmode_intr (ide_drive_t *drive)
-{
- byte stat;
-
- if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT)) {
- drive->mult_count = drive->mult_req;
- } else {
- drive->mult_req = drive->mult_count = 0;
- drive->special.b.recalibrate = 1;
- (void) ide_dump_status(drive, "set_multmode", stat);
- }
- return ide_stopped;
-}
-
-/*
- * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
- */
-ide_startstop_t set_geometry_intr (ide_drive_t *drive)
-{
- byte stat;
-
- if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT))
- return ide_stopped;
-
- if (stat & (ERR_STAT|DRQ_STAT))
- return ide_error(drive, "set_geometry_intr", stat);
-
- ide_set_handler(drive, &set_geometry_intr, WAIT_CMD, NULL);
- return ide_started;
-}
-
-/*
- * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
- */
-ide_startstop_t recal_intr (ide_drive_t *drive)
-{
- byte stat = GET_STAT();
-
- if (!OK_STAT(stat,READY_STAT,BAD_STAT))
- return ide_error(drive, "recal_intr", stat);
- return ide_stopped;
-}
-
-/*
- * Handler for commands without a data phase
- */
-ide_startstop_t task_no_data_intr (ide_drive_t *drive)
-{
- ide_task_t *args = HWGROUP(drive)->rq->special;
- byte stat = GET_STAT();
-
- ide__sti(); /* local CPU only */
-
- if (!OK_STAT(stat, READY_STAT, BAD_STAT))
- return ide_error(drive, "task_no_data_intr", stat); /* calls ide_end_drive_cmd */
-
- if (args)
- ide_end_drive_cmd (drive, stat, GET_ERR());
-
- return ide_stopped;
-}
-
-/*
- * Handler for command with PIO data-in phase
- */
-ide_startstop_t task_in_intr (ide_drive_t *drive)
-{
- byte stat = GET_STAT();
- byte io_32bit = drive->io_32bit;
- struct request *rq = HWGROUP(drive)->rq;
- char *pBuf = NULL;
-
- if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
- if (stat & (ERR_STAT|DRQ_STAT)) {
- return ide_error(drive, "task_in_intr", stat);
- }
- if (!(stat & BUSY_STAT)) {
- DTF("task_in_intr to Soon wait for next interrupt\n");
- ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- }
- DTF("stat: %02x\n", stat);
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
- DTF("Read: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors);
-
- drive->io_32bit = 0;
- taskfile_input_data(drive, pBuf, SECTOR_WORDS);
- drive->io_32bit = io_32bit;
-
- if (--rq->current_nr_sectors <= 0) {
- /* (hs): swapped next 2 lines */
- DTF("Request Ended stat: %02x\n", GET_STAT());
- ide_end_request(1, HWGROUP(drive));
- } else {
- ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- return ide_stopped;
-}
-
-#undef ALTSTAT_SCREW_UP
-
-#ifdef ALTSTAT_SCREW_UP
-/*
- * (ks/hs): Poll Alternate Status Register to ensure
- * that drive is not busy.
- */
-byte altstat_multi_busy (ide_drive_t *drive, byte stat, const char *msg)
-{
- int i;
-
- DTF("multi%s: ASR = %x\n", msg, stat);
- if (stat & BUSY_STAT) {
- /* (ks/hs): FIXME: Replace hard-coded 100, error handling? */
- for (i=0; i<100; i++) {
- stat = GET_ALTSTAT();
- if ((stat & BUSY_STAT) == 0)
- break;
- }
- }
- /*
- * (ks/hs): Read Status AFTER Alternate Status Register
- */
- return(GET_STAT());
-}
-
-/*
- * (ks/hs): Poll Alternate status register to wait for drive
- * to become ready for next transfer
- */
-byte altstat_multi_poll (ide_drive_t *drive, byte stat, const char *msg)
-{
- /* (ks/hs): FIXME: Error handling, time-out? */
- while (stat & BUSY_STAT)
- stat = GET_ALTSTAT();
- DTF("multi%s: nsect=1, ASR = %x\n", msg, stat);
- return(GET_STAT()); /* (ks/hs): Clear pending IRQ */
-}
-#endif /* ALTSTAT_SCREW_UP */
-
-/*
- * Handler for command with Read Multiple
- */
-ide_startstop_t task_mulin_intr (ide_drive_t *drive)
-{
- unsigned int msect, nsect;
-
-#ifdef ALTSTAT_SCREW_UP
- byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "read");
-#else
- byte stat = GET_STAT();
-#endif /* ALTSTAT_SCREW_UP */
-
- byte io_32bit = drive->io_32bit;
- struct request *rq = HWGROUP(drive)->rq;
- char *pBuf = NULL;
-
- if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
- if (stat & (ERR_STAT|DRQ_STAT)) {
- return ide_error(drive, "task_mulin_intr", stat);
- }
- /* no data yet, so wait for another interrupt */
- ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL);
- return ide_started;
- }
-
- /* (ks/hs): Fixed Multi-Sector transfer */
- msect = drive->mult_count;
-
-#ifdef ALTSTAT_SCREW_UP
- /*
- * Screw the request we do not support bad data-phase setups!
- * Either read and learn the ATA standard or crash yourself!
- */
- if (!msect) {
- /*
- * (ks/hs): Drive supports multi-sector transfer,
- * drive->mult_count was not set
- */
- nsect = 1;
- while (rq->current_nr_sectors) {
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
- DTF("Multiread: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors);
- drive->io_32bit = 0;
- taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
- drive->io_32bit = io_32bit;
- rq->errors = 0;
- rq->current_nr_sectors -= nsect;
- stat = altstat_multi_poll(drive, GET_ALTSTAT(), "read");
- }
- ide_end_request(1, HWGROUP(drive));
- return ide_stopped;
- }
-#endif /* ALTSTAT_SCREW_UP */
-
- nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors;
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
-
- DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
- pBuf, nsect, rq->current_nr_sectors);
- drive->io_32bit = 0;
- taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
- drive->io_32bit = io_32bit;
- rq->errors = 0;
- rq->current_nr_sectors -= nsect;
- if (rq->current_nr_sectors != 0) {
- ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- ide_end_request(1, HWGROUP(drive));
- return ide_stopped;
-}
-
-ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
-{
- ide_task_t *args = rq->special;
- ide_startstop_t startstop;
-
- if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
- printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name, drive->mult_count ? "MULTWRITE" : "WRITE");
- return startstop;
- }
-
- /* (ks/hs): Fixed Multi Write */
- if ((args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE) &&
- (args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE_EXT)) {
- /* For Write_sectors we need to stuff the first sector */
- taskfile_output_data(drive, rq->buffer, SECTOR_WORDS);
- rq->current_nr_sectors--;
- return ide_started;
- } else {
- /*
- * (ks/hs): Stuff the first sector(s)
- * by implicitly calling the handler
- */
- if (!(drive_is_ready(drive))) {
- int i;
- /*
- * (ks/hs): FIXME: Replace hard-coded
- * 100, error handling?
- */
- for (i=0; i<100; i++) {
- if (drive_is_ready(drive))
- break;
- }
- }
- return args->handler(drive);
- }
- return ide_started;
-}
-
-/*
- * Handler for command with PIO data-out phase
- */
-ide_startstop_t task_out_intr (ide_drive_t *drive)
-{
- byte stat = GET_STAT();
- byte io_32bit = drive->io_32bit;
- struct request *rq = HWGROUP(drive)->rq;
- char *pBuf = NULL;
-
- if (!rq->current_nr_sectors) {
- ide_end_request(1, HWGROUP(drive));
- return ide_stopped;
- }
-
- if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) {
- return ide_error(drive, "task_out_intr", stat);
- }
- if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) {
- rq = HWGROUP(drive)->rq;
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
- DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors);
- drive->io_32bit = 0;
- taskfile_output_data(drive, pBuf, SECTOR_WORDS);
- drive->io_32bit = io_32bit;
- rq->errors = 0;
- rq->current_nr_sectors--;
- }
-
- if (rq->current_nr_sectors <= 0) {
- ide_end_request(1, HWGROUP(drive));
- } else {
- ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- return ide_stopped;
-}
-
-/*
- * Handler for command write multiple
- * Called directly from execute_drive_cmd for the first bunch of sectors,
- * afterwards only by the ISR
- */
-ide_startstop_t task_mulout_intr (ide_drive_t *drive)
-{
- unsigned int msect, nsect;
-
-#ifdef ALTSTAT_SCREW_UP
- byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "write");
-#else
- byte stat = GET_STAT();
-#endif /* ALTSTAT_SCREW_UP */
-
- byte io_32bit = drive->io_32bit;
- struct request *rq = HWGROUP(drive)->rq;
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- char *pBuf = NULL;
-
- /*
- * (ks/hs): Handle last IRQ on multi-sector transfer,
- * occurs after all data was sent
- */
- if (rq->current_nr_sectors == 0) {
- if (stat & (ERR_STAT|DRQ_STAT))
- return ide_error(drive, "task_mulout_intr", stat);
- ide_end_request(1, HWGROUP(drive));
- return ide_stopped;
- }
-
- if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
- if (stat & (ERR_STAT|DRQ_STAT)) {
- return ide_error(drive, "task_mulout_intr", stat);
- }
- /* no data yet, so wait for another interrupt */
- if (hwgroup->handler == NULL)
- ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
- return ide_started;
- }
-
- /* (ks/hs): See task_mulin_intr */
- msect = drive->mult_count;
-
-#ifdef ALTSTAT_SCREW_UP
- /*
- * Screw the request we do not support bad data-phase setups!
- * Either read and learn the ATA standard or crash yourself!
- */
- if (!msect) {
- nsect = 1;
- while (rq->current_nr_sectors) {
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
- DTF("Multiwrite: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors);
- drive->io_32bit = 0;
- taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
- drive->io_32bit = io_32bit;
- rq->errors = 0;
- rq->current_nr_sectors -= nsect;
- stat = altstat_multi_poll(drive, GET_ALTSTAT(), "write");
- }
- ide_end_request(1, HWGROUP(drive));
- return ide_stopped;
- }
-#endif /* ALTSTAT_SCREW_UP */
-
- nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors;
- pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE);
- DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
- pBuf, nsect, rq->current_nr_sectors);
- drive->io_32bit = 0;
- taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
- drive->io_32bit = io_32bit;
- rq->errors = 0;
- rq->current_nr_sectors -= nsect;
- if (hwgroup->handler == NULL)
- ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
- return ide_started;
-}
-
-/* Called by internal to feature out type of command being called */
-ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
-{
- switch(taskfile->command) {
- /* IDE_DRIVE_TASK_RAW_WRITE */
- case CFA_WRITE_MULTI_WO_ERASE:
- case WIN_MULTWRITE:
- case WIN_MULTWRITE_EXT:
-// case WIN_WRITEDMA:
-// case WIN_WRITEDMA_QUEUED:
-// case WIN_WRITEDMA_EXT:
-// case WIN_WRITEDMA_QUEUED_EXT:
- /* IDE_DRIVE_TASK_OUT */
- case WIN_WRITE:
- case WIN_WRITE_VERIFY:
- case WIN_WRITE_BUFFER:
- case CFA_WRITE_SECT_WO_ERASE:
- case WIN_DOWNLOAD_MICROCODE:
- return &pre_task_out_intr;
- /* IDE_DRIVE_TASK_OUT */
- case WIN_SMART:
- if (taskfile->feature == SMART_WRITE_LOG_SECTOR)
- return &pre_task_out_intr;
- default:
- break;
- }
- return(NULL);
-}
-
-/* Called by internal to feature out type of command being called */
-ide_handler_t * ide_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
-{
- switch(taskfile->command) {
- case WIN_IDENTIFY:
- case WIN_PIDENTIFY:
- case CFA_TRANSLATE_SECTOR:
- case WIN_READ_BUFFER:
- case WIN_READ:
- case WIN_READ_EXT:
- return &task_in_intr;
- case WIN_SECURITY_DISABLE:
- case WIN_SECURITY_ERASE_UNIT:
- case WIN_SECURITY_SET_PASS:
- case WIN_SECURITY_UNLOCK:
- case WIN_DOWNLOAD_MICROCODE:
- case CFA_WRITE_SECT_WO_ERASE:
- case WIN_WRITE_BUFFER:
- case WIN_WRITE_VERIFY:
- case WIN_WRITE:
- case WIN_WRITE_EXT:
- return &task_out_intr;
- case WIN_MULTREAD:
- case WIN_MULTREAD_EXT:
- return &task_mulin_intr;
- case CFA_WRITE_MULTI_WO_ERASE:
- case WIN_MULTWRITE:
- case WIN_MULTWRITE_EXT:
- return &task_mulout_intr;
- case WIN_SMART:
- switch(taskfile->feature) {
- case SMART_READ_VALUES:
- case SMART_READ_THRESHOLDS:
- case SMART_READ_LOG_SECTOR:
- return &task_in_intr;
- case SMART_WRITE_LOG_SECTOR:
- return &task_out_intr;
- default:
- return &task_no_data_intr;
- }
- case CFA_REQ_EXT_ERROR_CODE:
- case CFA_ERASE_SECTORS:
- case WIN_VERIFY:
- case WIN_VERIFY_EXT:
- case WIN_SEEK:
- return &task_no_data_intr;
- case WIN_SPECIFY:
- return &set_geometry_intr;
- case WIN_RESTORE:
- return &recal_intr;
- case WIN_DIAGNOSE:
- case WIN_FLUSH_CACHE:
- case WIN_FLUSH_CACHE_EXT:
- case WIN_STANDBYNOW1:
- case WIN_STANDBYNOW2:
- case WIN_SLEEPNOW1:
- case WIN_SLEEPNOW2:
- case WIN_SETIDLE1:
- case WIN_CHECKPOWERMODE1:
- case WIN_CHECKPOWERMODE2:
- case WIN_GETMEDIASTATUS:
- case WIN_MEDIAEJECT:
- return &task_no_data_intr;
- case WIN_SETMULT:
- return &set_multmode_intr;
- case WIN_READ_NATIVE_MAX:
- case WIN_SET_MAX:
- case WIN_READ_NATIVE_MAX_EXT:
- case WIN_SET_MAX_EXT:
- case WIN_SECURITY_ERASE_PREPARE:
- case WIN_SECURITY_FREEZE_LOCK:
- case WIN_DOORLOCK:
- case WIN_DOORUNLOCK:
- case WIN_SETFEATURES:
- return &task_no_data_intr;
- case DISABLE_SEAGATE:
- case EXABYTE_ENABLE_NEST:
- return &task_no_data_intr;
-#ifdef CONFIG_BLK_DEV_IDEDMA
- case WIN_READDMA:
- case WIN_IDENTIFY_DMA:
- case WIN_READDMA_QUEUED:
- case WIN_READDMA_EXT:
- case WIN_READDMA_QUEUED_EXT:
- case WIN_WRITEDMA:
- case WIN_WRITEDMA_QUEUED:
- case WIN_WRITEDMA_EXT:
- case WIN_WRITEDMA_QUEUED_EXT:
-#endif
- case WIN_FORMAT:
- case WIN_INIT:
- case WIN_DEVICE_RESET:
- case WIN_QUEUED_SERVICE:
- case WIN_PACKETCMD:
- default:
- return(NULL);
- }
-}
-
-/* Called by ioctl to feature out type of command being called */
-int ide_cmd_type_parser (ide_task_t *args)
-{
- struct hd_drive_task_hdr *taskfile = (struct hd_drive_task_hdr *) args->tfRegister;
- struct hd_drive_hob_hdr *hobfile = (struct hd_drive_hob_hdr *) args->hobRegister;
-
- args->prehandler = ide_pre_handler_parser(taskfile, hobfile);
- args->handler = ide_handler_parser(taskfile, hobfile);
-
- switch(args->tfRegister[IDE_COMMAND_OFFSET]) {
- case WIN_IDENTIFY:
- case WIN_PIDENTIFY:
- return IDE_DRIVE_TASK_IN;
- case CFA_TRANSLATE_SECTOR:
- case WIN_READ:
- case WIN_READ_BUFFER:
- return IDE_DRIVE_TASK_IN;
- case WIN_WRITE:
- case WIN_WRITE_VERIFY:
- case WIN_WRITE_BUFFER:
- case CFA_WRITE_SECT_WO_ERASE:
- case WIN_DOWNLOAD_MICROCODE:
- return IDE_DRIVE_TASK_RAW_WRITE;
- case WIN_MULTREAD:
- return IDE_DRIVE_TASK_IN;
- case CFA_WRITE_MULTI_WO_ERASE:
- case WIN_MULTWRITE:
- return IDE_DRIVE_TASK_RAW_WRITE;
- case WIN_SECURITY_DISABLE:
- case WIN_SECURITY_ERASE_UNIT:
- case WIN_SECURITY_SET_PASS:
- case WIN_SECURITY_UNLOCK:
- return IDE_DRIVE_TASK_OUT;
- case WIN_SMART:
- args->tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
- args->tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
- switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
- case SMART_READ_VALUES:
- case SMART_READ_THRESHOLDS:
- case SMART_READ_LOG_SECTOR:
- return IDE_DRIVE_TASK_IN;
- case SMART_WRITE_LOG_SECTOR:
- return IDE_DRIVE_TASK_OUT;
- default:
- return IDE_DRIVE_TASK_NO_DATA;
- }
-#ifdef CONFIG_BLK_DEV_IDEDMA
- case WIN_READDMA:
- case WIN_IDENTIFY_DMA:
- case WIN_READDMA_QUEUED:
- case WIN_READDMA_EXT:
- case WIN_READDMA_QUEUED_EXT:
- return IDE_DRIVE_TASK_IN;
- case WIN_WRITEDMA:
- case WIN_WRITEDMA_QUEUED:
- case WIN_WRITEDMA_EXT:
- case WIN_WRITEDMA_QUEUED_EXT:
- return IDE_DRIVE_TASK_RAW_WRITE;
-#endif
- case WIN_SETFEATURES:
- switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
- case SETFEATURES_XFER:
- return IDE_DRIVE_TASK_SET_XFER;
- case SETFEATURES_DIS_DEFECT:
- case SETFEATURES_EN_APM:
- case SETFEATURES_DIS_MSN:
- case SETFEATURES_EN_RI:
- case SETFEATURES_EN_SI:
- case SETFEATURES_DIS_RPOD:
- case SETFEATURES_DIS_WCACHE:
- case SETFEATURES_EN_DEFECT:
- case SETFEATURES_DIS_APM:
- case SETFEATURES_EN_MSN:
- case SETFEATURES_EN_RLA:
- case SETFEATURES_PREFETCH:
- case SETFEATURES_EN_RPOD:
- case SETFEATURES_DIS_RI:
- case SETFEATURES_DIS_SI:
- default:
- return IDE_DRIVE_TASK_NO_DATA;
- }
- case WIN_NOP:
- case CFA_REQ_EXT_ERROR_CODE:
- case CFA_ERASE_SECTORS:
- case WIN_VERIFY:
- case WIN_VERIFY_EXT:
- case WIN_SEEK:
- case WIN_SPECIFY:
- case WIN_RESTORE:
- case WIN_DIAGNOSE:
- case WIN_FLUSH_CACHE:
- case WIN_FLUSH_CACHE_EXT:
- case WIN_STANDBYNOW1:
- case WIN_STANDBYNOW2:
- case WIN_SLEEPNOW1:
- case WIN_SLEEPNOW2:
- case WIN_SETIDLE1:
- case DISABLE_SEAGATE:
- case WIN_CHECKPOWERMODE1:
- case WIN_CHECKPOWERMODE2:
- case WIN_GETMEDIASTATUS:
- case WIN_MEDIAEJECT:
- case WIN_SETMULT:
- case WIN_READ_NATIVE_MAX:
- case WIN_SET_MAX:
- case WIN_READ_NATIVE_MAX_EXT:
- case WIN_SET_MAX_EXT:
- case WIN_SECURITY_ERASE_PREPARE:
- case WIN_SECURITY_FREEZE_LOCK:
- case EXABYTE_ENABLE_NEST:
- case WIN_DOORLOCK:
- case WIN_DOORUNLOCK:
- return IDE_DRIVE_TASK_NO_DATA;
- case WIN_FORMAT:
- case WIN_INIT:
- case WIN_DEVICE_RESET:
- case WIN_QUEUED_SERVICE:
- case WIN_PACKETCMD:
- default:
- return IDE_DRIVE_TASK_INVALID;
- }
-}
-
-/*
- * This function is intended to be used prior to invoking ide_do_drive_cmd().
- */
-void ide_init_drive_taskfile (struct request *rq)
-{
- memset(rq, 0, sizeof(*rq));
- rq->cmd = IDE_DRIVE_TASK_NO_DATA;
-}
-
-/*
- * This is kept for internal use only !!!
- * This is an internal call and nobody in user-space has a damn
- * reason to call this taskfile.
- *
- * ide_raw_taskfile is the one that user-space executes.
- */
-int ide_wait_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf)
-{
- struct request rq;
- ide_task_t args;
-
- memset(&args, 0, sizeof(ide_task_t));
-
- args.tfRegister[IDE_DATA_OFFSET] = taskfile->data;
- args.tfRegister[IDE_FEATURE_OFFSET] = taskfile->feature;
- args.tfRegister[IDE_NSECTOR_OFFSET] = taskfile->sector_count;
- args.tfRegister[IDE_SECTOR_OFFSET] = taskfile->sector_number;
- args.tfRegister[IDE_LCYL_OFFSET] = taskfile->low_cylinder;
- args.tfRegister[IDE_HCYL_OFFSET] = taskfile->high_cylinder;
- args.tfRegister[IDE_SELECT_OFFSET] = taskfile->device_head;
- args.tfRegister[IDE_COMMAND_OFFSET] = taskfile->command;
-
- args.hobRegister[IDE_DATA_OFFSET_HOB] = hobfile->data;
- args.hobRegister[IDE_FEATURE_OFFSET_HOB] = hobfile->feature;
- args.hobRegister[IDE_NSECTOR_OFFSET_HOB] = hobfile->sector_count;
- args.hobRegister[IDE_SECTOR_OFFSET_HOB] = hobfile->sector_number;
- args.hobRegister[IDE_LCYL_OFFSET_HOB] = hobfile->low_cylinder;
- args.hobRegister[IDE_HCYL_OFFSET_HOB] = hobfile->high_cylinder;
- args.hobRegister[IDE_SELECT_OFFSET_HOB] = hobfile->device_head;
- args.hobRegister[IDE_CONTROL_OFFSET_HOB] = hobfile->control;
-
- ide_init_drive_taskfile(&rq);
- /* This is kept for internal use only !!! */
- args.command_type = ide_cmd_type_parser (&args);
- if (args.command_type != IDE_DRIVE_TASK_NO_DATA)
- rq.current_nr_sectors = rq.nr_sectors = (hobfile->sector_count << 8) | taskfile->sector_count;
-
- rq.cmd = IDE_DRIVE_TASKFILE;
- rq.buffer = buf;
- rq.special = &args;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
-
-int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, byte *buf)
-{
- struct request rq;
- ide_init_drive_taskfile(&rq);
- rq.cmd = IDE_DRIVE_TASKFILE;
- rq.buffer = buf;
-
- if (args->command_type != IDE_DRIVE_TASK_NO_DATA)
- rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET];
-
- rq.special = args;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
-
-
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
-char * ide_ioctl_verbose (unsigned int cmd)
-{
- return("unknown");
-}
-
-char * ide_task_cmd_verbose (byte task)
-{
- return("unknown");
-}
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
-/*
- * The taskfile glue table
- *
- * reqtask.data_phase reqtask.req_cmd
- * args.command_type args.handler
- *
- * TASKFILE_P_OUT_DMAQ ?? ??
- * TASKFILE_P_IN_DMAQ ?? ??
- * TASKFILE_P_OUT_DMA ?? ??
- * TASKFILE_P_IN_DMA ?? ??
- * TASKFILE_P_OUT ?? ??
- * TASKFILE_P_IN ?? ??
- *
- * TASKFILE_OUT_DMAQ IDE_DRIVE_TASK_RAW_WRITE NULL
- * TASKFILE_IN_DMAQ IDE_DRIVE_TASK_IN NULL
- *
- * TASKFILE_OUT_DMA IDE_DRIVE_TASK_RAW_WRITE NULL
- * TASKFILE_IN_DMA IDE_DRIVE_TASK_IN NULL
- *
- * TASKFILE_IN_OUT ?? ??
- *
- * TASKFILE_MULTI_OUT IDE_DRIVE_TASK_RAW_WRITE task_mulout_intr
- * TASKFILE_MULTI_IN IDE_DRIVE_TASK_IN task_mulin_intr
- *
- * TASKFILE_OUT IDE_DRIVE_TASK_RAW_WRITE task_out_intr
- * TASKFILE_OUT IDE_DRIVE_TASK_OUT task_out_intr
- *
- * TASKFILE_IN IDE_DRIVE_TASK_IN task_in_intr
- * TASKFILE_NO_DATA IDE_DRIVE_TASK_NO_DATA task_no_data_intr
- *
- * IDE_DRIVE_TASK_SET_XFER task_no_data_intr
- * IDE_DRIVE_TASK_INVALID
- *
- */
-
-#define MAX_DMA (256*SECTOR_WORDS)
-
-int ide_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- ide_task_request_t *req_task;
- ide_task_t args;
-
- byte *outbuf = NULL;
- byte *inbuf = NULL;
- task_ioreg_t *argsptr = args.tfRegister;
- task_ioreg_t *hobsptr = args.hobRegister;
- int err = 0;
- int tasksize = sizeof(struct ide_task_request_s);
- int taskin = 0;
- int taskout = 0;
-
- req_task = kmalloc(tasksize, GFP_KERNEL);
- if (req_task == NULL) return -ENOMEM;
- memset(req_task, 0, tasksize);
- if (copy_from_user(req_task, (void *) arg, tasksize)) {
- kfree(req_task);
- return -EFAULT;
- }
-
- taskout = (int) req_task->out_size;
- taskin = (int) req_task->in_size;
-
- if (taskout) {
- int outtotal = tasksize;
- outbuf = kmalloc(taskout, GFP_KERNEL);
- if (outbuf == NULL) {
- err = -ENOMEM;
- goto abort;
- }
- memset(outbuf, 0, taskout);
- if (copy_from_user(outbuf, (void *)arg + outtotal, taskout)) {
- err = -EFAULT;
- goto abort;
- }
- }
-
- if (taskin) {
- int intotal = tasksize + taskout;
- inbuf = kmalloc(taskin, GFP_KERNEL);
- if (inbuf == NULL) {
- err = -ENOMEM;
- goto abort;
- }
- memset(inbuf, 0, taskin);
- if (copy_from_user(inbuf, (void *)arg + intotal , taskin)) {
- err = -EFAULT;
- goto abort;
- }
- }
-
- memset(argsptr, 0, HDIO_DRIVE_TASK_HDR_SIZE);
- memset(hobsptr, 0, HDIO_DRIVE_HOB_HDR_SIZE);
- memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
- memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE);
-
- args.tf_in_flags = req_task->in_flags;
- args.tf_out_flags = req_task->out_flags;
- args.data_phase = req_task->data_phase;
- args.command_type = req_task->req_cmd;
-
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
- DTF("%s: ide_ioctl_cmd %s: ide_task_cmd %s\n",
- drive->name,
- ide_ioctl_verbose(cmd),
- ide_task_cmd_verbose(args.tfRegister[IDE_COMMAND_OFFSET]));
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
- switch(req_task->data_phase) {
- case TASKFILE_OUT_DMAQ:
- case TASKFILE_OUT_DMA:
- args.prehandler = NULL;
- args.handler = NULL;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, outbuf);
- break;
- case TASKFILE_IN_DMAQ:
- case TASKFILE_IN_DMA:
- args.prehandler = NULL;
- args.handler = NULL;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, inbuf);
- break;
- case TASKFILE_IN_OUT:
-#if 0
- args.prehandler = &pre_task_out_intr;
- args.handler = &task_out_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, outbuf);
- args.prehandler = NULL;
- args.handler = &task_in_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, inbuf);
- break;
-#else
- err = -EFAULT;
- goto abort;
-#endif
- case TASKFILE_MULTI_OUT:
- if (drive->mult_count) {
- args.prehandler = &pre_task_out_intr;
- args.handler = &task_mulout_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, outbuf);
- } else {
- /* (hs): give up if multcount is not set */
- printk("%s: %s Multimode Write " \
- "multcount is not set\n",
- drive->name, __FUNCTION__);
- err = -EPERM;
- goto abort;
- }
- break;
- case TASKFILE_OUT:
- args.prehandler = &pre_task_out_intr;
- args.handler = &task_out_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, outbuf);
- break;
- case TASKFILE_MULTI_IN:
- if (drive->mult_count) {
- args.prehandler = NULL;
- args.handler = &task_mulin_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, inbuf);
- } else {
- /* (hs): give up if multcount is not set */
- printk("%s: %s Multimode Read failure " \
- "multcount is not set\n",
- drive->name, __FUNCTION__);
- err = -EPERM;
- goto abort;
- }
- break;
- case TASKFILE_IN:
- args.prehandler = NULL;
- args.handler = &task_in_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, inbuf);
- break;
- case TASKFILE_NO_DATA:
- args.prehandler = NULL;
- args.handler = &task_no_data_intr;
- args.posthandler = NULL;
- err = ide_raw_taskfile(drive, &args, NULL);
- break;
- default:
- args.prehandler = NULL;
- args.handler = NULL;
- args.posthandler = NULL;
- err = -EFAULT;
- goto abort;
- }
-
- memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE);
- memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE);
- req_task->in_flags = args.tf_in_flags;
- req_task->out_flags = args.tf_out_flags;
-
- if (copy_to_user((void *)arg, req_task, tasksize)) {
- err = -EFAULT;
- goto abort;
- }
- if (taskout) {
- int outtotal = tasksize;
- if (copy_to_user((void *)arg+outtotal, outbuf, taskout)) {
- err = -EFAULT;
- goto abort;
- }
- }
- if (taskin) {
- int intotal = tasksize + taskout;
- if (copy_to_user((void *)arg+intotal, inbuf, taskin)) {
- err = -EFAULT;
- goto abort;
- }
- }
-abort:
- kfree(req_task);
- if (outbuf != NULL)
- kfree(outbuf);
- if (inbuf != NULL)
- kfree(inbuf);
- return err;
-}
-
-EXPORT_SYMBOL(task_read_24);
-EXPORT_SYMBOL(do_rw_taskfile);
-EXPORT_SYMBOL(do_taskfile);
-// EXPORT_SYMBOL(flagged_taskfile);
-
-//EXPORT_SYMBOL(ide_end_taskfile);
-
-EXPORT_SYMBOL(set_multmode_intr);
-EXPORT_SYMBOL(set_geometry_intr);
-EXPORT_SYMBOL(recal_intr);
-
-EXPORT_SYMBOL(task_no_data_intr);
-EXPORT_SYMBOL(task_in_intr);
-EXPORT_SYMBOL(task_mulin_intr);
-EXPORT_SYMBOL(pre_task_out_intr);
-EXPORT_SYMBOL(task_out_intr);
-EXPORT_SYMBOL(task_mulout_intr);
-
-EXPORT_SYMBOL(ide_init_drive_taskfile);
-EXPORT_SYMBOL(ide_wait_taskfile);
-EXPORT_SYMBOL(ide_raw_taskfile);
-EXPORT_SYMBOL(ide_pre_handler_parser);
-EXPORT_SYMBOL(ide_handler_parser);
-EXPORT_SYMBOL(ide_cmd_type_parser);
-EXPORT_SYMBOL(ide_taskfile_ioctl);
-
-#ifdef CONFIG_PKT_TASK_IOCTL
-
-#if 0
-{
-
-{ /* start cdrom */
-
- struct cdrom_info *info = drive->driver_data;
-
- if (info->dma) {
- if (info->cmd == READ) {
- info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive);
- } else if (info->cmd == WRITE) {
- info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive);
- } else {
- printk("ide-cd: DMA set, but not allowed\n");
- }
- }
-
- /* Set up the controller registers. */
- OUT_BYTE (info->dma, IDE_FEATURE_REG);
- OUT_BYTE (0, IDE_NSECTOR_REG);
- OUT_BYTE (0, IDE_SECTOR_REG);
-
- OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG);
- OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG);
- if (IDE_CONTROL_REG)
- OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
-
- if (info->dma)
- (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
-
- if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
- ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry);
- OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- return ide_started;
- } else {
- OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- return (*handler) (drive);
- }
-
-} /* end cdrom */
-
-{ /* start floppy */
-
- idefloppy_floppy_t *floppy = drive->driver_data;
- idefloppy_bcount_reg_t bcount;
- int dma_ok = 0;
-
- floppy->pc=pc; /* Set the current packet command */
-
- pc->retries++;
- pc->actually_transferred=0; /* We haven't transferred any data yet */
- pc->current_position=pc->buffer;
- bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024);
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
- (void) HWIF(drive)->dmaproc(ide_dma_off, drive);
- }
- if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
- dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
- if (IDE_CONTROL_REG)
- OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
- OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */
- OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);
- OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
- OUT_BYTE (drive->select.all,IDE_SELECT_REG);
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (dma_ok) { /* Begin DMA, if necessary */
- set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
- (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
- }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-} /* end floppy */
-
-{ /* start tape */
-
- idetape_tape_t *tape = drive->driver_data;
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
- printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n");
- (void) HWIF(drive)->dmaproc(ide_dma_off, drive);
- }
- if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
- dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
- if (IDE_CONTROL_REG)
- OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
- OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */
- OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);
- OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
- OUT_BYTE (drive->select.all,IDE_SELECT_REG);
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (dma_ok) { /* Begin DMA, if necessary */
- set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
- (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
- }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
- if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
- ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
- OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
- return ide_started;
- } else {
- OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
- return idetape_transfer_pc(drive);
- }
-
-} /* end tape */
-
-}
-#endif
-
-int pkt_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-#if 0
- switch(req_task->data_phase) {
- case TASKFILE_P_OUT_DMAQ:
- case TASKFILE_P_IN_DMAQ:
- case TASKFILE_P_OUT_DMA:
- case TASKFILE_P_IN_DMA:
- case TASKFILE_P_OUT:
- case TASKFILE_P_IN:
- }
-#endif
- return -ENOMSG;
-}
-
-EXPORT_SYMBOL(pkt_taskfile_ioctl);
-
-#endif /* CONFIG_PKT_TASK_IOCTL */
diff --git a/xen/drivers/ide/ide-xen.c b/xen/drivers/ide/ide-xen.c
deleted file mode 100644
index c925ab0c36..0000000000
--- a/xen/drivers/ide/ide-xen.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <xen/ide.h>
-#include <xen/vbd.h>
-#include <asm/domain_page.h>
-#include <asm/io.h>
-
-static kdev_t ide_devs[] = {
- MKDEV(IDE0_MAJOR, 0), MKDEV(IDE0_MAJOR, 64), /* hda, hdb */
- MKDEV(IDE1_MAJOR, 0), MKDEV(IDE1_MAJOR, 64), /* hdc, hdd */
- MKDEV(IDE2_MAJOR, 0), MKDEV(IDE2_MAJOR, 64), /* hde, hdf */
- MKDEV(IDE3_MAJOR, 0), MKDEV(IDE3_MAJOR, 64), /* hdg, hdh */
- MKDEV(IDE4_MAJOR, 0), MKDEV(IDE4_MAJOR, 64), /* hdi, hdj */
- MKDEV(IDE5_MAJOR, 0), MKDEV(IDE5_MAJOR, 64), /* hdk, hdl */
- MKDEV(IDE6_MAJOR, 0), MKDEV(IDE6_MAJOR, 64), /* hdm, hdn */
- MKDEV(IDE7_MAJOR, 0), MKDEV(IDE7_MAJOR, 64), /* hdo, hdp */
- MKDEV(IDE8_MAJOR, 0), MKDEV(IDE8_MAJOR, 64), /* hdq, hdr */
- MKDEV(IDE9_MAJOR, 0), MKDEV(IDE9_MAJOR, 64) /* hds, hdt */
-};
-
-void ide_probe_devices(xen_disk_info_t* xdi)
-{
- int i, unit;
- ide_drive_t *drive;
- xen_disk_t *xd = &xdi->disks[xdi->count];
-
- for ( i = 0; i < MAX_HWIFS; i++ )
- {
- ide_hwif_t *hwif = &ide_hwifs[i];
- if ( !hwif->present ) continue;
-
- for ( unit = 0; unit < MAX_DRIVES; unit++ )
- {
- drive = &hwif->drives[unit];
-
- if ( !drive->present )
- continue;
-
- if ( xdi->count == xdi->max )
- BUG();
-
- /* We export 'raw' linux device numbers to domain 0. */
- xd->device = ide_devs[(i * MAX_DRIVES) + unit];
-
- /*
- * NB: we use the ide 'media' field (ide_disk, ide_cdrom, etc) as
- * our 'type' field (XD_TYPE_DISK, XD_TYPE_CDROM, etc). Hence must
- * ensure these are kept in sync.
- */
- if ( (xd->info = drive->media) == XD_TYPE_CDROM )
- xd->info |= XD_FLAG_RO;
-
- xd->capacity = current_capacity(drive);
- xd->domain = 0;
-
- xdi->count++;
- xd++;
- }
- }
-}
diff --git a/xen/drivers/ide/ide.c b/xen/drivers/ide/ide.c
deleted file mode 100644
index e7e278255e..0000000000
--- a/xen/drivers/ide/ide.c
+++ /dev/null
@@ -1,4211 +0,0 @@
-/*
- * linux/drivers/ide/ide.c Version 6.31 June 9, 2000
- *
- * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
- */
-
-/*
- * Mostly written by Mark Lord <mlord@pobox.com>
- * and Gadi Oxman <gadio@netvision.net.il>
- * and Andre Hedrick <andre@linux-ide.org>
- *
- * See linux/MAINTAINERS for address of current maintainer.
- *
- * This is the multiple IDE interface driver, as evolved from hd.c.
- * It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs (usually 14 & 15).
- * There can be up to two drives per interface, as per the ATA-2 spec.
- *
- * Primary: ide0, port 0x1f0; major=3; hda is minor=0; hdb is minor=64
- * Secondary: ide1, port 0x170; major=22; hdc is minor=0; hdd is minor=64
- * Tertiary: ide2, port 0x???; major=33; hde is minor=0; hdf is minor=64
- * Quaternary: ide3, port 0x???; major=34; hdg is minor=0; hdh is minor=64
- * ...
- *
- * From hd.c:
- * |
- * | It traverses the request-list, using interrupts to jump between functions.
- * | As nearly all functions can be called within interrupts, we may not sleep.
- * | Special care is recommended. Have Fun!
- * |
- * | modified by Drew Eckhardt to check nr of hd's from the CMOS.
- * |
- * | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
- * | in the early extended-partition checks and added DM partitions.
- * |
- * | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI).
- * |
- * | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
- * | and general streamlining by Mark Lord (mlord@pobox.com).
- *
- * October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by:
- *
- * Mark Lord (mlord@pobox.com) (IDE Perf.Pkg)
- * Delman Lee (delman@ieee.org) ("Mr. atdisk2")
- * Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom)
- *
- * This was a rewrite of just about everything from hd.c, though some original
- * code is still sprinkled about. Think of it as a major evolution, with
- * inspiration from lots of linux users, esp. hamish@zot.apana.org.au
- *
- * Version 1.0 ALPHA initial code, primary i/f working okay
- * Version 1.3 BETA dual i/f on shared irq tested & working!
- * Version 1.4 BETA added auto probing for irq(s)
- * Version 1.5 BETA added ALPHA (untested) support for IDE cd-roms,
- * ...
- * Version 5.50 allow values as small as 20 for idebus=
- * Version 5.51 force non io_32bit in drive_cmd_intr()
- * change delay_10ms() to delay_50ms() to fix problems
- * Version 5.52 fix incorrect invalidation of removable devices
- * add "hdx=slow" command line option
- * Version 5.60 start to modularize the driver; the disk and ATAPI
- * drivers can be compiled as loadable modules.
- * move IDE probe code to ide-probe.c
- * move IDE disk code to ide-disk.c
- * add support for generic IDE device subdrivers
- * add m68k code from Geert Uytterhoeven
- * probe all interfaces by default
- * add ioctl to (re)probe an interface
- * Version 6.00 use per device request queues
- * attempt to optimize shared hwgroup performance
- * add ioctl to manually adjust bandwidth algorithms
- * add kerneld support for the probe module
- * fix bug in ide_error()
- * fix bug in the first ide_get_lock() call for Atari
- * don't flush leftover data for ATAPI devices
- * Version 6.01 clear hwgroup->active while the hwgroup sleeps
- * support HDIO_GETGEO for floppies
- * Version 6.02 fix ide_ack_intr() call
- * check partition table on floppies
- * Version 6.03 handle bad status bit sequencing in ide_wait_stat()
- * Version 6.10 deleted old entries from this list of updates
- * replaced triton.c with ide-dma.c generic PCI DMA
- * added support for BIOS-enabled UltraDMA
- * rename all "promise" things to "pdc4030"
- * fix EZ-DRIVE handling on small disks
- * Version 6.11 fix probe error in ide_scan_devices()
- * fix ancient "jiffies" polling bugs
- * mask all hwgroup interrupts on each irq entry
- * Version 6.12 integrate ioctl and proc interfaces
- * fix parsing of "idex=" command line parameter
- * Version 6.13 add support for ide4/ide5 courtesy rjones@orchestream.com
- * Version 6.14 fixed IRQ sharing among PCI devices
- * Version 6.15 added SMP awareness to IDE drivers
- * Version 6.16 fixed various bugs; even more SMP friendly
- * Version 6.17 fix for newest EZ-Drive problem
- * Version 6.18 default unpartitioned-disk translation now "BIOS LBA"
- * Version 6.19 Re-design for a UNIFORM driver for all platforms,
- * model based on suggestions from Russell King and
- * Geert Uytterhoeven
- * Promise DC4030VL now supported.
- * add support for ide6/ide7
- * delay_50ms() changed to ide_delay_50ms() and exported.
- * Version 6.20 Added/Fixed Generic ATA-66 support and hwif detection.
- * Added hdx=flash to allow for second flash disk
- * detection w/o the hang loop.
- * Added support for ide8/ide9
- * Added idex=ata66 for the quirky chipsets that are
- * ATA-66 compliant, but have yet to determine a method
- * of verification of the 80c cable presence.
- * Specifically Promise's PDC20262 chipset.
- * Version 6.21 Fixing/Fixed SMP spinlock issue with insight from an old
- * hat that clarified original low level driver design.
- * Version 6.30 Added SMP support; fixed multmode issues. -ml
- * Version 6.31 Debug Share INTR's and request queue streaming
- * Native ATA-100 support
- * Prep for Cascades Project
- *
- * Some additional driver compile-time options are in ./include/linux/ide.h
- *
- * To do, in likely order of completion:
- * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
- *
- */
-
-#define REVISION "Revision: 6.31"
-#define VERSION "Id: ide.c 6.31 2000/06/09"
-
-#undef REALLY_SLOW_IO /* most systems can safely undef this */
-
-#define _IDE_C /* Tell ide.h it's really us */
-
-#include <xen/config.h>
-#include <xen/module.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-/*#include <xen/kernel.h>*/
-#include <xen/timer.h>
-#include <xen/mm.h>
-#include <xen/interrupt.h>
-#include <xen/major.h>
-#include <xen/errno.h>
-#include <xen/genhd.h>
-#include <xen/blkpg.h>
-#include <xen/slab.h>
-#include <xen/init.h>
-#include <xen/pci.h>
-#include <xen/delay.h>
-#include <xen/ide.h>
-/*#include <xen/devfs_fs_kernel.h>*/
-/*#include <xen/completion.h>*/
-/*#include <xen/reboot.h>*/
-
-#include <asm/domain_page.h>
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-
-#include "ide_modes.h"
-
-#ifdef CONFIG_KMOD
-#include <xen/kmod.h>
-#endif /* CONFIG_KMOD */
-
-#ifdef CONFIG_IDE_TASKFILE_IO
-# define __TASKFILE__IO
-#else /* CONFIG_IDE_TASKFILE_IO */
-# undef __TASKFILE__IO
-#endif /* CONFIG_IDE_TASKFILE_IO */
-
-#ifdef __TASKFILE__IO
-#else /* !__TASKFILE__IO */
-#endif /* __TASKFILE__IO */
-
-
-
-
-/* XXXXXXXXXXXX This may be replaced by fs/block_dev.c versions!!! XXXXX */
-/* (only included here so the hypervisor will link :-) */
-int check_disk_change(kdev_t dev) { return 0; }
-int unregister_blkdev(unsigned int major, const char * name) { return 0; }
-/* And these ones are from fs/inode.c... */
-int invalidate_device(kdev_t dev, int do_sync) { return 0; }
-/* fs/buffer.c... */
-void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) { }
-/* fs/devices.c... */
-const char * kdevname(kdev_t dev) { return NULL; }
-/* End of XXXXXX region */
-
-
-
-
-/* default maximum number of failures */
-#define IDE_DEFAULT_MAX_FAILURES 1
-
-static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR };
-
-static int idebus_parameter; /* holds the "idebus=" parameter */
-static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
-static int initializing; /* set while initializing built-in drivers */
-
-#ifdef CONFIG_BLK_DEV_IDEPCI
-static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
-#endif /* CONFIG_BLK_DEV_IDEPCI */
-
-#if defined(__mc68000__) || defined(CONFIG_APUS)
-/*
- * ide_lock is used by the Atari code to obtain access to the IDE interrupt,
- * which is shared between several drivers.
- */
-static int ide_lock;
-#endif /* __mc68000__ || CONFIG_APUS */
-
-int noautodma = 0;
-
-/*
- * ide_modules keeps track of the available IDE chipset/probe/driver modules.
- */
-ide_module_t *ide_modules;
-ide_module_t *ide_probe;
-
-/*
- * This is declared extern in ide.h, for access by other IDE modules:
- */
-ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
-
-#if (DISK_RECOVERY_TIME > 0)
-/*
- * For really screwy hardware (hey, at least it *can* be used with Linux)
- * we can enforce a minimum delay time between successive operations.
- */
-static unsigned long read_timer (void)
-{
- unsigned long t, flags;
- int i;
-
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only */
- t = jiffies * 11932;
- outb_p(0, 0x43);
- i = inb_p(0x40);
- i |= inb(0x40) << 8;
- __restore_flags(flags); /* local CPU only */
- return (t - i);
-}
-#endif /* DISK_RECOVERY_TIME */
-
-static inline void set_recovery_timer (ide_hwif_t *hwif)
-{
-#if (DISK_RECOVERY_TIME > 0)
- hwif->last_time = read_timer();
-#endif /* DISK_RECOVERY_TIME */
-}
-
-/*
- * Do not even *think* about calling this!
- */
-static void init_hwif_data (unsigned int index)
-{
- unsigned int unit;
- hw_regs_t hw;
- ide_hwif_t *hwif = &ide_hwifs[index];
-
- /* bulk initialize hwif & drive info with zeros */
- memset(hwif, 0, sizeof(ide_hwif_t));
- memset(&hw, 0, sizeof(hw_regs_t));
-
- /* fill in any non-zero initial values */
- hwif->index = index;
- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
- memcpy(&hwif->hw, &hw, sizeof(hw));
- memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
- hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
-#ifdef CONFIG_BLK_DEV_HD
- if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
- hwif->noprobe = 1; /* may be overridden by ide_setup() */
-#endif /* CONFIG_BLK_DEV_HD */
- hwif->major = ide_hwif_to_major[index];
- hwif->name[0] = 'i';
- hwif->name[1] = 'd';
- hwif->name[2] = 'e';
- hwif->name[3] = '0' + index;
- hwif->bus_state = BUSSTATE_ON;
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
-
- drive->media = ide_disk;
- drive->select.all = (unit<<4)|0xa0;
- drive->hwif = hwif;
- drive->ctl = 0x08;
- drive->ready_stat = READY_STAT;
- drive->bad_wstat = BAD_W_STAT;
- drive->special.b.recalibrate = 1;
- drive->special.b.set_geometry = 1;
- drive->name[0] = 'h';
- drive->name[1] = 'd';
- drive->name[2] = '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
- * ide_drive_t 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 index;
- static unsigned long magic_cookie = MAGIC_COOKIE;
-
- if (magic_cookie != MAGIC_COOKIE)
- return; /* already initialized */
- magic_cookie = 0;
-
- /* Initialise all interface structures */
- for (index = 0; index < MAX_HWIFS; ++index)
- init_hwif_data(index);
-
- /* Add default hw interfaces */
- ide_init_default_hwifs();
-
- idebus_parameter = 0;
- system_bus_speed = 0;
-}
-
-/*
- * CompactFlash cards and their brethern pretend to be removable hard disks, except:
- * (1) they never have a slave unit, and
- * (2) they don't have doorlock mechanisms.
- * This test catches them, and is invoked elsewhere when setting appropriate config bits.
- *
- * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) devices,
- * so in linux 2.3.x we should change this to just treat all PCMCIA drives this way,
- * and get rid of the model-name tests below (too big of an interface change for 2.2.x).
- * At that time, we might also consider parameterizing the timeouts and retries,
- * since these are MUCH faster than mechanical drives. -M.Lord
- */
-int drive_is_flashcard (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
-
- if (drive->removable && id != NULL) {
- if (id->config == 0x848a) return 1; /* CompactFlash */
- if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */
- || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
- || !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */
- || !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */
- || !strncmp(id->model, "LEXAR ATA_FLASH", 15) /* Lexar */
- || !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */
- {
- return 1; /* yes, it is a flash memory card */
- }
- }
- return 0; /* no, it is not a flash memory card */
-}
-
-/*
- * ide_system_bus_speed() returns what we think is the system VESA/PCI
- * bus speed (in MHz). This is used for calculating interface PIO timings.
- * The default is 40 for known PCI systems, 50 otherwise.
- * The "idebus=xx" parameter can be used to override this value.
- * The actual value to be used is computed/displayed the first time through.
- */
-int ide_system_bus_speed (void)
-{
- if (!system_bus_speed) {
- if (idebus_parameter)
- system_bus_speed = idebus_parameter; /* user supplied value */
-#ifdef CONFIG_PCI
- else if (pci_present())
- system_bus_speed = 33; /* safe default value for PCI */
-#endif /* CONFIG_PCI */
- else
- system_bus_speed = 50; /* safe default value for VESA and PCI */
- printk("ide: Assuming %dMHz system bus speed for PIO modes%s\n", system_bus_speed,
- idebus_parameter ? "" : "; override with idebus=xx");
- }
- return system_bus_speed;
-}
-
-#if SUPPORT_VLB_SYNC
-/*
- * Some localbus EIDE interfaces require a special access sequence
- * when using 32-bit I/O instructions to transfer data. We call this
- * the "vlb_sync" sequence, which consists of three successive reads
- * of the sector count register location, with interrupts disabled
- * to ensure that the reads all happen together.
- */
-static inline void do_vlb_sync (ide_ioreg_t port) {
- (void) inb (port);
- (void) inb (port);
- (void) inb (port);
-}
-#endif /* SUPPORT_VLB_SYNC */
-
-/*
- * This is used for most PIO data transfers *from* the IDE interface
- */
-void ide_input_data (ide_drive_t *drive, void *vbuffer, unsigned int wcount)
-{
- void *buffer;
- byte io_32bit;
-
- /* first check if this controller has defined a special function
- * for handling polled ide transfers
- */
-
- if(HWIF(drive)->ideproc) {
- HWIF(drive)->ideproc(ideproc_ide_input_data,
- drive, vbuffer, wcount);
- return;
- }
-
- /* We assume controllers own functions will make their own
- * arrangemnets for mapping/unmaping the destination mem if
- * required (or not if DMA)
- */
-
- buffer = map_domain_mem(virt_to_phys(vbuffer));
-
- io_32bit = drive->io_32bit;
-
- if (io_32bit) {
-#if SUPPORT_VLB_SYNC
- if (io_32bit & 2) {
- unsigned long flags;
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only */
- do_vlb_sync(IDE_NSECTOR_REG);
- insl(IDE_DATA_REG, buffer, wcount);
- __restore_flags(flags); /* local CPU only */
- } else
-#endif /* SUPPORT_VLB_SYNC */
- insl(IDE_DATA_REG, buffer, wcount);
- } else {
-#if SUPPORT_SLOW_DATA_PORTS
- if (drive->slow) {
- unsigned short *ptr = (unsigned short *) buffer;
- while (wcount--) {
- *ptr++ = inw_p(IDE_DATA_REG);
- *ptr++ = inw_p(IDE_DATA_REG);
- }
- } else
-#endif /* SUPPORT_SLOW_DATA_PORTS */
- insw(IDE_DATA_REG, buffer, wcount<<1);
- }
-
- unmap_domain_mem(buffer);
-}
-
-/*
- * This is used for most PIO data transfers *to* the IDE interface
- */
-void ide_output_data (ide_drive_t *drive, void *vbuffer, unsigned int wcount)
-{
- void *buffer;
- byte io_32bit;
-
- if(HWIF(drive)->ideproc) {
- HWIF(drive)->ideproc(ideproc_ide_output_data,
- drive, vbuffer, wcount);
- return;
- }
-
- buffer = map_domain_mem(virt_to_phys(vbuffer));
-
- io_32bit = drive->io_32bit;
-
- if (io_32bit) {
-#if SUPPORT_VLB_SYNC
- if (io_32bit & 2) {
- unsigned long flags;
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only */
- do_vlb_sync(IDE_NSECTOR_REG);
- outsl(IDE_DATA_REG, buffer, wcount);
- __restore_flags(flags); /* local CPU only */
- } else
-#endif /* SUPPORT_VLB_SYNC */
- outsl(IDE_DATA_REG, buffer, wcount);
- } else {
-#if SUPPORT_SLOW_DATA_PORTS
- if (drive->slow) {
- unsigned short *ptr = (unsigned short *) buffer;
- while (wcount--) {
- outw_p(*ptr++, IDE_DATA_REG);
- outw_p(*ptr++, IDE_DATA_REG);
- }
- } else
-#endif /* SUPPORT_SLOW_DATA_PORTS */
- outsw(IDE_DATA_REG, buffer, wcount<<1);
- }
-
- unmap_domain_mem(buffer);
-}
-
-/*
- * 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_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
-{
- if(HWIF(drive)->ideproc) {
- HWIF(drive)->ideproc(ideproc_atapi_input_bytes,
- 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 /* CONFIG_ATARI */
- ide_input_data (drive, buffer, bytecount / 4);
- if ((bytecount & 0x03) >= 2)
- insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
-}
-
-void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
-{
- if(HWIF(drive)->ideproc) {
- HWIF(drive)->ideproc(ideproc_atapi_output_bytes,
- 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 /* CONFIG_ATARI */
- ide_output_data (drive, buffer, bytecount / 4);
- if ((bytecount & 0x03) >= 2)
- outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
-}
-
-/*
- * Needed for PCI irq sharing
- */
-//static inline
-int drive_is_ready (ide_drive_t *drive)
-{
- byte stat = 0;
- if (drive->waiting_for_dma)
- return HWIF(drive)->dmaproc(ide_dma_test_irq, drive);
-#if 0
- udelay(1); /* need to guarantee 400ns since last command was issued */
-#endif
-
-#ifdef CONFIG_IDEPCI_SHARE_IRQ
- /*
- * We do a passive status test under shared PCI interrupts on
- * cards that truly share the ATA side interrupt, but may also share
- * an interrupt with another pci card/device. We make no assumptions
- * about possible isa-pnp and pci-pnp issues yet.
- */
- if (IDE_CONTROL_REG)
- stat = GET_ALTSTAT();
- else
-#endif /* CONFIG_IDEPCI_SHARE_IRQ */
- stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */
-
- if (stat & BUSY_STAT)
- return 0; /* drive busy: definitely not interrupting */
- return 1; /* drive ready: *might* be interrupting */
-}
-
-/*
- * This is our end_request replacement function.
- */
-void ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
-{
- struct request *rq;
- unsigned long flags;
- ide_drive_t *drive = hwgroup->drive;
-
- spin_lock_irqsave(&io_request_lock, flags);
- rq = hwgroup->rq;
-
- /*
- * decide whether to reenable DMA -- 3 is a random magic for now,
- * if we DMA timeout more than 3 times, just stay in PIO
- */
- if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
- drive->state = 0;
- hwgroup->hwif->dmaproc(ide_dma_on, drive);
- }
-
- if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) {
- add_blkdev_randomness(MAJOR(rq->rq_dev));
- blkdev_dequeue_request(rq);
- hwgroup->rq = NULL;
- end_that_request_last(rq);
- }
- spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-/*
- * This should get invoked any time we exit the driver to
- * wait for an interrupt response from a drive. handler() points
- * at the appropriate code to handle the next interrupt, and a
- * timer is started to prevent us from waiting forever in case
- * something goes wrong (see the ide_timer_expiry() handler later on).
- */
-void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
- unsigned int timeout, ide_expiry_t *expiry)
-{
- unsigned long flags;
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
-
- spin_lock_irqsave(&io_request_lock, flags);
- if (hwgroup->handler != NULL) {
- printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n",
- drive->name, hwgroup->handler, handler);
- }
- hwgroup->handler = handler;
- hwgroup->expiry = expiry;
- hwgroup->timer.expires = jiffies + timeout;
- add_timer(&hwgroup->timer);
- spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-/*
- * current_capacity() returns the capacity (in sectors) of a drive
- * according to its current geometry/LBA settings.
- */
-unsigned long current_capacity (ide_drive_t *drive)
-{
- if (!drive->present)
- return 0;
- if (drive->driver != NULL)
- return DRIVER(drive)->capacity(drive);
- return 0;
-}
-
-extern struct block_device_operations ide_fops[];
-/*
- * ide_geninit() is called exactly *once* for each interface.
- */
-void ide_geninit (ide_hwif_t *hwif)
-{
- unsigned int unit;
- struct gendisk *gd = hwif->gd;
-
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
-
- if (!drive->present)
- continue;
- if (drive->media!=ide_disk && drive->media!=ide_floppy)
- continue;
- register_disk(gd,MKDEV(hwif->major,unit<<PARTN_BITS),
-#ifdef CONFIG_BLK_DEV_ISAPNP
- (drive->forced_geom && drive->noprobe) ? 1 :
-#endif /* CONFIG_BLK_DEV_ISAPNP */
- 1<<PARTN_BITS, ide_fops,
- current_capacity(drive));
- }
-}
-
-static ide_startstop_t do_reset1 (ide_drive_t *, int); /* needed below */
-
-/*
- * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms
- * during an atapi drive reset operation. If the drive has not yet responded,
- * and we have not yet hit our maximum waiting time, then the timer is restarted
- * for another 50ms.
- */
-static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- byte stat;
-
- SELECT_DRIVE(HWIF(drive),drive);
- udelay (10);
-
- if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) {
- printk("%s: ATAPI reset complete\n", drive->name);
- } else {
- if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
- ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
- return ide_started; /* continue polling */
- }
- hwgroup->poll_timeout = 0; /* end of polling */
- printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat);
- return do_reset1 (drive, 1); /* do it the old fashioned way */
- }
- hwgroup->poll_timeout = 0; /* done polling */
- return ide_stopped;
-}
-
-/*
- * reset_pollfunc() gets invoked to poll the interface for completion every 50ms
- * during an ide reset operation. If the drives have not yet responded,
- * and we have not yet hit our maximum waiting time, then the timer is restarted
- * for another 50ms.
- */
-static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- ide_hwif_t *hwif = HWIF(drive);
- byte tmp;
-
- if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) {
- if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
- ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
- return ide_started; /* continue polling */
- }
- printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
- drive->failures++;
- } else {
- printk("%s: reset: ", hwif->name);
- if ((tmp = GET_ERR()) == 1) {
- printk("success\n");
- drive->failures = 0;
- } else {
- drive->failures++;
-#if FANCY_STATUS_DUMPS
- printk("master: ");
- switch (tmp & 0x7f) {
- case 1: printk("passed");
- break;
- case 2: printk("formatter device error");
- break;
- case 3: printk("sector buffer error");
- break;
- case 4: printk("ECC circuitry error");
- break;
- case 5: printk("controlling MPU error");
- break;
- default:printk("error (0x%02x?)", tmp);
- }
- if (tmp & 0x80)
- printk("; slave: failed");
- printk("\n");
-#else
- printk("failed\n");
-#endif /* FANCY_STATUS_DUMPS */
- }
- }
- hwgroup->poll_timeout = 0; /* done polling */
- return ide_stopped;
-}
-
-static void check_dma_crc (ide_drive_t *drive)
-{
- if (drive->crc_count) {
- (void) HWIF(drive)->dmaproc(ide_dma_off_quietly, drive);
- if ((HWIF(drive)->speedproc) != NULL)
- HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive));
- if (drive->current_speed >= XFER_SW_DMA_0)
- (void) HWIF(drive)->dmaproc(ide_dma_on, drive);
- } else {
- (void) HWIF(drive)->dmaproc(ide_dma_off, drive);
- }
-}
-
-static void pre_reset (ide_drive_t *drive)
-{
- if (drive->driver != NULL)
- DRIVER(drive)->pre_reset(drive);
-
- if (!drive->keep_settings) {
- if (drive->using_dma) {
- check_dma_crc(drive);
- } else {
- drive->unmask = 0;
- drive->io_32bit = 0;
- }
- return;
- }
- if (drive->using_dma)
- check_dma_crc(drive);
-}
-
-/*
- * do_reset1() attempts to recover a confused drive by resetting it.
- * Unfortunately, resetting a disk drive actually resets all devices on
- * the same interface, so it can really be thought of as resetting the
- * interface rather than resetting the drive.
- *
- * ATAPI devices have their own reset mechanism which allows them to be
- * individually reset without clobbering other devices on the same interface.
- *
- * Unfortunately, the IDE interface does not generate an interrupt to let
- * us know when the reset operation has finished, so we must poll for this.
- * Equally poor, though, is the fact that this may a very long time to complete,
- * (up to 30 seconds worstcase). So, instead of busy-waiting here for it,
- * we set a timer to poll at 50ms intervals.
- */
-static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
-{
- unsigned int unit;
- unsigned long flags;
- ide_hwif_t *hwif = HWIF(drive);
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
-
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only */
-
- /* For an ATAPI device, first try an ATAPI SRST. */
- if (drive->media != ide_disk && !do_not_try_atapi) {
- pre_reset(drive);
- SELECT_DRIVE(hwif,drive);
- udelay (20);
- OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
- hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
- __restore_flags (flags); /* local CPU only */
- return ide_started;
- }
-
- /*
- * First, reset any device state data we were maintaining
- * for any of the drives on this interface.
- */
- for (unit = 0; unit < MAX_DRIVES; ++unit)
- pre_reset(&hwif->drives[unit]);
-
-#if OK_TO_RESET_CONTROLLER
- if (!IDE_CONTROL_REG) {
- __restore_flags(flags);
- return ide_stopped;
- }
- /*
- * Note that we also set nIEN while resetting the device,
- * to mask unwanted interrupts from the interface during the reset.
- * However, due to the design of PC hardware, this will cause an
- * immediate interrupt due to the edge transition it produces.
- * This single interrupt gives us a "fast poll" for drives that
- * recover from reset very quickly, saving us the first 50ms wait time.
- */
- OUT_BYTE(drive->ctl|6,IDE_CONTROL_REG); /* set SRST and nIEN */
- udelay(10); /* more than enough time */
- if (drive->quirk_list == 2) {
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear SRST and nIEN */
- } else {
- OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */
- }
- udelay(10); /* more than enough time */
- hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
-
- /*
- * Some weird controller like resetting themselves to a strange
- * state when the disks are reset this way. At least, the Winbond
- * 553 documentation says that
- */
- if (hwif->resetproc != NULL)
- hwif->resetproc(drive);
-
-#endif /* OK_TO_RESET_CONTROLLER */
-
- __restore_flags (flags); /* local CPU only */
- return ide_started;
-}
-
-/*
- * ide_do_reset() is the entry point to the drive/interface reset code.
- */
-ide_startstop_t ide_do_reset (ide_drive_t *drive)
-{
- return do_reset1 (drive, 0);
-}
-
-static inline u32 read_24 (ide_drive_t *drive)
-{
- return (IN_BYTE(IDE_HCYL_REG)<<16) |
- (IN_BYTE(IDE_LCYL_REG)<<8) |
- IN_BYTE(IDE_SECTOR_REG);
-}
-
-/*
- * Clean up after success/failure of an explicit drive cmd
- */
-void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err)
-{
- unsigned long flags;
- struct request *rq;
-
- spin_lock_irqsave(&io_request_lock, flags);
- rq = HWGROUP(drive)->rq;
- spin_unlock_irqrestore(&io_request_lock, flags);
-
- switch(rq->cmd) {
- case IDE_DRIVE_CMD:
- {
- byte *args = (byte *) rq->buffer;
- rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
- if (args) {
- args[0] = stat;
- args[1] = err;
- args[2] = IN_BYTE(IDE_NSECTOR_REG);
- }
- break;
- }
- case IDE_DRIVE_TASK:
- {
- byte *args = (byte *) rq->buffer;
- rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
- if (args) {
- args[0] = stat;
- args[1] = err;
- args[2] = IN_BYTE(IDE_NSECTOR_REG);
- args[3] = IN_BYTE(IDE_SECTOR_REG);
- args[4] = IN_BYTE(IDE_LCYL_REG);
- args[5] = IN_BYTE(IDE_HCYL_REG);
- args[6] = IN_BYTE(IDE_SELECT_REG);
- }
- break;
- }
- case IDE_DRIVE_TASKFILE:
- {
- ide_task_t *args = (ide_task_t *) rq->special;
- rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
- if (args) {
- if (args->tf_in_flags.b.data) {
- unsigned short data = IN_WORD(IDE_DATA_REG);
- args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF;
- args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF;
- }
- args->tfRegister[IDE_ERROR_OFFSET] = err;
- args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG);
- args->tfRegister[IDE_SECTOR_OFFSET] = IN_BYTE(IDE_SECTOR_REG);
- args->tfRegister[IDE_LCYL_OFFSET] = IN_BYTE(IDE_LCYL_REG);
- args->tfRegister[IDE_HCYL_OFFSET] = IN_BYTE(IDE_HCYL_REG);
- args->tfRegister[IDE_SELECT_OFFSET] = IN_BYTE(IDE_SELECT_REG);
- args->tfRegister[IDE_STATUS_OFFSET] = stat;
-
- if ((drive->id->command_set_2 & 0x0400) &&
- (drive->id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
- args->hobRegister[IDE_FEATURE_OFFSET_HOB] = IN_BYTE(IDE_FEATURE_REG);
- args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = IN_BYTE(IDE_NSECTOR_REG);
- args->hobRegister[IDE_SECTOR_OFFSET_HOB] = IN_BYTE(IDE_SECTOR_REG);
- args->hobRegister[IDE_LCYL_OFFSET_HOB] = IN_BYTE(IDE_LCYL_REG);
- args->hobRegister[IDE_HCYL_OFFSET_HOB] = IN_BYTE(IDE_HCYL_REG);
- }
- }
- break;
- }
- default:
- break;
- }
- spin_lock_irqsave(&io_request_lock, flags);
- blkdev_dequeue_request(rq);
- HWGROUP(drive)->rq = NULL;
- end_that_request_last(rq);
- spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
- */
-byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat)
-{
- unsigned long flags;
- byte err = 0;
-
- __save_flags (flags); /* local CPU only */
- ide__sti(); /* local CPU only */
- printk("%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
- printk(" { ");
- if (stat & BUSY_STAT)
- printk("Busy ");
- else {
- if (stat & READY_STAT) printk("DriveReady ");
- if (stat & WRERR_STAT) printk("DeviceFault ");
- if (stat & SEEK_STAT) printk("SeekComplete ");
- if (stat & DRQ_STAT) printk("DataRequest ");
- if (stat & ECC_STAT) printk("CorrectedError ");
- if (stat & INDEX_STAT) printk("Index ");
- if (stat & ERR_STAT) printk("Error ");
- }
- printk("}");
-#endif /* FANCY_STATUS_DUMPS */
- printk("\n");
- if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
- err = GET_ERR();
- printk("%s: %s: error=0x%02x", drive->name, msg, err);
-#if FANCY_STATUS_DUMPS
- if (drive->media == ide_disk) {
- printk(" { ");
- if (err & ABRT_ERR) printk("DriveStatusError ");
- if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector ");
- if (err & ECC_ERR) printk("UncorrectableError ");
- if (err & ID_ERR) printk("SectorIdNotFound ");
- if (err & TRK0_ERR) printk("TrackZeroNotFound ");
- if (err & MARK_ERR) printk("AddrMarkNotFound ");
- printk("}");
- if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
- if ((drive->id->command_set_2 & 0x0400) &&
- (drive->id->cfs_enable_2 & 0x0400) &&
- (drive->addressing == 1)) {
- __u64 sectors = 0;
- u32 low = 0, high = 0;
- low = read_24(drive);
- OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG);
- high = read_24(drive);
-
- sectors = ((__u64)high << 24) | low;
- printk(", LBAsect=%llu, high=%d, low=%d",
- (unsigned long long) sectors,
- high, low);
- } else {
- byte cur = IN_BYTE(IDE_SELECT_REG);
- if (cur & 0x40) { /* using LBA? */
- printk(", LBAsect=%ld", (unsigned long)
- ((cur&0xf)<<24)
- |(IN_BYTE(IDE_HCYL_REG)<<16)
- |(IN_BYTE(IDE_LCYL_REG)<<8)
- | IN_BYTE(IDE_SECTOR_REG));
- } else {
- printk(", CHS=%d/%d/%d",
- (IN_BYTE(IDE_HCYL_REG)<<8) +
- IN_BYTE(IDE_LCYL_REG),
- cur & 0xf,
- IN_BYTE(IDE_SECTOR_REG));
- }
- }
- if (HWGROUP(drive) && HWGROUP(drive)->rq)
- printk(", sector=%ld", HWGROUP(drive)->rq->sector);
- }
- }
-#endif /* FANCY_STATUS_DUMPS */
- printk("\n");
- }
- __restore_flags (flags); /* local CPU only */
- return err;
-}
-
-/*
- * try_to_flush_leftover_data() is invoked in response to a drive
- * unexpectedly having its DRQ_STAT bit set. As an alternative to
- * resetting the drive, this routine tries to clear the condition
- * by read a sector's worth of data from the drive. Of course,
- * this may not help if the drive is *waiting* for data from *us*.
- */
-static void try_to_flush_leftover_data (ide_drive_t *drive)
-{
- int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS;
-
- if (drive->media != ide_disk)
- return;
- while (i > 0) {
- u32 buffer[16];
- unsigned int wcount = (i > 16) ? 16 : i;
- i -= wcount;
- ide_input_data (drive, buffer, wcount);
- }
-}
-
-/*
- * ide_error() takes action based on the error returned by the drive.
- */
-ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat)
-{
- struct request *rq;
- byte err;
-
- err = ide_dump_status(drive, msg, stat);
- if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
- return ide_stopped;
- /* retry only "normal" I/O: */
- if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) {
- rq->errors = 1;
- ide_end_drive_cmd(drive, stat, err);
- return ide_stopped;
- }
- if (rq->cmd == IDE_DRIVE_TASKFILE) {
- rq->errors = 1;
- ide_end_drive_cmd(drive, stat, err);
-// ide_end_taskfile(drive, stat, err);
- return ide_stopped;
- }
-
- if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */
- rq->errors |= ERROR_RESET;
- } else {
- if (drive->media == ide_disk && (stat & ERR_STAT)) {
- /* err has different meaning on cdrom and tape */
- if (err == ABRT_ERR) {
- if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY)
- return ide_stopped; /* some newer drives don't support WIN_SPECIFY */
- } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) {
- drive->crc_count++; /* UDMA crc error -- just retry the operation */
- } else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */
- rq->errors = ERROR_MAX;
- else if (err & TRK0_ERR) /* help it find track zero */
- rq->errors |= ERROR_RECAL;
- }
- if ((stat & DRQ_STAT) && rq->cmd != WRITE)
- try_to_flush_leftover_data(drive);
- }
- if (GET_STAT() & (BUSY_STAT|DRQ_STAT))
- OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */
-
- if (rq->errors >= ERROR_MAX) {
- if (drive->driver != NULL)
- DRIVER(drive)->end_request(0, HWGROUP(drive));
- else
- ide_end_request(0, HWGROUP(drive));
- } else {
- if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
- ++rq->errors;
- return ide_do_reset(drive);
- }
- if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
- drive->special.b.recalibrate = 1;
- ++rq->errors;
- }
- return ide_stopped;
-}
-
-/*
- * Issue a simple drive command
- * The drive must be selected beforehand.
- */
-void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
-{
- ide_set_handler (drive, handler, WAIT_CMD, NULL);
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
- SELECT_MASK(HWIF(drive),drive,0);
- OUT_BYTE(nsect,IDE_NSECTOR_REG);
- OUT_BYTE(cmd,IDE_COMMAND_REG);
-}
-
-/*
- * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
- */
-static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
- byte *args = (byte *) rq->buffer;
- byte stat = GET_STAT();
- int retries = 10;
-
- ide__sti(); /* local CPU only */
- if ((stat & DRQ_STAT) && args && args[3]) {
- byte io_32bit = drive->io_32bit;
- drive->io_32bit = 0;
- ide_input_data(drive, &args[4], args[3] * SECTOR_WORDS);
- drive->io_32bit = io_32bit;
- while (((stat = GET_STAT()) & BUSY_STAT) && retries--)
- udelay(100);
- }
-
- if (!OK_STAT(stat, READY_STAT, BAD_STAT))
- return ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */
- ide_end_drive_cmd (drive, stat, GET_ERR());
- return ide_stopped;
-}
-
-/*
- * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT
- * commands to a drive. It used to do much more, but has been scaled back.
- */
-static ide_startstop_t do_special (ide_drive_t *drive)
-{
- special_t *s = &drive->special;
-
-#ifdef DEBUG
- printk("%s: do_special: 0x%02x\n", drive->name, s->all);
-#endif
- if (s->b.set_tune) {
- ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
- s->b.set_tune = 0;
- if (tuneproc != NULL)
- tuneproc(drive, drive->tune_req);
- } else if (drive->driver != NULL) {
- return DRIVER(drive)->special(drive);
- } else if (s->all) {
- printk("%s: bad special flag: 0x%02x\n", drive->name, s->all);
- s->all = 0;
- }
- return ide_stopped;
-}
-
-/*
- * This routine busy-waits for the drive status to be not "busy".
- * It then checks the status for all of the "good" bits and none
- * of the "bad" bits, and if all is okay it returns 0. All other
- * cases return 1 after invoking ide_error() -- caller should just return.
- *
- * This routine should get fixed to not hog the cpu during extra long waits..
- * That could be done by busy-waiting for the first jiffy or two, and then
- * setting a timer to wake up at half second intervals thereafter,
- * until timeout is achieved, before timing out.
- */
-int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) {
- byte stat;
- int i;
- unsigned long flags;
-
- /* bail early if we've exceeded max_failures */
- if (drive->max_failures && (drive->failures > drive->max_failures)) {
- *startstop = ide_stopped;
- return 1;
- }
-
- udelay(1); /* spec allows drive 400ns to assert "BUSY" */
- if ((stat = GET_STAT()) & BUSY_STAT) {
- __save_flags(flags); /* local CPU only */
- ide__sti(); /* local CPU only */
- timeout += jiffies;
- while ((stat = GET_STAT()) & BUSY_STAT) {
- if (0 < (signed long)(jiffies - timeout)) {
- __restore_flags(flags); /* local CPU only */
- *startstop = ide_error(drive, "status timeout", stat);
- return 1;
- }
- }
- __restore_flags(flags); /* local CPU only */
- }
- /*
- * Allow status to settle, then read it again.
- * A few rare drives vastly violate the 400ns spec here,
- * so we'll wait up to 10usec for a "good" status
- * rather than expensively fail things immediately.
- * This fix courtesy of Matthew Faupel & Niccolo Rigacci.
- */
- for (i = 0; i < 10; i++) {
- udelay(1);
- if (OK_STAT((stat = GET_STAT()), good, bad))
- return 0;
- }
- *startstop = ide_error(drive, "status error", stat);
- return 1;
-}
-
-/*
- * execute_drive_cmd() issues a special drive command,
- * usually initiated by ioctl() from the external hdparm program.
- */
-static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
-{
- switch(rq->cmd) {
- case IDE_DRIVE_TASKFILE:
- {
- ide_task_t *args = rq->special;
-
- if (!(args)) break;
-
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
- {
- printk(KERN_INFO "%s: ", drive->name);
-// printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]);
- printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]);
- printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]);
- printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]);
- printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]);
- printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]);
- printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]);
- printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]);
- printk(KERN_INFO "%s: ", drive->name);
-// printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET_HOB]);
- printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET_HOB]);
- printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET_HOB]);
- printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET_HOB]);
- printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET_HOB]);
- printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET_HOB]);
- printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET_HOB]);
- printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]);
- }
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
-// if (args->tf_out_flags.all == 0) {
- do_taskfile(drive,
- (struct hd_drive_task_hdr *)&args->tfRegister,
- (struct hd_drive_hob_hdr *)&args->hobRegister,
- args->handler);
-// } else {
-// return flagged_taskfile(drive, args);
-// }
-
- if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) ||
- (args->command_type == IDE_DRIVE_TASK_OUT)) &&
- args->prehandler && args->handler)
- return args->prehandler(drive, rq);
- return ide_started;
- }
- case IDE_DRIVE_TASK:
- {
- byte *args = rq->buffer;
- byte sel;
-
- if (!(args)) break;
-#ifdef DEBUG
- printk("%s: DRIVE_TASK_CMD ", drive->name);
- printk("cmd=0x%02x ", args[0]);
- printk("fr=0x%02x ", args[1]);
- printk("ns=0x%02x ", args[2]);
- printk("sc=0x%02x ", args[3]);
- printk("lcyl=0x%02x ", args[4]);
- printk("hcyl=0x%02x ", args[5]);
- printk("sel=0x%02x\n", args[6]);
-#endif
- OUT_BYTE(args[1], IDE_FEATURE_REG);
- OUT_BYTE(args[3], IDE_SECTOR_REG);
- OUT_BYTE(args[4], IDE_LCYL_REG);
- OUT_BYTE(args[5], IDE_HCYL_REG);
- sel = (args[6] & ~0x10);
- if (drive->select.b.unit)
- sel |= 0x10;
- OUT_BYTE(sel, IDE_SELECT_REG);
- ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
- return ide_started;
- }
- case IDE_DRIVE_CMD:
- {
- byte *args = rq->buffer;
-
- if (!(args)) break;
-#ifdef DEBUG
- printk("%s: DRIVE_CMD ", drive->name);
- printk("cmd=0x%02x ", args[0]);
- printk("sc=0x%02x ", args[1]);
- printk("fr=0x%02x ", args[2]);
- printk("xx=0x%02x\n", args[3]);
-#endif
- if (args[0] == WIN_SMART) {
- OUT_BYTE(0x4f, IDE_LCYL_REG);
- OUT_BYTE(0xc2, IDE_HCYL_REG);
- OUT_BYTE(args[2],IDE_FEATURE_REG);
- OUT_BYTE(args[1],IDE_SECTOR_REG);
- ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
- return ide_started;
- }
- OUT_BYTE(args[2],IDE_FEATURE_REG);
- ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
- return ide_started;
- }
- default:
- break;
- }
- /*
- * NULL is actually a valid way of waiting for
- * all current requests to be flushed from the queue.
- */
-#ifdef DEBUG
- printk("%s: DRIVE_CMD (null)\n", drive->name);
-#endif
- ide_end_drive_cmd(drive, GET_STAT(), GET_ERR());
- return ide_stopped;
-}
-
-/*
- * start_request() initiates handling of a new I/O request
- * needed to reverse the perverted changes anonymously made back
- * 2.3.99-pre6
- */
-static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
-{
- ide_startstop_t startstop;
- unsigned long block, blockend;
- unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS;
- ide_hwif_t *hwif = HWIF(drive);
-
-#ifdef DEBUG
- printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
-#endif
- /* bail early if we've exceeded max_failures */
- if (drive->max_failures && (drive->failures > drive->max_failures)) {
- goto kill_rq;
- }
-
- if (unit >= MAX_DRIVES) {
- printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev));
- goto kill_rq;
- }
-#ifdef DEBUG
- if (rq->bh && !buffer_locked(rq->bh)) {
- printk("%s: block not locked\n", drive->name);
- goto kill_rq;
- }
-#endif
- block = rq->sector;
- blockend = block + rq->nr_sectors;
-
-
-#ifdef NEVER
- if ((rq->cmd == READ || rq->cmd == WRITE) &&
- (drive->media == ide_disk || drive->media == ide_floppy)) {
- if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) {
- printk("%s%c: bad access: block=%ld, count=%ld\n", drive->name,
- (minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', block, rq->nr_sectors);
- goto kill_rq;
- }
- block += drive->part[minor&PARTN_MASK].start_sect + drive->sect0;
- }
- /* Yecch - this will shift the entire interval,
- possibly killing some innocent following sector */
- if (block == 0 && drive->remap_0_to_1 == 1)
- block = 1; /* redirect MBR access to EZ-Drive partn table */
-#endif
-
-#ifdef NEVER_DEBUG
- {
- printk(" ide::start_request %lx %lx %lx %lx %lx\n",
- rq->sector, rq->nr_sectors, block,
- drive->part[minor&PARTN_MASK].start_sect, drive->sect0);
- }
-#endif
-
-#if (DISK_RECOVERY_TIME > 0)
- while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
-#endif
-
- SELECT_DRIVE(hwif, drive);
- if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
- printk("%s: drive not ready for command\n", drive->name);
- return startstop;
- }
- drive->special.all = 0;
- if (!drive->special.all) {
- switch(rq->cmd) {
- case IDE_DRIVE_CMD:
- case IDE_DRIVE_TASK:
- case IDE_DRIVE_TASKFILE:
- return execute_drive_cmd(drive, rq);
- default:
- break;
- }
- if (drive->driver != NULL) {
- return (DRIVER(drive)->do_request(drive, rq, block));
- }
- printk("%s: media type %d not supported\n", drive->name, drive->media);
- goto kill_rq;
- }
- return do_special(drive);
-kill_rq:
- if (drive->driver != NULL)
- DRIVER(drive)->end_request(0, HWGROUP(drive));
- else
- ide_end_request(0, HWGROUP(drive));
- return ide_stopped;
-}
-
-ide_startstop_t restart_request (ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- unsigned long flags;
- struct request *rq;
-
- spin_lock_irqsave(&io_request_lock, flags);
- hwgroup->handler = NULL;
- del_timer(&hwgroup->timer);
- rq = hwgroup->rq;
- spin_unlock_irqrestore(&io_request_lock, flags);
-
- return start_request(drive, rq);
-}
-
-/*
- * ide_stall_queue() can be used by a drive to give excess bandwidth back
- * to the hwgroup by sleeping for timeout jiffies.
- */
-void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
-{
- if (timeout > WAIT_WORSTCASE)
- timeout = WAIT_WORSTCASE;
- drive->sleep = timeout + jiffies;
-}
-
-#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time)
-
-/*
- * choose_drive() selects the next drive which will be serviced.
- */
-static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
-{
- ide_drive_t *drive, *best;
-
-repeat:
- best = NULL;
- drive = hwgroup->drive;
- do {
- if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) {
- if (!best
- || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
- || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
- {
- if( !drive->queue.plugged )
- best = drive;
- }
- }
- } while ((drive = drive->next) != hwgroup->drive);
- if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
- long t = (signed long)(WAKEUP(best) - jiffies);
- if (t >= WAIT_MIN_SLEEP) {
- /*
- * We *may* have some time to spare, but first let's see if
- * someone can potentially benefit from our nice mood today..
- */
- drive = best->next;
- do {
- if (!drive->sleep
- && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time))
- && 0 < (signed long)((jiffies + t) - WAKEUP(drive)))
- {
- ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP));
- goto repeat;
- }
- } while ((drive = drive->next) != best);
- }
- }
- return best;
-}
-
-/*
- * Issue a new request to a drive from hwgroup
- * Caller must have already done spin_lock_irqsave(&io_request_lock, ..);
- *
- * A hwgroup is a serialized group of IDE interfaces. Usually there is
- * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)
- * may have both interfaces in a single hwgroup to "serialize" access.
- * Or possibly multiple ISA interfaces can share a common IRQ by being grouped
- * together into one hwgroup for serialized access.
- *
- * Note also that several hwgroups can end up sharing a single IRQ,
- * possibly along with many other devices. This is especially common in
- * PCI-based systems with off-board IDE controller cards.
- *
- * The IDE driver uses the single global io_request_lock spinlock to protect
- * access to the request queues, and to protect the hwgroup->busy flag.
- *
- * The first thread into the driver for a particular hwgroup sets the
- * hwgroup->busy flag to indicate that this hwgroup is now active,
- * and then initiates processing of the top request from the request queue.
- *
- * Other threads attempting entry notice the busy setting, and will simply
- * queue their new requests and exit immediately. Note that hwgroup->busy
- * remains set even when the driver is merely awaiting the next interrupt.
- * Thus, the meaning is "this hwgroup is busy processing a request".
- *
- * When processing of a request completes, the completing thread or IRQ-handler
- * will start the next request from the queue. If no more work remains,
- * the driver will clear the hwgroup->busy flag and exit.
- *
- * The io_request_lock (spinlock) is used to protect all access to the
- * hwgroup->busy flag, but is otherwise not needed for most processing in
- * the driver. This makes the driver much more friendlier to shared IRQs
- * than previous designs, while remaining 100% (?) SMP safe and capable.
- */
-/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back
- * into life on wakeup from machine sleep.
- */
-void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
-{
- ide_drive_t *drive;
- ide_hwif_t *hwif;
- struct request *rq;
- ide_startstop_t startstop;
-
- ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only: POSSIBLY BROKEN HERE(?) */
-
- __cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */
-
- while (!hwgroup->busy) {
- hwgroup->busy = 1;
- drive = choose_drive(hwgroup);
- if (drive == NULL) {
- unsigned long sleep = 0;
- hwgroup->rq = NULL;
- drive = hwgroup->drive;
- do {
- if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep)))
- sleep = drive->sleep;
- } while ((drive = drive->next) != hwgroup->drive);
- if (sleep) {
- /*
- * Take a short snooze, and then wake up this hwgroup again.
- * This gives other hwgroups on the same a chance to
- * play fairly with us, just in case there are big differences
- * in relative throughputs.. don't want to hog the cpu too much.
- */
- if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
- sleep = jiffies + WAIT_MIN_SLEEP;
-#if 1
- if (timer_pending(&hwgroup->timer))
- printk("ide_set_handler: timer already active\n");
-#endif
- hwgroup->sleeping = 1; /* so that ide_timer_expiry knows what to do */
- mod_timer(&hwgroup->timer, sleep);
- /* we purposely leave hwgroup->busy==1 while sleeping */
- } else {
- /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_disk? */
- ide_release_lock(&ide_lock); /* for atari only */
- hwgroup->busy = 0;
- }
- return; /* no more work for this hwgroup (for now) */
- }
- hwif = HWIF(drive);
- if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) {
- /* set nIEN for previous hwif */
- SELECT_INTERRUPT(hwif, drive);
- }
- hwgroup->hwif = hwif;
- hwgroup->drive = drive;
- drive->sleep = 0;
- drive->service_start = jiffies;
-
- if ( drive->queue.plugged ) /* paranoia */
- printk("%s: Huh? nuking plugged queue\n", drive->name);
-
- rq = hwgroup->rq = blkdev_entry_next_request(&drive->queue.queue_head);
- /*
- * Some systems have trouble with IDE IRQs arriving while
- * the driver is still setting things up. So, here we disable
- * the IRQ used by this interface while the request is being started.
- * This may look bad at first, but pretty much the same thing
- * happens anyway when any interrupt comes in, IDE or otherwise
- * -- the kernel masks the IRQ while it is being handled.
- */
- if (masked_irq && hwif->irq != masked_irq)
- disable_irq_nosync(hwif->irq);
- spin_unlock(&io_request_lock);
- ide__sti(); /* allow other IRQs while we start this request */
- startstop = start_request(drive, rq);
- spin_lock_irq(&io_request_lock);
- if (masked_irq && hwif->irq != masked_irq)
- enable_irq(hwif->irq);
- if (startstop == ide_stopped)
- hwgroup->busy = 0;
- }
-}
-
-/*
- * ide_get_queue() returns the queue which corresponds to a given device.
- */
-request_queue_t *ide_get_queue (kdev_t dev)
-{
- ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[MAJOR(dev)].data;
-
- return &hwif->drives[DEVICE_NR(dev) & 1].queue;
-}
-
-/*
- * Passes the stuff to ide_do_request
- */
-void do_ide_request(request_queue_t *q)
-{
- ide_do_request(q->queuedata, 0);
-}
-
-/*
- * un-busy the hwgroup etc, and clear any pending DMA status. we want to
- * retry the current request in pio mode instead of risking tossing it
- * all away
- */
-void ide_dma_timeout_retry(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = HWIF(drive);
- struct request *rq;
-
- /*
- * end current dma transaction
- */
- (void) hwif->dmaproc(ide_dma_end, drive);
-
- /*
- * complain a little, later we might remove some of this verbosity
- */
- printk("%s: timeout waiting for DMA\n", drive->name);
- (void) hwif->dmaproc(ide_dma_timeout, drive);
-
- /*
- * disable dma for now, but remember that we did so because of
- * a timeout -- we'll reenable after we finish this next request
- * (or rather the first chunk of it) in pio.
- */
- drive->retry_pio++;
- drive->state = DMA_PIO_RETRY;
- (void) hwif->dmaproc(ide_dma_off_quietly, drive);
-
- /*
- * un-busy drive etc (hwgroup->busy is cleared on return) and
- * make sure request is sane
- */
- rq = HWGROUP(drive)->rq;
- HWGROUP(drive)->rq = NULL;
-
- rq->errors = 0;
- rq->sector = rq->bh->b_rsector;
- rq->current_nr_sectors = rq->bh->b_size >> 9;
- rq->buffer = rq->bh->b_data;
-}
-
-/*
- * ide_timer_expiry() is our timeout function for all drive operations.
- * But note that it can also be invoked as a result of a "sleep" operation
- * triggered by the mod_timer() call in ide_do_request.
- */
-void ide_timer_expiry (unsigned long data)
-{
- ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
- ide_handler_t *handler;
- ide_expiry_t *expiry;
- unsigned long flags;
- unsigned long wait;
-
- spin_lock_irqsave(&io_request_lock, flags);
- del_timer(&hwgroup->timer);
-
- if ((handler = hwgroup->handler) == NULL) {
- /*
- * Either a marginal timeout occurred
- * (got the interrupt just as timer expired),
- * or we were "sleeping" to give other devices a chance.
- * Either way, we don't really want to complain about anything.
- */
- if (hwgroup->sleeping) {
- hwgroup->sleeping = 0;
- hwgroup->busy = 0;
- }
- } else {
- ide_drive_t *drive = hwgroup->drive;
- if (!drive) {
- printk("ide_timer_expiry: hwgroup->drive was NULL\n");
- hwgroup->handler = NULL;
- } else {
- ide_hwif_t *hwif;
- ide_startstop_t startstop;
- if (!hwgroup->busy) {
- hwgroup->busy = 1; /* paranoia */
- printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name);
- }
- if ((expiry = hwgroup->expiry) != NULL) {
- /* continue */
- if ((wait = expiry(drive)) != 0) {
- /* reset timer */
- hwgroup->timer.expires = jiffies + wait;
- add_timer(&hwgroup->timer);
- spin_unlock_irqrestore(&io_request_lock, flags);
- return;
- }
- }
- hwgroup->handler = NULL;
- /*
- * We need to simulate a real interrupt when invoking
- * the handler() function, which means we need to globally
- * mask the specific IRQ:
- */
- spin_unlock(&io_request_lock);
- hwif = HWIF(drive);
-#if DISABLE_IRQ_NOSYNC
- disable_irq_nosync(hwif->irq);
-#else
- disable_irq(hwif->irq); /* disable_irq_nosync ?? */
-#endif /* DISABLE_IRQ_NOSYNC */
- __cli(); /* local CPU only, as if we were handling an interrupt */
- if (hwgroup->poll_timeout != 0) {
- startstop = handler(drive);
- } else if (drive_is_ready(drive)) {
- if (drive->waiting_for_dma)
- (void) hwgroup->hwif->dmaproc(ide_dma_lostirq, drive);
- (void)ide_ack_intr(hwif);
- printk("%s: lost interrupt\n", drive->name);
- startstop = handler(drive);
- } else {
- if (drive->waiting_for_dma) {
- startstop = ide_stopped;
- ide_dma_timeout_retry(drive);
- } else
- startstop = ide_error(drive, "irq timeout", GET_STAT());
- }
- set_recovery_timer(hwif);
- drive->service_time = jiffies - drive->service_start;
- enable_irq(hwif->irq);
- spin_lock_irq(&io_request_lock);
- if (startstop == ide_stopped)
- hwgroup->busy = 0;
- }
- }
- ide_do_request(hwgroup, 0);
- spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-/*
- * There's nothing really useful we can do with an unexpected interrupt,
- * other than reading the status register (to clear it), and logging it.
- * There should be no way that an irq can happen before we're ready for it,
- * so we needn't worry much about losing an "important" interrupt here.
- *
- * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
- * drive enters "idle", "standby", or "sleep" mode, so if the status looks
- * "good", we just ignore the interrupt completely.
- *
- * This routine assumes __cli() is in effect when called.
- *
- * If an unexpected interrupt happens on irq15 while we are handling irq14
- * and if the two interfaces are "serialized" (CMD640), then it looks like
- * we could screw up by interfering with a new request being set up for irq15.
- *
- * In reality, this is a non-issue. The new command is not sent unless the
- * drive is ready to accept one, in which case we know the drive is not
- * trying to interrupt us. And ide_set_handler() is always invoked before
- * completing the issuance of any new drive command, so we will not be
- * accidentally invoked as a result of any valid command completion interrupt.
- *
- */
-static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
-{
- byte stat;
- ide_hwif_t *hwif = hwgroup->hwif;
-
- /*
- * handle the unexpected interrupt
- */
- do {
- if (hwif->irq == irq) {
- stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
- if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
- /* Try to not flood the console with msgs */
- static unsigned long last_msgtime, count;
- ++count;
- if (0 < (signed long)(jiffies - (last_msgtime + HZ))) {
- last_msgtime = jiffies;
- printk("%s%s: unexpected interrupt, status=0x%02x, count=%ld\n",
- hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count);
- }
- }
- }
- } while ((hwif = hwif->next) != hwgroup->hwif);
-}
-
-/*
- * entry point for all interrupts, caller does __cli() for us
- */
-void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned long flags;
- ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
- ide_hwif_t *hwif;
- ide_drive_t *drive;
- ide_handler_t *handler;
- ide_startstop_t startstop;
-
- spin_lock_irqsave(&io_request_lock, flags);
- hwif = hwgroup->hwif;
-
- if (!ide_ack_intr(hwif)) {
- spin_unlock_irqrestore(&io_request_lock, flags);
- return;
- }
-
- if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
- /*
- * Not expecting an interrupt from this drive.
- * That means this could be:
- * (1) an interrupt from another PCI device
- * sharing the same PCI INT# as us.
- * or (2) a drive just entered sleep or standby mode,
- * and is interrupting to let us know.
- * or (3) a spurious interrupt of unknown origin.
- *
- * For PCI, we cannot tell the difference,
- * so in that case we just ignore it and hope it goes away.
- */
-#ifdef CONFIG_BLK_DEV_IDEPCI
- if (IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL))
-#endif /* CONFIG_BLK_DEV_IDEPCI */
- {
- /*
- * Probably not a shared PCI interrupt,
- * so we can safely try to do something about it:
- */
- unexpected_intr(irq, hwgroup);
-#ifdef CONFIG_BLK_DEV_IDEPCI
- } else {
- /*
- * Whack the status register, just in case we have a leftover pending IRQ.
- */
- (void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
-#endif /* CONFIG_BLK_DEV_IDEPCI */
- }
- spin_unlock_irqrestore(&io_request_lock, flags);
- return;
- }
- drive = hwgroup->drive;
- if (!drive) {
- /*
- * This should NEVER happen, and there isn't much we could do about it here.
- */
- spin_unlock_irqrestore(&io_request_lock, flags);
- return;
- }
- if (!drive_is_ready(drive)) {
- /*
- * This happens regularly when we share a PCI IRQ with another device.
- * Unfortunately, it can also happen with some buggy drives that trigger
- * the IRQ before their status register is up to date. Hopefully we have
- * enough advance overhead that the latter isn't a problem.
- */
- spin_unlock_irqrestore(&io_request_lock, flags);
- return;
- }
- if (!hwgroup->busy) {
- hwgroup->busy = 1; /* paranoia */
- printk("%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);
- }
- hwgroup->handler = NULL;
- del_timer(&hwgroup->timer);
- spin_unlock(&io_request_lock);
-
- if (drive->unmask)
- ide__sti(); /* local CPU only */
- startstop = handler(drive); /* service this interrupt, may set handler for next interrupt */
- spin_lock_irq(&io_request_lock);
-
- /*
- * Note that handler() may have set things up for another
- * interrupt to occur soon, but it cannot happen until
- * we exit from this routine, because it will be the
- * same irq as is currently being serviced here, and Linux
- * won't allow another of the same (on any CPU) until we return.
- */
- set_recovery_timer(HWIF(drive));
- drive->service_time = jiffies - drive->service_start;
- if (startstop == ide_stopped) {
- if (hwgroup->handler == NULL) { /* paranoia */
- hwgroup->busy = 0;
- ide_do_request(hwgroup, hwif->irq);
- } else {
- printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name);
- }
- }
- spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-/*
- * get_info_ptr() returns the (ide_drive_t *) for a given device number.
- * It returns NULL if the given device number does not match any present drives.
- */
-ide_drive_t *get_info_ptr (kdev_t i_rdev)
-{
- int major = MAJOR(i_rdev);
-#if 0
- int minor = MINOR(i_rdev) & PARTN_MASK;
-#endif
- unsigned int h;
-
- for (h = 0; h < MAX_HWIFS; ++h) {
- ide_hwif_t *hwif = &ide_hwifs[h];
- if (hwif->present && major == hwif->major) {
- unsigned unit = DEVICE_NR(i_rdev);
- if (unit < MAX_DRIVES) {
- ide_drive_t *drive = &hwif->drives[unit];
-#if 0
- if ((drive->present) && (drive->part[minor].nr_sects))
-#else
- if (drive->present)
-#endif
- return drive;
- }
- break;
- }
- }
- return NULL;
-}
-
-/*
- * This function is intended to be used prior to invoking ide_do_drive_cmd().
- */
-void ide_init_drive_cmd (struct request *rq)
-{
- memset(rq, 0, sizeof(*rq));
- rq->cmd = IDE_DRIVE_CMD;
-}
-
-/*
- * This function issues a special IDE device request
- * onto the request queue.
- *
- * If action is ide_wait, then the rq is queued at the end of the
- * request queue, and the function sleeps until it has been processed.
- * This is for use when invoked from an ioctl handler.
- *
- * If action is ide_preempt, then the rq is queued at the head of
- * the request queue, displacing the currently-being-processed
- * request and this function returns immediately without waiting
- * for the new rq to be completed. This is VERY DANGEROUS, and is
- * intended for careful use by the ATAPI tape/cdrom driver code.
- *
- * If action is ide_next, then the rq is queued immediately after
- * the currently-being-processed-request (if any), and the function
- * returns without waiting for the new rq to be completed. As above,
- * This is VERY DANGEROUS, and is intended for careful use by the
- * ATAPI tape/cdrom driver code.
- *
- * If action is ide_end, then the rq is queued at the end of the
- * request queue, and the function returns immediately without waiting
- * for the new rq to be completed. This is again intended for careful
- * use by the ATAPI tape/cdrom driver code.
- */
-int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action)
-{
- unsigned long flags;
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- unsigned int major = HWIF(drive)->major;
- struct list_head *queue_head = &drive->queue.queue_head;
-#if 0
- DECLARE_COMPLETION(wait);
-#else
- int wait = 1;
- int usecs = 0;
-#endif
-
-
-#ifdef CONFIG_BLK_DEV_PDC4030
- if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)
- return -ENOSYS; /* special drive cmds not supported */
-#endif
- rq->errors = 0;
- rq->rq_status = RQ_ACTIVE;
- rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS);
-
-
- if (action == ide_wait) {
- /* XXX SMH: we cannot 'block' in xen => we'll spin instead */
- rq->waiting = (void *)&wait;
- }
-
- spin_lock_irqsave(&io_request_lock, flags);
- if (list_empty(queue_head) || action == ide_preempt) {
- if (action == ide_preempt)
- hwgroup->rq = NULL;
- } else {
- if (action == ide_wait || action == ide_end) {
- queue_head = queue_head->prev;
- } else
- queue_head = queue_head->next;
- }
- list_add(&rq->queue, queue_head);
- ide_do_request(hwgroup, 0);
- spin_unlock_irqrestore(&io_request_lock, flags);
-
- /* XXX SMH: spin waiting for response */
- if (action == ide_wait) {
-
- while(wait) {
- udelay(500);
- usecs += 500;
- if(usecs > 1000000) {
- printk("ide_do_drive_cmd [ide_wait]: still waiting\n");
- usecs = 0;
- }
- }
- }
-
- return 0;
-
-}
-
-/*
- * 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)
-{
- ide_drive_t *drive;
- ide_hwgroup_t *hwgroup;
- unsigned int p, major, minor;
- unsigned long flags;
-
- if ((drive = get_info_ptr(i_rdev)) == NULL)
- return -ENODEV;
- major = MAJOR(i_rdev);
- minor = drive->select.b.unit << PARTN_BITS;
- hwgroup = HWGROUP(drive);
- spin_lock_irqsave(&io_request_lock, flags);
- if (drive->busy || (drive->usage > 1)) {
- spin_unlock_irqrestore(&io_request_lock, flags);
- return -EBUSY;
- };
- drive->busy = 1;
- MOD_INC_USE_COUNT;
- spin_unlock_irqrestore(&io_request_lock, flags);
-
- for (p = 0; p < (1<<PARTN_BITS); ++p) {
- if (drive->part[p].nr_sects > 0) {
- kdev_t devp = MKDEV(major, minor+p);
- invalidate_device(devp, 1);
- }
- drive->part[p].start_sect = 0;
- drive->part[p].nr_sects = 0;
- };
-
- if (DRIVER(drive)->revalidate)
- DRIVER(drive)->revalidate(drive);
-
- drive->busy = 0;
- /*wake_up(&drive->wqueue);*/
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static void revalidate_drives (void)
-{
- ide_hwif_t *hwif;
- ide_drive_t *drive;
- int index, unit;
-
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = &ide_hwifs[index];
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- drive = &ide_hwifs[index].drives[unit];
- if (drive->revalidate) {
- drive->revalidate = 0;
- if (!initializing)
- (void) ide_revalidate_disk(MKDEV(hwif->major, unit<<PARTN_BITS));
- }
- }
- }
-}
-
-static void ide_probe_module (void)
-{
- if (!ide_probe) {
-#if defined(CONFIG_KMOD) && defined(CONFIG_BLK_DEV_IDE_MODULE)
- (void) request_module("ide-probe-mod");
-#endif /* (CONFIG_KMOD) && (CONFIG_BLK_DEV_IDE_MODULE) */
- } else {
- (void) ide_probe->init();
- }
- revalidate_drives();
-}
-
-static void ide_driver_module (void)
-{
- int index;
- ide_module_t *module = ide_modules;
-
- for (index = 0; index < MAX_HWIFS; ++index)
- if (ide_hwifs[index].present)
- goto search;
- ide_probe_module();
-search:
- while (module) {
- (void) module->init();
- module = module->next;
- }
- revalidate_drives();
-}
-
-static int ide_open (struct inode * inode, struct file * filp)
-{
- ide_drive_t *drive;
-
- if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
- return -ENXIO;
- if (drive->driver == NULL)
- ide_driver_module();
-#ifdef CONFIG_KMOD
- if (drive->driver == NULL) {
- if (drive->media == ide_disk)
- (void) request_module("ide-disk");
- if (drive->media == ide_cdrom)
- (void) request_module("ide-cd");
- if (drive->media == ide_tape)
- (void) request_module("ide-tape");
- if (drive->media == ide_floppy)
- (void) request_module("ide-floppy");
-#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI)
- if (drive->media == ide_scsi)
- (void) request_module("ide-scsi");
-#endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */
- }
-#endif /* CONFIG_KMOD */
-#if 0
- while (drive->busy)
- sleep_on(&drive->wqueue);
-#endif
- drive->usage++;
- if (drive->driver != NULL)
- return DRIVER(drive)->open(inode, filp, drive);
- printk ("%s: driver not present\n", drive->name);
- drive->usage--;
- return -ENXIO;
-}
-
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-static int ide_release (struct inode * inode, struct file * file)
-{
- ide_drive_t *drive;
-
- if ((drive = get_info_ptr(inode->i_rdev)) != NULL) {
- drive->usage--;
- if (drive->driver != NULL)
- DRIVER(drive)->release(inode, file, drive);
- }
- return 0;
-}
-
-int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
-{
- if (!drive->present || drive->busy || drive->usage)
- goto abort;
- if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
- goto abort;
- strncpy(drive->driver_req, driver, 9);
- ide_driver_module();
- drive->driver_req[0] = 0;
- ide_driver_module();
- if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver))
- return 0;
-abort:
- return 1;
-}
-
-#ifdef CONFIG_PROC_FS
-ide_proc_entry_t generic_subdriver_entries[] = {
- { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL },
- { NULL, 0, NULL, NULL }
-};
-#endif
-
-/*
- * Note that we only release the standard ports,
- * and do not even try to handle any extra ports
- * allocated for weird IDE interface chipsets.
- */
-void hwif_unregister (ide_hwif_t *hwif)
-{
- if (hwif->straight8) {
- ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
- goto jump_eight;
- }
- if (hwif->io_ports[IDE_DATA_OFFSET])
- ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
- if (hwif->io_ports[IDE_ERROR_OFFSET])
- ide_release_region(hwif->io_ports[IDE_ERROR_OFFSET], 1);
- if (hwif->io_ports[IDE_NSECTOR_OFFSET])
- ide_release_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1);
- if (hwif->io_ports[IDE_SECTOR_OFFSET])
- ide_release_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1);
- if (hwif->io_ports[IDE_LCYL_OFFSET])
- ide_release_region(hwif->io_ports[IDE_LCYL_OFFSET], 1);
- if (hwif->io_ports[IDE_HCYL_OFFSET])
- ide_release_region(hwif->io_ports[IDE_HCYL_OFFSET], 1);
- if (hwif->io_ports[IDE_SELECT_OFFSET])
- ide_release_region(hwif->io_ports[IDE_SELECT_OFFSET], 1);
- if (hwif->io_ports[IDE_STATUS_OFFSET])
- ide_release_region(hwif->io_ports[IDE_STATUS_OFFSET], 1);
-jump_eight:
- if (hwif->io_ports[IDE_CONTROL_OFFSET])
- ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
-#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
- if (hwif->io_ports[IDE_IRQ_OFFSET])
- ide_release_region(hwif->io_ports[IDE_IRQ_OFFSET], 1);
-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
-}
-
-void ide_unregister (unsigned int index)
-{
- struct gendisk *gd;
- ide_drive_t *drive, *d;
- ide_hwif_t *hwif, *g;
- ide_hwgroup_t *hwgroup;
- int irq_count = 0, unit, i;
- unsigned long flags;
- unsigned int p, minor;
- ide_hwif_t old_hwif;
-
- if (index >= MAX_HWIFS)
- return;
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
- hwif = &ide_hwifs[index];
- if (!hwif->present)
- goto abort;
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- drive = &hwif->drives[unit];
- if (!drive->present)
- continue;
- if (drive->busy || drive->usage)
- goto abort;
- if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
- goto abort;
- }
- hwif->present = 0;
-
- /*
- * All clear? Then blow away the buffer cache
- */
- sti();
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- drive = &hwif->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 = MKDEV(hwif->major, minor+p);
- invalidate_device(devp, 0);
- }
- }
-#ifdef CONFIG_PROC_FS
- destroy_proc_ide_drives(hwif);
-#endif
- }
- cli();
- hwgroup = hwif->hwgroup;
-
- /*
- * free the irq if we were the only hwif using it
- */
- g = hwgroup->hwif;
- do {
- if (g->irq == hwif->irq)
- ++irq_count;
- g = g->next;
- } while (g != hwgroup->hwif);
- if (irq_count == 1)
- free_irq(hwif->irq, hwgroup);
-
- /*
- * Note that we only release the standard ports,
- * and do not even try to handle any extra ports
- * allocated for weird IDE interface chipsets.
- */
- hwif_unregister(hwif);
-
- /*
- * Remove us from the hwgroup, and free
- * the hwgroup if we were the only member
- */
- d = hwgroup->drive;
- for (i = 0; i < MAX_DRIVES; ++i) {
- drive = &hwif->drives[i];
-#ifdef DEVFS_MUST_DIE
- if (drive->de) {
- devfs_unregister (drive->de);
- drive->de = NULL;
- }
-#endif
- if (!drive->present)
- continue;
- while (hwgroup->drive->next != drive)
- hwgroup->drive = hwgroup->drive->next;
- hwgroup->drive->next = drive->next;
- if (hwgroup->drive == drive)
- hwgroup->drive = NULL;
- if (drive->id != NULL) {
- kfree(drive->id);
- drive->id = NULL;
- }
- drive->present = 0;
- blk_cleanup_queue(&drive->queue);
- }
- if (d->present)
- hwgroup->drive = d;
- while (hwgroup->hwif->next != hwif)
- hwgroup->hwif = hwgroup->hwif->next;
- hwgroup->hwif->next = hwif->next;
- if (hwgroup->hwif == hwif)
- kfree(hwgroup);
- else
- hwgroup->hwif = HWIF(hwgroup->drive);
-
-#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
- if (hwif->dma_base) {
- (void) ide_release_dma(hwif);
- hwif->dma_base = 0;
- }
-#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
-
- /*
- * Remove us from the kernel's knowledge
- */
- unregister_blkdev(hwif->major, hwif->name);
- kfree(blksize_size[hwif->major]);
- kfree(max_sectors[hwif->major]);
- /*kfree(max_readahead[hwif->major]);*/
- blk_dev[hwif->major].data = NULL;
- blk_dev[hwif->major].queue = NULL;
- blksize_size[hwif->major] = NULL;
- gd = hwif->gd;
- if (gd) {
- del_gendisk(gd);
- kfree(gd->sizes);
- kfree(gd->part);
-#ifdef DEVFS_MUST_DIE
- if (gd->de_arr)
- kfree (gd->de_arr);
-#endif
- if (gd->flags)
- kfree (gd->flags);
- kfree(gd);
- hwif->gd = NULL;
- }
- old_hwif = *hwif;
- init_hwif_data (index); /* restore hwif data to pristine status */
- hwif->hwgroup = old_hwif.hwgroup;
- hwif->tuneproc = old_hwif.tuneproc;
- hwif->speedproc = old_hwif.speedproc;
- hwif->selectproc = old_hwif.selectproc;
- hwif->resetproc = old_hwif.resetproc;
- hwif->intrproc = old_hwif.intrproc;
- hwif->maskproc = old_hwif.maskproc;
- hwif->quirkproc = old_hwif.quirkproc;
- hwif->rwproc = old_hwif.rwproc;
- hwif->ideproc = old_hwif.ideproc;
- hwif->dmaproc = old_hwif.dmaproc;
- hwif->busproc = old_hwif.busproc;
- hwif->bus_state = old_hwif.bus_state;
- hwif->dma_base = old_hwif.dma_base;
- hwif->dma_extra = old_hwif.dma_extra;
- hwif->config_data = old_hwif.config_data;
- hwif->select_data = old_hwif.select_data;
- hwif->proc = old_hwif.proc;
-#ifndef CONFIG_BLK_DEV_IDECS
- hwif->irq = old_hwif.irq;
-#endif /* CONFIG_BLK_DEV_IDECS */
- hwif->major = old_hwif.major;
- hwif->chipset = old_hwif.chipset;
- hwif->autodma = old_hwif.autodma;
- hwif->udma_four = old_hwif.udma_four;
-#ifdef CONFIG_BLK_DEV_IDEPCI
- hwif->pci_dev = old_hwif.pci_dev;
- hwif->pci_devid = old_hwif.pci_devid;
-#endif /* CONFIG_BLK_DEV_IDEPCI */
- hwif->straight8 = old_hwif.straight8;
- hwif->hwif_data = old_hwif.hwif_data;
-abort:
- restore_flags(flags); /* all CPUs */
-}
-
-/*
- * Setup hw_regs_t structure described by parameters. You
- * may set up the hw structure yourself OR use this routine to
- * do it for you.
- */
-void ide_setup_ports ( hw_regs_t *hw,
- ide_ioreg_t base, int *offsets,
- ide_ioreg_t ctrl, ide_ioreg_t intr,
- ide_ack_intr_t *ack_intr, int irq)
-{
- int i;
-
- for (i = 0; i < IDE_NR_PORTS; i++) {
- if (offsets[i] == -1) {
- switch(i) {
- case IDE_CONTROL_OFFSET:
- hw->io_ports[i] = ctrl;
- break;
-#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
- case IDE_IRQ_OFFSET:
- hw->io_ports[i] = intr;
- break;
-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
- default:
- hw->io_ports[i] = 0;
- break;
- }
- } else {
- hw->io_ports[i] = base + offsets[i];
- }
- }
- hw->irq = irq;
- hw->dma = NO_DMA;
- hw->ack_intr = ack_intr;
-}
-
-/*
- * 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, ide_hwif_t **hwifp)
-{
- int index, retry = 1;
- ide_hwif_t *hwif;
-
- do {
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = &ide_hwifs[index];
- if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
- goto found;
- }
- for (index = 0; index < MAX_HWIFS; ++index) {
- hwif = &ide_hwifs[index];
- if ((!hwif->present && !hwif->mate && !initializing) ||
- (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
- goto found;
- }
- for (index = 0; index < MAX_HWIFS; index++)
- ide_unregister(index);
- } while (retry--);
- return -1;
-found:
- if (hwif->present)
- ide_unregister(index);
- if (hwif->present)
- return -1;
- memcpy(&hwif->hw, hw, sizeof(*hw));
- memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
- hwif->irq = hw->irq;
- hwif->noprobe = 0;
- hwif->chipset = hw->chipset;
-
- if (!initializing) {
- ide_probe_module();
-#ifdef CONFIG_PROC_FS
- create_proc_ide_interfaces();
-#endif
- ide_driver_module();
- }
-
- if (hwifp)
- *hwifp = hwif;
-
- return (initializing || hwif->present) ? index : -1;
-}
-
-/*
- * Compatability function with 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);
-}
-
-void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
-{
- ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
-
- while ((*p) && strcmp((*p)->name, name) < 0)
- p = &((*p)->next);
- if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
- goto abort;
- memset(setting, 0, sizeof(*setting));
- if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
- goto abort;
- strcpy(setting->name, name); setting->rw = rw;
- setting->read_ioctl = read_ioctl; setting->write_ioctl = write_ioctl;
- setting->data_type = data_type; setting->min = min;
- setting->max = max; setting->mul_factor = mul_factor;
- setting->div_factor = div_factor; setting->data = data;
- setting->set = set; setting->next = *p;
- if (drive->driver)
- setting->auto_remove = 1;
- *p = setting;
- return;
-abort:
- if (setting)
- kfree(setting);
-}
-
-void ide_remove_setting (ide_drive_t *drive, char *name)
-{
- ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting;
-
- while ((*p) && strcmp((*p)->name, name))
- p = &((*p)->next);
- if ((setting = (*p)) == NULL)
- return;
- (*p) = setting->next;
- kfree(setting->name);
- kfree(setting);
-}
-
-static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd)
-{
- ide_settings_t *setting = drive->settings;
-
- while (setting) {
- if (setting->read_ioctl == cmd || setting->write_ioctl == cmd)
- break;
- setting = setting->next;
- }
- return setting;
-}
-
-ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name)
-{
- ide_settings_t *setting = drive->settings;
-
- while (setting) {
- if (strcmp(setting->name, name) == 0)
- break;
- setting = setting->next;
- }
- return setting;
-}
-
-static void auto_remove_settings (ide_drive_t *drive)
-{
- ide_settings_t *setting;
-repeat:
- setting = drive->settings;
- while (setting) {
- if (setting->auto_remove) {
- ide_remove_setting(drive, setting->name);
- goto repeat;
- }
- setting = setting->next;
- }
-}
-
-int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting)
-{
- int val = -EINVAL;
- unsigned long flags;
-
- if ((setting->rw & SETTING_READ)) {
- spin_lock_irqsave(&io_request_lock, flags);
- switch(setting->data_type) {
- case TYPE_BYTE:
- val = *((u8 *) setting->data);
- break;
- case TYPE_SHORT:
- val = *((u16 *) setting->data);
- break;
- case TYPE_INT:
- case TYPE_INTA:
- val = *((u32 *) setting->data);
- break;
- }
- spin_unlock_irqrestore(&io_request_lock, flags);
- }
- return val;
-}
-
-int ide_spin_wait_hwgroup (ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- unsigned long timeout = jiffies + (3 * HZ);
-
- spin_lock_irq(&io_request_lock);
-
- while (hwgroup->busy) {
- unsigned long lflags;
- spin_unlock_irq(&io_request_lock);
- __save_flags(lflags); /* local CPU only */
- __sti(); /* local CPU only; needed for jiffies */
- if (0 < (signed long)(jiffies - timeout)) {
- __restore_flags(lflags); /* local CPU only */
- printk("%s: channel busy\n", drive->name);
- return -EBUSY;
- }
- __restore_flags(lflags); /* local CPU only */
- spin_lock_irq(&io_request_lock);
- }
- return 0;
-}
-
-/*
- * FIXME: This should be changed to enqueue a special request
- * to the driver to change settings, and then wait on a sema for completion.
- * The current scheme of polling is kludgey, though safe enough.
- */
-int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
-{
- int i;
- u32 *p;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (!(setting->rw & SETTING_WRITE))
- return -EPERM;
- if (val < setting->min || val > setting->max)
- return -EINVAL;
- if (setting->set)
- return setting->set(drive, val);
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
- switch (setting->data_type) {
- case TYPE_BYTE:
- *((u8 *) setting->data) = val;
- break;
- case TYPE_SHORT:
- *((u16 *) setting->data) = val;
- break;
- case TYPE_INT:
- *((u32 *) setting->data) = val;
- break;
- case TYPE_INTA:
- p = (u32 *) setting->data;
- for (i = 0; i < 1 << PARTN_BITS; i++, p++)
- *p = val;
- break;
- }
- spin_unlock_irq(&io_request_lock);
- return 0;
-}
-
-static int set_io_32bit(ide_drive_t *drive, int arg)
-{
- drive->io_32bit = arg;
-#ifdef CONFIG_BLK_DEV_DTC2278
- if (HWIF(drive)->chipset == ide_dtc2278)
- HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
-#endif /* CONFIG_BLK_DEV_DTC2278 */
- return 0;
-}
-
-static int set_using_dma (ide_drive_t *drive, int arg)
-{
- if (!drive->driver || !DRIVER(drive)->supports_dma)
- return -EPERM;
- if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc)
- return -EPERM;
- if (HWIF(drive)->dmaproc(arg ? ide_dma_on : ide_dma_off, drive))
- return -EIO;
- return 0;
-}
-
-static int set_pio_mode (ide_drive_t *drive, int arg)
-{
- struct request rq;
-
- if (!HWIF(drive)->tuneproc)
- return -ENOSYS;
- if (drive->special.b.set_tune)
- return -EBUSY;
- ide_init_drive_cmd(&rq);
- drive->tune_req = (byte) arg;
- drive->special.b.set_tune = 1;
- (void) ide_do_drive_cmd (drive, &rq, ide_wait);
- return 0;
-}
-
-void ide_add_generic_settings (ide_drive_t *drive)
-{
-/*
- * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function
- */
- ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit);
- ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL);
- ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL);
- ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode);
- ide_add_setting(drive, "slow", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->slow, NULL);
- ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL);
- ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma);
- ide_add_setting(drive, "ide_scsi", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, NULL);
- ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->init_speed, NULL);
- ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->current_speed, NULL);
- ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL);
-}
-
-int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf)
-{
- struct request rq;
- byte buffer[4];
-
- if (!buf)
- buf = buffer;
- memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);
- ide_init_drive_cmd(&rq);
- rq.buffer = buf;
- *buf++ = cmd;
- *buf++ = nsect;
- *buf++ = feature;
- *buf++ = sectors;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
-
-int ide_wait_cmd_task (ide_drive_t *drive, byte *buf)
-{
- struct request rq;
-
- ide_init_drive_cmd(&rq);
- rq.cmd = IDE_DRIVE_TASK;
- rq.buffer = buf;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
-
-/*
- * Delay for *at least* 50ms. As we don't know how much time is left
- * until the next tick occurs, we wait an extra tick to be safe.
- * This is used only during the probing/polling for drives at boot time.
- *
- * However, its usefullness may be needed in other places, thus we export it now.
- * The future may change this to a millisecond setable delay.
- */
-void ide_delay_50ms (void)
-{
-#ifndef CONFIG_BLK_DEV_IDECS
- mdelay(50);
-#else
- __set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/20);
-#endif /* CONFIG_BLK_DEV_IDECS */
-}
-
-int system_bus_clock (void)
-{
- return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
-}
-
-int ide_reinit_drive (ide_drive_t *drive)
-{
- switch (drive->media) {
-#ifdef CONFIG_BLK_DEV_IDECD
- case ide_cdrom:
- {
- extern int ide_cdrom_reinit(ide_drive_t *drive);
- if (ide_cdrom_reinit(drive))
- return 1;
- break;
- }
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDEDISK
- case ide_disk:
- {
- extern int idedisk_reinit(ide_drive_t *drive);
- if (idedisk_reinit(drive))
- return 1;
- break;
- }
-#endif /* CONFIG_BLK_DEV_IDEDISK */
-#ifdef CONFIG_BLK_DEV_IDEFLOPPY
- case ide_floppy:
- {
- extern int idefloppy_reinit(ide_drive_t *drive);
- if (idefloppy_reinit(drive))
- return 1;
- break;
- }
-#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
-#ifdef CONFIG_BLK_DEV_IDETAPE
- case ide_tape:
- {
- extern int idetape_reinit(ide_drive_t *drive);
- if (idetape_reinit(drive))
- return 1;
- break;
- }
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-#ifdef CONFIG_BLK_DEV_IDESCSI
-/*
- * {
- * extern int idescsi_reinit(ide_drive_t *drive);
- * if (idescsi_reinit(drive))
- * return 1;
- * break;
- * }
- */
-#endif /* CONFIG_BLK_DEV_IDESCSI */
- default:
- return 1;
- }
- return 0;
-}
-
-static int ide_ioctl (struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- int err = 0, major, minor;
- ide_drive_t *drive;
- struct request rq;
- kdev_t dev;
- ide_settings_t *setting;
-
- if (!inode || !(dev = inode->i_rdev))
- return -EINVAL;
- major = MAJOR(dev); minor = MINOR(dev);
- if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
- return -ENODEV;
-
- if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) {
- if (cmd == setting->read_ioctl) {
- err = ide_read_setting(drive, setting);
- return err >= 0 ? put_user(err, (long *) arg) : err;
- } else {
- if ((MINOR(inode->i_rdev) & PARTN_MASK))
- return -EINVAL;
- return ide_write_setting(drive, setting, arg);
- }
- }
-
- ide_init_drive_cmd (&rq);
- switch (cmd) {
- case HDIO_GETGEO:
- {
- struct hd_geometry *loc = (struct hd_geometry *) arg;
- unsigned short bios_cyl = drive->bios_cyl; /* truncate */
- if (!loc || (drive->media != ide_disk && drive->media != ide_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:
- {
- struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;
- if (!loc || (drive->media != ide_disk && drive->media != ide_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(drive->bios_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 HDIO_GETGEO_BIG_RAW:
- {
- struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;
- if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;
- if (put_user(drive->head, (byte *) &loc->heads)) return -EFAULT;
- if (put_user(drive->sect, (byte *) &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;
- }
-
-#if 0
- case BLKGETSIZE: /* Return device size */
- return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (unsigned long *) arg);
- case BLKGETSIZE64:
- return put_user((u64)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects << 9, (u64 *) arg);
-
- case BLKRRPART: /* Re-read partition tables */
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- return ide_revalidate_disk(inode->i_rdev);
-#endif
-
- case HDIO_OBSOLETE_IDENTITY:
- 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, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
- 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 |
- drive->nice0 << IDE_NICE_0 |
- drive->nice1 << IDE_NICE_1 |
- drive->nice2 << IDE_NICE_2,
- (long *) arg);
-
-#ifdef CONFIG_IDE_TASK_IOCTL
- case HDIO_DRIVE_TASKFILE:
- if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- return -EACCES;
- switch(drive->media) {
- case ide_disk:
- return ide_taskfile_ioctl(drive, inode, file, cmd, arg);
-#ifdef CONFIG_PKT_TASK_IOCTL
- case ide_cdrom:
- case ide_tape:
- case ide_floppy:
- return pkt_taskfile_ioctl(drive, inode, file, cmd, arg);
-#endif /* CONFIG_PKT_TASK_IOCTL */
- default:
- return -ENOMSG;
- }
-#endif /* CONFIG_IDE_TASK_IOCTL */
-
- case HDIO_DRIVE_CMD:
- {
- byte args[4], *argbuf = args;
- byte xfer_rate = 0;
- int argsize = 4;
- ide_task_t tfargs;
-
- if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- return -EACCES;
- if (NULL == (void *) arg)
- return ide_do_drive_cmd(drive, &rq, ide_wait);
- if (copy_from_user(args, (void *)arg, 4))
- return -EFAULT;
-
- tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
- tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
- tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1];
- tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00;
- tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00;
- tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00;
- tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
-
- if (args[3]) {
- argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
- argbuf = kmalloc(argsize, GFP_KERNEL);
- if (argbuf == NULL)
- return -ENOMEM;
- memcpy(argbuf, args, 4);
- }
-
- if (set_transfer(drive, &tfargs)) {
- xfer_rate = args[1];
- if (ide_ata66_check(drive, &tfargs))
- goto abort;
- }
-
- err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
-
- if (!err && xfer_rate) {
- /* active-retuning-calls future */
- if ((HWIF(drive)->speedproc) != NULL)
- HWIF(drive)->speedproc(drive, xfer_rate);
- ide_driveid_update(drive);
- }
- abort:
- if (copy_to_user((void *)arg, argbuf, argsize))
- err = -EFAULT;
- if (argsize > 4)
- kfree(argbuf);
- return err;
- }
- case HDIO_DRIVE_TASK:
- {
- byte args[7], *argbuf = args;
- int argsize = 7;
- if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES;
- if (copy_from_user(args, (void *)arg, 7))
- return -EFAULT;
- err = ide_wait_cmd_task(drive, argbuf);
- if (copy_to_user((void *)arg, argbuf, argsize))
- err = -EFAULT;
- return err;
- }
- case HDIO_SCAN_HWIF:
- {
- int args[3];
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- if (copy_from_user(args, (void *)arg, 3 * sizeof(int)))
- return -EFAULT;
- if (ide_register(args[0], args[1], args[2]) == -1)
- return -EIO;
- return 0;
- }
- case HDIO_UNREGISTER_HWIF:
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- /* (arg > MAX_HWIFS) checked in function */
- ide_unregister(arg);
- return 0;
- case HDIO_SET_NICE:
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- if (drive->driver == NULL)
- return -EPERM;
- if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
- return -EPERM;
- drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
- if (drive->dsc_overlap && !DRIVER(drive)->supports_dsc_overlap) {
- drive->dsc_overlap = 0;
- return -EPERM;
- }
- drive->nice1 = (arg >> IDE_NICE_1) & 1;
- return 0;
- case HDIO_DRIVE_RESET:
- {
- unsigned long flags;
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
-
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-#if 1
- spin_lock_irqsave(&io_request_lock, flags);
- if (hwgroup->handler != NULL) {
- printk("%s: ide_set_handler: handler not null; %p\n", drive->name, hwgroup->handler);
- (void) hwgroup->handler(drive);
-// hwgroup->handler = NULL;
-// hwgroup->expiry = NULL;
- hwgroup->timer.expires = jiffies + 0;;
- del_timer(&hwgroup->timer);
- }
- spin_unlock_irqrestore(&io_request_lock, flags);
-
-#endif
- (void) ide_do_reset(drive);
- if (drive->suspend_reset) {
-/*
- * APM WAKE UP todo !!
- * int nogoodpower = 1;
- * while(nogoodpower) {
- * check_power1() or check_power2()
- * nogoodpower = 0;
- * }
- * HWIF(drive)->multiproc(drive);
- */
- return ide_revalidate_disk(inode->i_rdev);
- }
- return 0;
- }
-#if 0
- case BLKROSET:
- case BLKROGET:
- case BLKFLSBUF:
- case BLKSSZGET:
- case BLKPG:
- case BLKELVGET:
- case BLKELVSET:
- case BLKBSZGET:
- case BLKBSZSET:
- return blk_ioctl(inode->i_rdev, cmd, arg);
-#endif
-
- case HDIO_GET_BUSSTATE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (put_user(HWIF(drive)->bus_state, (long *)arg))
- return -EFAULT;
- return 0;
-
- case HDIO_SET_BUSSTATE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (HWIF(drive)->busproc)
- HWIF(drive)->busproc(drive, (int)arg);
- return 0;
-
- default:
- if (drive->driver != NULL)
- return DRIVER(drive)->ioctl(drive, inode, file, cmd, arg);
- return -EPERM;
- }
-}
-
-static int ide_check_media_change (kdev_t i_rdev)
-{
- ide_drive_t *drive;
-
- if ((drive = get_info_ptr(i_rdev)) == NULL)
- return -ENODEV;
- if (drive->driver != NULL)
- return DRIVER(drive)->media_change(drive);
- return 0;
-}
-
-void ide_fixstring (byte *s, const int bytecount, const int byteswap)
-{
- byte *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */
-
- if (byteswap) {
- /* convert from big-endian to host byte order */
- for (p = end ; p != s;) {
- unsigned short *pp = (unsigned short *) (p -= 2);
- *pp = ntohs(*pp);
- }
- }
-
- /* strip leading blanks */
- while (s != end && *s == ' ')
- ++s;
-
- /* compress internal blanks and strip trailing blanks */
- while (s != end && *s) {
- if (*s++ != ' ' || (s != end && *s && *s != ' '))
- *p++ = *(s-1);
- }
-
- /* wipe out trailing garbage */
- while (p != end)
- *p++ = '\0';
-}
-
-/*
- * 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;
-}
-
-/*
- * match_parm() does 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 */
-}
-
-/*
- * ide_setup() gets called VERY EARLY during initialization,
- * to handle kernel "command line" strings beginning with "hdx="
- * or "ide". Here is the complete set currently supported:
- *
- * "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.
- *
- * "hdx=swapdata" : when the drive is a disk, byte swap all data
- * "hdx=bswap" : same as above..........
- * "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=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 addr 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];
- ide_hwif_t *hwif;
- ide_drive_t *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",2) == 0 && s[2] == '=') /* hd= is for hd.c */
- return 0; /* driver and not us */
-
- if (strncmp(s,"ide",3) &&
- strncmp(s,"idebus",6) &&
- strncmp(s,"hd",2)) /* hdx= & hdxlun= */
- return 0;
-
- printk("ide_setup: %s", s);
- init_ide_data ();
-
-#ifdef CONFIG_BLK_DEV_IDEDOUBLER
- if (!strcmp(s, "ide=doubler")) {
- extern int ide_doubler;
-
- printk(" : Enabled support for IDE doublers\n");
- ide_doubler = 1;
- return 1;
- }
-#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
-
- if (!strcmp(s, "ide=nodma")) {
- printk("IDE: Prevented DMA\n");
- noautodma = 1;
- return 1;
- }
-
-#ifdef CONFIG_BLK_DEV_IDEPCI
- if (!strcmp(s, "ide=reverse")) {
- ide_scan_direction = 1;
- printk(" : Enabled support for IDE inverse scan order.\n");
- return 1;
- }
-#endif /* CONFIG_BLK_DEV_IDEPCI */
-
- /*
- * Look for drive options: "hdx="
- */
- if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
- const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom",
- "serialize", "autotune", "noautotune",
- "slow", "swapdata", "bswap", "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) == 0) {
- strncpy(drive->driver_req, s + 4, 9);
- goto done;
- }
- /*
- * Look for last lun option: "hdxlun="
- */
- if (s[3] == 'l' && s[4] == 'u' && s[5] == 'n') {
- 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->media = ide_cdrom;
- 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" */
- drive->slow = 1;
- goto done;
- case -9: /* "swapdata" or "bswap" */
- case -10:
- drive->bswap = 1;
- goto done;
- case -11: /* "flash" */
- drive->ata_flash = 1;
- goto done;
- case -12: /* "remap" */
- drive->remap_0_to_1 = 1;
- goto done;
- case -13: /* "noremap" */
- drive->remap_0_to_1 = 2;
- goto done;
- case -14: /* "scsi" */
-#if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI)
- drive->scsi = 1;
- goto done;
-#else
- drive->scsi = 0;
- goto bad_option;
-#endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */
- case 3: /* cyl,head,sect */
- drive->media = ide_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;
- }
- }
-
- if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e')
- goto bad_option;
- /*
- * Look for bus speed option: "idebus="
- */
- if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') {
- if (match_parm(&s[6], NULL, vals, 1) != 1)
- goto bad_option;
- if (vals[0] >= 20 && vals[0] <= 66) {
- idebus_parameter = vals[0];
- } else
- printk(" -- BAD BUS SPEED! Expected value from 20 to 66");
- goto done;
- }
- /*
- * Look for interface options: "idex="
- */
- if (s[3] >= '0' && s[3] <= max_hwif) {
- /*
- * Be VERY CAREFUL changing this: note hardcoded indexes below
- * -8,-9,-10 : are reserved for future idex calls to ease the hardcoding.
- */
- const char *ide_words[] = {
- "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66",
- "minus8", "minus9", "minus10",
- "four", "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 /* CONFIG_BLK_DEV_PDC4030 */
-#ifdef CONFIG_BLK_DEV_ALI14XX
- case -17: /* "ali14xx" */
- {
- extern void init_ali14xx (void);
- init_ali14xx();
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_ALI14XX */
-#ifdef CONFIG_BLK_DEV_UMC8672
- case -16: /* "umc8672" */
- {
- extern void init_umc8672 (void);
- init_umc8672();
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_UMC8672 */
-#ifdef CONFIG_BLK_DEV_DTC2278
- case -15: /* "dtc2278" */
- {
- extern void init_dtc2278 (void);
- init_dtc2278();
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_DTC2278 */
-#ifdef CONFIG_BLK_DEV_CMD640
- case -14: /* "cmd640_vlb" */
- {
- extern int cmd640_vlb; /* flag for cmd640.c */
- cmd640_vlb = 1;
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_CMD640 */
-#ifdef CONFIG_BLK_DEV_HT6560B
- case -13: /* "ht6560b" */
- {
- extern void init_ht6560b (void);
- init_ht6560b();
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_HT6560B */
-#if CONFIG_BLK_DEV_QD65XX
- case -12: /* "qd65xx" */
- {
- extern void init_qd65xx (void);
- init_qd65xx();
- goto done;
- }
-#endif /* CONFIG_BLK_DEV_QD65XX */
-#ifdef CONFIG_BLK_DEV_4DRIVES
- case -11: /* "four" drives on one set of ports */
- {
- ide_hwif_t *mate = &ide_hwifs[hw^1];
- mate->drives[0].select.all ^= 0x20;
- mate->drives[1].select.all ^= 0x20;
- hwif->chipset = mate->chipset = ide_4drives;
- mate->irq = hwif->irq;
- memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports));
- goto do_serialize;
- }
-#endif /* CONFIG_BLK_DEV_4DRIVES */
- case -10: /* minus10 */
- case -9: /* minus9 */
- case -8: /* minus8 */
- goto bad_option;
- case -7: /* ata66 */
-#ifdef CONFIG_BLK_DEV_IDEPCI
- hwif->udma_four = 1;
- goto done;
-#else /* !CONFIG_BLK_DEV_IDEPCI */
- hwif->udma_four = 0;
- goto bad_hwif;
-#endif /* CONFIG_BLK_DEV_IDEPCI */
- 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:
- hwif->mate = &ide_hwifs[hw^1];
- hwif->mate->mate = hwif;
- hwif->serialized = hwif->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;
-}
-
-/*
- * probe_for_hwifs() finds/initializes "known" IDE interfaces
- */
-static void __init probe_for_hwifs (void)
-{
-#ifdef CONFIG_PCI
- if (pci_present())
- {
-#ifdef CONFIG_BLK_DEV_IDEPCI
- ide_scan_pcibus(ide_scan_direction);
-#else
-#ifdef CONFIG_BLK_DEV_RZ1000
- {
- extern void ide_probe_for_rz100x(void);
- ide_probe_for_rz100x();
- }
-#endif /* CONFIG_BLK_DEV_RZ1000 */
-#endif /* CONFIG_BLK_DEV_IDEPCI */
- }
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_ETRAX_IDE
- {
- extern void init_e100_ide(void);
- init_e100_ide();
- }
-#endif /* CONFIG_ETRAX_IDE */
-#ifdef CONFIG_BLK_DEV_CMD640
- {
- extern void ide_probe_for_cmd640x(void);
- ide_probe_for_cmd640x();
- }
-#endif /* CONFIG_BLK_DEV_CMD640 */
-#ifdef CONFIG_BLK_DEV_PDC4030
- {
- extern int ide_probe_for_pdc4030(void);
- (void) ide_probe_for_pdc4030();
- }
-#endif /* CONFIG_BLK_DEV_PDC4030 */
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
- {
- extern void pmac_ide_probe(void);
- pmac_ide_probe();
- }
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#ifdef CONFIG_BLK_DEV_IDE_SWARM
- {
- extern void swarm_ide_probe(void);
- swarm_ide_probe();
- }
-#endif /* CONFIG_BLK_DEV_IDE_SWARM */
-#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
- {
- extern void icside_init(void);
- icside_init();
- }
-#endif /* CONFIG_BLK_DEV_IDE_ICSIDE */
-#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
- {
- extern void rapide_init(void);
- rapide_init();
- }
-#endif /* CONFIG_BLK_DEV_IDE_RAPIDE */
-#ifdef CONFIG_BLK_DEV_GAYLE
- {
- extern void gayle_init(void);
- gayle_init();
- }
-#endif /* CONFIG_BLK_DEV_GAYLE */
-#ifdef CONFIG_BLK_DEV_FALCON_IDE
- {
- extern void falconide_init(void);
- falconide_init();
- }
-#endif /* CONFIG_BLK_DEV_FALCON_IDE */
-#ifdef CONFIG_BLK_DEV_MAC_IDE
- {
- extern void macide_init(void);
- macide_init();
- }
-#endif /* CONFIG_BLK_DEV_MAC_IDE */
-#ifdef CONFIG_BLK_DEV_Q40IDE
- {
- extern void q40ide_init(void);
- q40ide_init();
- }
-#endif /* CONFIG_BLK_DEV_Q40IDE */
-#ifdef CONFIG_BLK_DEV_BUDDHA
- {
- extern void buddha_init(void);
- buddha_init();
- }
-#endif /* CONFIG_BLK_DEV_BUDDHA */
-#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP)
- {
- extern void pnpide_init(int enable);
- pnpide_init(1);
- }
-#endif /* CONFIG_BLK_DEV_ISAPNP */
-}
-
-void __init ide_init_builtin_drivers (void)
-{
- /*
- * Probe for special PCI and other "known" interface chipsets
- */
- probe_for_hwifs ();
-
-#ifdef CONFIG_BLK_DEV_IDE
-#if defined(__mc68000__) || defined(CONFIG_APUS)
- if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
- ide_get_lock(&ide_lock, NULL, NULL); /* for atari only */
- disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */
-// disable_irq_nosync(ide_hwifs[0].irq);
- }
-#endif /* __mc68000__ || CONFIG_APUS */
-
- (void) 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(&ide_lock); /* for atari only */
- }
-#endif /* __mc68000__ || CONFIG_APUS */
-#endif /* CONFIG_BLK_DEV_IDE */
-
-#ifdef CONFIG_PROC_FS
- proc_ide_create();
-#endif
-
- /*
- * Attempt to match drivers for the available drives
- */
-#ifdef CONFIG_BLK_DEV_IDEDISK
- (void) idedisk_init();
-#endif /* CONFIG_BLK_DEV_IDEDISK */
-#ifdef CONFIG_BLK_DEV_IDECD
- (void) ide_cdrom_init();
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
- (void) idetape_init();
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-#ifdef CONFIG_BLK_DEV_IDEFLOPPY
- (void) idefloppy_init();
-#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
-#ifdef CONFIG_BLK_DEV_IDESCSI
- #ifdef CONFIG_SCSI
- (void) idescsi_init();
- #else
- #warning ide scsi-emulation selected but no SCSI-subsystem in kernel
- #endif
-#endif /* CONFIG_BLK_DEV_IDESCSI */
-}
-
-static int default_cleanup (ide_drive_t *drive)
-{
- return ide_unregister_subdriver(drive);
-}
-
-static int default_standby (ide_drive_t *drive)
-{
- return 0;
-}
-
-static int default_flushcache (ide_drive_t *drive)
-{
- return 0;
-}
-
-static ide_startstop_t default_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
-{
- ide_end_request(0, HWGROUP(drive));
- return ide_stopped;
-}
-
-static void default_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
-{
- ide_end_request(uptodate, hwgroup);
-}
-
-static int default_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -EIO;
-}
-
-static int default_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- drive->usage--;
- return -EIO;
-}
-
-static void default_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
-}
-
-static int default_check_media_change (ide_drive_t *drive)
-{
- return 1;
-}
-
-static void default_pre_reset (ide_drive_t *drive)
-{
-}
-
-static unsigned long default_capacity (ide_drive_t *drive)
-{
- return 0x7fffffff;
-}
-
-static ide_startstop_t default_special (ide_drive_t *drive)
-{
- special_t *s = &drive->special;
-
- s->all = 0;
- drive->mult_req = 0;
- return ide_stopped;
-}
-
-static int default_reinit (ide_drive_t *drive)
-{
- printk(KERN_ERR "%s: does not support hotswap of device class !\n", drive->name);
-
- return 0;
-}
-
-static void setup_driver_defaults (ide_drive_t *drive)
-{
- ide_driver_t *d = drive->driver;
-
- if (d->cleanup == NULL) d->cleanup = default_cleanup;
- if (d->standby == NULL) d->standby = default_standby;
- if (d->flushcache == NULL) d->flushcache = default_flushcache;
- if (d->do_request == NULL) d->do_request = default_do_request;
- if (d->end_request == NULL) d->end_request = default_end_request;
- if (d->ioctl == NULL) d->ioctl = default_ioctl;
- if (d->open == NULL) d->open = default_open;
- if (d->release == NULL) d->release = default_release;
- if (d->media_change == NULL) d->media_change = default_check_media_change;
- if (d->pre_reset == NULL) d->pre_reset = default_pre_reset;
- if (d->capacity == NULL) d->capacity = default_capacity;
- if (d->special == NULL) d->special = default_special;
- if (d->reinit == NULL) d->reinit = default_reinit;
-}
-
-ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n)
-{
- unsigned int unit, index, i;
-
- for (index = 0, i = 0; index < MAX_HWIFS; ++index) {
- ide_hwif_t *hwif = &ide_hwifs[index];
- if (!hwif->present)
- continue;
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- char *req = drive->driver_req;
- if (*req && !strstr(name, req))
- continue;
- if (drive->present && drive->media == media && drive->driver == driver && ++i > n)
- return drive;
- }
- }
- return NULL;
-}
-
-int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version)
-{
- unsigned long flags;
-
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
- if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL || drive->busy || drive->usage) {
- restore_flags(flags); /* all CPUs */
- return 1;
- }
- drive->driver = driver;
- setup_driver_defaults(drive);
- restore_flags(flags); /* all CPUs */
- if (drive->autotune != 2) {
- if (driver->supports_dma && HWIF(drive)->dmaproc != NULL) {
- /*
- * Force DMAing for the beginning of the check.
- * Some chipsets appear to do interesting things,
- * if not checked and cleared.
- * PARANOIA!!!
- */
- (void) (HWIF(drive)->dmaproc(ide_dma_off_quietly, drive));
- (void) (HWIF(drive)->dmaproc(ide_dma_check, drive));
- }
- drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap);
- drive->nice1 = 1;
- }
- drive->revalidate = 1;
- drive->suspend_reset = 0;
-#ifdef CONFIG_PROC_FS
- ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive);
- ide_add_proc_entries(drive->proc, driver->proc, drive);
-#endif
- return 0;
-}
-
-int ide_unregister_subdriver (ide_drive_t *drive)
-{
- unsigned long flags;
-
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
- if (drive->usage || drive->busy || drive->driver == NULL || DRIVER(drive)->busy) {
- restore_flags(flags); /* all CPUs */
- return 1;
- }
-#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE)
- pnpide_init(0);
-#endif /* CONFIG_BLK_DEV_ISAPNP */
-#ifdef CONFIG_PROC_FS
- ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc);
- ide_remove_proc_entries(drive->proc, generic_subdriver_entries);
-#endif
- auto_remove_settings(drive);
- drive->driver = NULL;
- restore_flags(flags); /* all CPUs */
- return 0;
-}
-
-int ide_register_module (ide_module_t *module)
-{
- ide_module_t *p = ide_modules;
-
- while (p) {
- if (p == module)
- return 1;
- p = p->next;
- }
- module->next = ide_modules;
- ide_modules = module;
- revalidate_drives();
- return 0;
-}
-
-void ide_unregister_module (ide_module_t *module)
-{
- ide_module_t **p;
-
- for (p = &ide_modules; (*p) && (*p) != module; p = &((*p)->next));
- if (*p)
- *p = (*p)->next;
-}
-
-struct block_device_operations ide_fops[] = {{
- open: ide_open,
- release: ide_release,
- ioctl: ide_ioctl,
- check_media_change: ide_check_media_change,
- revalidate: ide_revalidate_disk
-}};
-
-EXPORT_SYMBOL(ide_hwifs);
-EXPORT_SYMBOL(ide_register_module);
-EXPORT_SYMBOL(ide_unregister_module);
-EXPORT_SYMBOL(ide_spin_wait_hwgroup);
-
-/*
- * Probe module
- */
-#ifdef DEVFS_MUST_DIE
-devfs_handle_t ide_devfs_handle;
-#endif
-
-EXPORT_SYMBOL(ide_probe);
-EXPORT_SYMBOL(drive_is_flashcard);
-EXPORT_SYMBOL(ide_timer_expiry);
-EXPORT_SYMBOL(ide_intr);
-EXPORT_SYMBOL(ide_fops);
-EXPORT_SYMBOL(ide_get_queue);
-EXPORT_SYMBOL(ide_add_generic_settings);
-#ifdef DEVFS_MUST_DIE
-EXPORT_SYMBOL(ide_devfs_handle);
-#endif
-EXPORT_SYMBOL(do_ide_request);
-/*
- * Driver module
- */
-EXPORT_SYMBOL(ide_scan_devices);
-EXPORT_SYMBOL(ide_register_subdriver);
-EXPORT_SYMBOL(ide_unregister_subdriver);
-EXPORT_SYMBOL(ide_replace_subdriver);
-EXPORT_SYMBOL(ide_input_data);
-EXPORT_SYMBOL(ide_output_data);
-EXPORT_SYMBOL(atapi_input_bytes);
-EXPORT_SYMBOL(atapi_output_bytes);
-EXPORT_SYMBOL(drive_is_ready);
-EXPORT_SYMBOL(ide_set_handler);
-EXPORT_SYMBOL(ide_dump_status);
-EXPORT_SYMBOL(ide_error);
-EXPORT_SYMBOL(ide_fixstring);
-EXPORT_SYMBOL(ide_wait_stat);
-EXPORT_SYMBOL(ide_do_reset);
-EXPORT_SYMBOL(restart_request);
-EXPORT_SYMBOL(ide_init_drive_cmd);
-EXPORT_SYMBOL(ide_do_drive_cmd);
-EXPORT_SYMBOL(ide_end_drive_cmd);
-EXPORT_SYMBOL(ide_end_request);
-EXPORT_SYMBOL(ide_revalidate_disk);
-EXPORT_SYMBOL(ide_cmd);
-EXPORT_SYMBOL(ide_wait_cmd);
-EXPORT_SYMBOL(ide_wait_cmd_task);
-EXPORT_SYMBOL(ide_delay_50ms);
-EXPORT_SYMBOL(ide_stall_queue);
-#ifdef CONFIG_PROC_FS
-EXPORT_SYMBOL(ide_add_proc_entries);
-EXPORT_SYMBOL(ide_remove_proc_entries);
-EXPORT_SYMBOL(proc_ide_read_geometry);
-EXPORT_SYMBOL(create_proc_ide_interfaces);
-EXPORT_SYMBOL(recreate_proc_ide_device);
-EXPORT_SYMBOL(destroy_proc_ide_device);
-#endif
-EXPORT_SYMBOL(ide_add_setting);
-EXPORT_SYMBOL(ide_remove_setting);
-
-EXPORT_SYMBOL(ide_register_hw);
-EXPORT_SYMBOL(ide_register);
-EXPORT_SYMBOL(ide_unregister);
-EXPORT_SYMBOL(ide_setup_ports);
-EXPORT_SYMBOL(hwif_unregister);
-EXPORT_SYMBOL(get_info_ptr);
-EXPORT_SYMBOL(current_capacity);
-
-EXPORT_SYMBOL(system_bus_clock);
-
-EXPORT_SYMBOL(ide_reinit_drive);
-
-#if 0
-static int ide_notify_reboot (struct notifier_block *this, unsigned long event, void *x)
-{
- ide_hwif_t *hwif;
- ide_drive_t *drive;
- int i, unit;
-
- 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++) {
- hwif = &ide_hwifs[i];
- if (!hwif->present)
- continue;
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- drive = &hwif->drives[unit];
- if (!drive->present)
- continue;
-
- /* set the drive to standby */
- printk("%s ", drive->name);
- if (event != SYS_RESTART)
- if (drive->driver != NULL && DRIVER(drive)->standby(drive))
- continue;
-
- if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
- continue;
- }
- }
- printk("\n");
- return NOTIFY_DONE;
-}
-
-static struct notifier_block ide_notifier = {
- ide_notify_reboot,
- NULL,
- 5
-};
-#endif
-
-/*
- * This is gets invoked once during initialization, to set *everything* up
- */
-int __init ide_init (void)
-{
- static char banner_printed;
- int i;
-
- if (!banner_printed) {
- printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
-#ifdef DEVFS_MUST_DIE
- ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL);
-#endif
- system_bus_speed = ide_system_bus_speed();
- banner_printed = 1;
- }
-
- init_ide_data ();
-
- initializing = 1;
- ide_init_builtin_drivers();
- initializing = 0;
-
- for (i = 0; i < MAX_HWIFS; ++i) {
- ide_hwif_t *hwif = &ide_hwifs[i];
- if (hwif->present)
- ide_geninit(hwif);
- }
-
- /*register_reboot_notifier(&ide_notifier);*/
- return 0;
-}
-
-#ifdef MODULE
-char *options = NULL;
-MODULE_PARM(options,"s");
-MODULE_LICENSE("GPL");
-
-static void __init parse_options (char *line)
-{
- char *next = line;
-
- if (line == NULL || !*line)
- return;
- while ((line = next) != NULL) {
- if ((next = strchr(line,' ')) != NULL)
- *next++ = 0;
- if (!ide_setup(line))
- printk ("Unknown option '%s'\n", line);
- }
-}
-
-int init_module (void)
-{
- parse_options(options);
- return ide_init();
-}
-
-void cleanup_module (void)
-{
- int index;
-
- /*unregister_reboot_notifier(&ide_notifier);*/
- for (index = 0; index < MAX_HWIFS; ++index) {
- ide_unregister(index);
-#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
- if (ide_hwifs[index].dma_base)
- (void) ide_release_dma(&ide_hwifs[index]);
-#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
- }
-
-#ifdef CONFIG_PROC_FS
- proc_ide_destroy();
-#endif
-#ifdef DEVFS_MUST_DIE
- devfs_unregister (ide_devfs_handle);
-#endif
-}
-
-#else /* !MODULE */
-
-__setup("", ide_setup);
-
-#endif /* MODULE */
diff --git a/xen/drivers/ide/ide_modes.h b/xen/drivers/ide/ide_modes.h
deleted file mode 100644
index c848380b13..0000000000
--- a/xen/drivers/ide/ide_modes.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * linux/drivers/ide/ide_modes.h
- *
- * Copyright (C) 1996 Linus Torvalds, Igor Abramov, and Mark Lord
- */
-
-#ifndef _IDE_MODES_H
-#define _IDE_MODES_H
-
-#include <xen/config.h>
-
-/*
- * Shared data/functions for determining best PIO mode for an IDE drive.
- * Most of this stuff originally lived in cmd640.c, and changes to the
- * ide_pio_blacklist[] table should be made with EXTREME CAUTION to avoid
- * breaking the fragile cmd640.c support.
- */
-
-#ifdef CONFIG_BLK_DEV_IDE_MODES
-
-/*
- * Standard (generic) timings for PIO modes, from ATA2 specification.
- * These timings are for access to the IDE data port register *only*.
- * Some drives may specify a mode, while also specifying a different
- * value for cycle_time (from drive identification data).
- */
-typedef struct ide_pio_timings_s {
- int setup_time; /* Address setup (ns) minimum */
- int active_time; /* Active pulse (ns) minimum */
- int cycle_time; /* Cycle time (ns) minimum = (setup + active + recovery) */
-} ide_pio_timings_t;
-
-typedef struct ide_pio_data_s {
- byte pio_mode;
- byte use_iordy;
- byte overridden;
- byte blacklisted;
- unsigned int cycle_time;
-} ide_pio_data_t;
-
-#ifndef _IDE_C
-
-int ide_scan_pio_blacklist (char *model);
-byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d);
-extern const ide_pio_timings_t ide_pio_timings[6];
-
-#else /* _IDE_C */
-
-const ide_pio_timings_t ide_pio_timings[6] = {
- { 70, 165, 600 }, /* PIO Mode 0 */
- { 50, 125, 383 }, /* PIO Mode 1 */
- { 30, 100, 240 }, /* PIO Mode 2 */
- { 30, 80, 180 }, /* PIO Mode 3 with IORDY */
- { 25, 70, 120 }, /* PIO Mode 4 with IORDY */
- { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */
-};
-
-/*
- * Black list. Some drives incorrectly report their maximal PIO mode,
- * at least in respect to CMD640. Here we keep info on some known drives.
- */
-static struct ide_pio_info {
- const char *name;
- int pio;
-} ide_pio_blacklist [] = {
-/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */
- { "Conner Peripherals 540MB - CFS540A", 3 },
-
- { "WDC AC2700", 3 },
- { "WDC AC2540", 3 },
- { "WDC AC2420", 3 },
- { "WDC AC2340", 3 },
- { "WDC AC2250", 0 },
- { "WDC AC2200", 0 },
- { "WDC AC21200", 4 },
- { "WDC AC2120", 0 },
- { "WDC AC2850", 3 },
- { "WDC AC1270", 3 },
- { "WDC AC1170", 1 },
- { "WDC AC1210", 1 },
- { "WDC AC280", 0 },
-/* { "WDC AC21000", 4 }, */
- { "WDC AC31000", 3 },
- { "WDC AC31200", 3 },
-/* { "WDC AC31600", 4 }, */
-
- { "Maxtor 7131 AT", 1 },
- { "Maxtor 7171 AT", 1 },
- { "Maxtor 7213 AT", 1 },
- { "Maxtor 7245 AT", 1 },
- { "Maxtor 7345 AT", 1 },
- { "Maxtor 7546 AT", 3 },
- { "Maxtor 7540 AV", 3 },
-
- { "SAMSUNG SHD-3121A", 1 },
- { "SAMSUNG SHD-3122A", 1 },
- { "SAMSUNG SHD-3172A", 1 },
-
-/* { "ST51080A", 4 },
- * { "ST51270A", 4 },
- * { "ST31220A", 4 },
- * { "ST31640A", 4 },
- * { "ST32140A", 4 },
- * { "ST3780A", 4 },
- */
- { "ST5660A", 3 },
- { "ST3660A", 3 },
- { "ST3630A", 3 },
- { "ST3655A", 3 },
- { "ST3391A", 3 },
- { "ST3390A", 1 },
- { "ST3600A", 1 },
- { "ST3290A", 0 },
- { "ST3144A", 0 },
- { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */
- /* drive) according to Seagates FIND-ATA program */
-
- { "QUANTUM ELS127A", 0 },
- { "QUANTUM ELS170A", 0 },
- { "QUANTUM LPS240A", 0 },
- { "QUANTUM LPS210A", 3 },
- { "QUANTUM LPS270A", 3 },
- { "QUANTUM LPS365A", 3 },
- { "QUANTUM LPS540A", 3 },
- { "QUANTUM LIGHTNING 540A", 3 },
- { "QUANTUM LIGHTNING 730A", 3 },
-
- { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */
- { "QUANTUM FIREBALL_640", 3 },
- { "QUANTUM FIREBALL_1080", 3 },
- { "QUANTUM FIREBALL_1280", 3 },
- { NULL, 0 }
-};
-
-/*
- * This routine searches the ide_pio_blacklist for an entry
- * matching the start/whole of the supplied model name.
- *
- * Returns -1 if no match found.
- * Otherwise returns the recommended PIO mode from ide_pio_blacklist[].
- */
-int ide_scan_pio_blacklist (char *model)
-{
- struct ide_pio_info *p;
-
- for (p = ide_pio_blacklist; p->name != NULL; p++) {
- if (strncmp(p->name, model, strlen(p->name)) == 0)
- return p->pio;
- }
- return -1;
-}
-
-/*
- * This routine returns the recommended PIO settings for a given drive,
- * based on the drive->id information and the ide_pio_blacklist[].
- * This is used by most chipset support modules when "auto-tuning".
- */
-
-/*
- * Drive PIO mode auto selection
- */
-byte ide_get_best_pio_mode (ide_drive_t *drive, byte mode_wanted, byte max_mode, ide_pio_data_t *d)
-{
- int pio_mode;
- int cycle_time = 0;
- int use_iordy = 0;
- struct hd_driveid* id = drive->id;
- int overridden = 0;
- int blacklisted = 0;
-
- if (mode_wanted != 255) {
- pio_mode = mode_wanted;
- } else if (!drive->id) {
- pio_mode = 0;
- } else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) {
- overridden = 1;
- blacklisted = 1;
- use_iordy = (pio_mode > 2);
- } else {
- pio_mode = id->tPIO;
- if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */
- pio_mode = 2;
- overridden = 1;
- }
- if (id->field_valid & 2) { /* drive implements ATA2? */
- if (id->capability & 8) { /* drive supports use_iordy? */
- use_iordy = 1;
- cycle_time = id->eide_pio_iordy;
- if (id->eide_pio_modes & 7) {
- overridden = 0;
- if (id->eide_pio_modes & 4)
- pio_mode = 5;
- else if (id->eide_pio_modes & 2)
- pio_mode = 4;
- else
- pio_mode = 3;
- }
- } else {
- cycle_time = id->eide_pio;
- }
- }
-
-#if 0
- if (drive->id->major_rev_num & 0x0004) printk("ATA-2 ");
-#endif
-
- /*
- * Conservative "downgrade" for all pre-ATA2 drives
- */
- if (pio_mode && pio_mode < 4) {
- pio_mode--;
- overridden = 1;
-#if 0
- use_iordy = (pio_mode > 2);
-#endif
- if (cycle_time && cycle_time < ide_pio_timings[pio_mode].cycle_time)
- cycle_time = 0; /* use standard timing */
- }
- }
- if (pio_mode > max_mode) {
- pio_mode = max_mode;
- cycle_time = 0;
- }
- if (d) {
- d->pio_mode = pio_mode;
- d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time;
- d->use_iordy = use_iordy;
- d->overridden = overridden;
- d->blacklisted = blacklisted;
- }
- return pio_mode;
-}
-
-#endif /* _IDE_C */
-#endif /* CONFIG_BLK_DEV_IDE_MODES */
-#endif /* _IDE_MODES_H */
diff --git a/xen/drivers/ide/piix.c b/xen/drivers/ide/piix.c
deleted file mode 100644
index e68deef9ba..0000000000
--- a/xen/drivers/ide/piix.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * linux/drivers/ide/piix.c Version 0.32 June 9, 2000
- *
- * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
- * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- * May be copied or modified under the terms of the GNU General Public License
- *
- * PIO mode setting function for Intel chipsets.
- * For use instead of BIOS settings.
- *
- * 40-41
- * 42-43
- *
- * 41
- * 43
- *
- * | PIO 0 | c0 | 80 | 0 | piix_tune_drive(drive, 0);
- * | PIO 2 | SW2 | d0 | 90 | 4 | piix_tune_drive(drive, 2);
- * | PIO 3 | MW1 | e1 | a1 | 9 | piix_tune_drive(drive, 3);
- * | PIO 4 | MW2 | e3 | a3 | b | piix_tune_drive(drive, 4);
- *
- * sitre = word40 & 0x4000; primary
- * sitre = word42 & 0x4000; secondary
- *
- * 44 8421|8421 hdd|hdb
- *
- * 48 8421 hdd|hdc|hdb|hda udma enabled
- *
- * 0001 hda
- * 0010 hdb
- * 0100 hdc
- * 1000 hdd
- *
- * 4a 84|21 hdb|hda
- * 4b 84|21 hdd|hdc
- *
- * ata-33/82371AB
- * ata-33/82371EB
- * ata-33/82801AB ata-66/82801AA
- * 00|00 udma 0 00|00 reserved
- * 01|01 udma 1 01|01 udma 3
- * 10|10 udma 2 10|10 udma 4
- * 11|11 reserved 11|11 reserved
- *
- * 54 8421|8421 ata66 drive|ata66 enable
- *
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &reg40);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, &reg48);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, &reg54);
- *
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/kernel.h>
-#include <xen/ioport.h>
-#include <xen/pci.h>
-#include <xen/hdreg.h>
-#include <xen/ide.h>
-#include <xen/delay.h>
-#include <xen/init.h>
-
-#include <asm/io.h>
-
-#include "ide_modes.h"
-
-#define PIIX_DEBUG_DRIVE_INFO 0
-
-#define DISPLAY_PIIX_TIMINGS
-
-#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <xen/stat.h>
-#include <xen/proc_fs.h>
-
-static int piix_get_info(char *, char **, off_t, int);
-extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */
-extern char *ide_media_verbose(ide_drive_t *);
-static struct pci_dev *bmide_dev;
-
-static int piix_get_info (char *buffer, char **addr, off_t offset, int count)
-{
- char *p = buffer;
- u32 bibma = pci_resource_start(bmide_dev, 4);
- u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
- u8 c0 = 0, c1 = 0;
- u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0;
-
- switch(bmide_dev->device) {
- case PCI_DEVICE_ID_INTEL_82801BA_8:
- case PCI_DEVICE_ID_INTEL_82801BA_9:
- case PCI_DEVICE_ID_INTEL_82801CA_10:
- case PCI_DEVICE_ID_INTEL_82801CA_11:
- case PCI_DEVICE_ID_INTEL_82801DB_11:
- case PCI_DEVICE_ID_INTEL_82801E_11:
- p += sprintf(p, "\n Intel PIIX4 Ultra 100 Chipset.\n");
- break;
- case PCI_DEVICE_ID_INTEL_82372FB_1:
- case PCI_DEVICE_ID_INTEL_82801AA_1:
- p += sprintf(p, "\n Intel PIIX4 Ultra 66 Chipset.\n");
- break;
- case PCI_DEVICE_ID_INTEL_82451NX:
- case PCI_DEVICE_ID_INTEL_82801AB_1:
- case PCI_DEVICE_ID_INTEL_82443MX_1:
- case PCI_DEVICE_ID_INTEL_82371AB:
- p += sprintf(p, "\n Intel PIIX4 Ultra 33 Chipset.\n");
- break;
- case PCI_DEVICE_ID_INTEL_82371SB_1:
- p += sprintf(p, "\n Intel PIIX3 Chipset.\n");
- break;
- case PCI_DEVICE_ID_INTEL_82371MX:
- p += sprintf(p, "\n Intel MPIIX Chipset.\n");
- return p-buffer; /* => must be less than 4k! */
- case PCI_DEVICE_ID_INTEL_82371FB_1:
- case PCI_DEVICE_ID_INTEL_82371FB_0:
- default:
- p += sprintf(p, "\n Intel PIIX Chipset.\n");
- break;
- }
-
- pci_read_config_word(bmide_dev, 0x40, &reg40);
- pci_read_config_word(bmide_dev, 0x42, &reg42);
- pci_read_config_byte(bmide_dev, 0x44, &reg44);
- pci_read_config_byte(bmide_dev, 0x48, &reg48);
- pci_read_config_byte(bmide_dev, 0x4a, &reg4a);
- pci_read_config_byte(bmide_dev, 0x4b, &reg4b);
- pci_read_config_byte(bmide_dev, 0x54, &reg54);
- pci_read_config_byte(bmide_dev, 0x55, &reg55);
-
- psitre = (reg40 & 0x4000) ? 1 : 0;
- ssitre = (reg42 & 0x4000) ? 1 : 0;
-
- /*
- * 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");
- p += sprintf(p, " %sabled %sabled\n",
- (c0&0x80) ? "dis" : " en",
- (c1&0x80) ? "dis" : " en");
- 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 " );
- p += sprintf(p, "UDMA enabled: %s %s %s %s\n",
- (reg48&0x01) ? "yes" : "no ",
- (reg48&0x02) ? "yes" : "no ",
- (reg48&0x04) ? "yes" : "no ",
- (reg48&0x08) ? "yes" : "no " );
- p += sprintf(p, "UDMA enabled: %s %s %s %s\n",
- ((reg54&0x11) && (reg55&0x10) && (reg4a&0x01)) ? "5" :
- ((reg54&0x11) && (reg4a&0x02)) ? "4" :
- ((reg54&0x11) && (reg4a&0x01)) ? "3" :
- (reg4a&0x02) ? "2" :
- (reg4a&0x01) ? "1" :
- (reg4a&0x00) ? "0" : "X",
- ((reg54&0x22) && (reg55&0x20) && (reg4a&0x10)) ? "5" :
- ((reg54&0x22) && (reg4a&0x20)) ? "4" :
- ((reg54&0x22) && (reg4a&0x10)) ? "3" :
- (reg4a&0x20) ? "2" :
- (reg4a&0x10) ? "1" :
- (reg4a&0x00) ? "0" : "X",
- ((reg54&0x44) && (reg55&0x40) && (reg4b&0x03)) ? "5" :
- ((reg54&0x44) && (reg4b&0x02)) ? "4" :
- ((reg54&0x44) && (reg4b&0x01)) ? "3" :
- (reg4b&0x02) ? "2" :
- (reg4b&0x01) ? "1" :
- (reg4b&0x00) ? "0" : "X",
- ((reg54&0x88) && (reg55&0x80) && (reg4b&0x30)) ? "5" :
- ((reg54&0x88) && (reg4b&0x20)) ? "4" :
- ((reg54&0x88) && (reg4b&0x10)) ? "3" :
- (reg4b&0x20) ? "2" :
- (reg4b&0x10) ? "1" :
- (reg4b&0x00) ? "0" : "X");
-
- p += sprintf(p, "UDMA\n");
- p += sprintf(p, "DMA\n");
- p += sprintf(p, "PIO\n");
-
-/*
- * FIXME.... Add configuration junk data....blah blah......
- */
-
- return p-buffer; /* => must be less than 4k! */
-}
-#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-/*
- * Used to set Fifo configuration via kernel command line:
- */
-
-byte piix_proc = 0;
-
-extern char *ide_xfer_verbose (byte xfer_rate);
-
-#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING)
-/*
- *
- */
-static byte piix_dma_2_pio (byte xfer_rate) {
- switch(xfer_rate) {
- case XFER_UDMA_5:
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- case XFER_MW_DMA_2:
- case XFER_PIO_4:
- return 4;
- case XFER_MW_DMA_1:
- case XFER_PIO_3:
- return 3;
- case XFER_SW_DMA_2:
- case XFER_PIO_2:
- return 2;
- case XFER_MW_DMA_0:
- case XFER_SW_DMA_1:
- case XFER_SW_DMA_0:
- case XFER_PIO_1:
- case XFER_PIO_0:
- case XFER_PIO_SLOW:
- default:
- return 0;
- }
-}
-#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */
-
-/*
- * Based on settings done by AMI BIOS
- * (might be useful if drive is not registered in CMOS for any reason).
- */
-static void piix_tune_drive (ide_drive_t *drive, byte pio)
-{
- unsigned long flags;
- u16 master_data;
- byte slave_data;
- int is_slave = (&HWIF(drive)->drives[1] == drive);
- int master_port = HWIF(drive)->index ? 0x42 : 0x40;
- int slave_port = 0x44;
- /* ISP RTC */
- byte timings[][2] = { { 0, 0 },
- { 0, 0 },
- { 1, 0 },
- { 2, 1 },
- { 2, 3 }, };
-
- pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
- pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
- if (is_slave) {
- master_data = master_data | 0x4000;
- if (pio > 1)
- /* enable PPE, IE and TIME */
- master_data = master_data | 0x0070;
- pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data);
- slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0);
- slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1])
- << (HWIF(drive)->index ? 4 : 0));
- } else {
- master_data = master_data & 0xccf8;
- if (pio > 1)
- /* enable PPE, IE and TIME */
- master_data = master_data | 0x0007;
- master_data = master_data | (timings[pio][0] << 12) |
- (timings[pio][1] << 8);
- }
- save_flags(flags);
- cli();
- pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data);
- if (is_slave)
- pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data);
- restore_flags(flags);
-}
-
-#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING)
-static int piix_tune_chipset (ide_drive_t *drive, byte speed)
-{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- byte maslave = hwif->channel ? 0x42 : 0x40;
- int a_speed = 3 << (drive->dn * 4);
- int u_flag = 1 << drive->dn;
- int v_flag = 0x01 << drive->dn;
- int w_flag = 0x10 << drive->dn;
- int u_speed = 0;
- int err = 0;
- int sitre;
- short reg4042, reg44, reg48, reg4a, reg54;
- byte reg55;
-
- pci_read_config_word(dev, maslave, &reg4042);
- sitre = (reg4042 & 0x4000) ? 1 : 0;
- pci_read_config_word(dev, 0x44, &reg44);
- pci_read_config_word(dev, 0x48, &reg48);
- pci_read_config_word(dev, 0x4a, &reg4a);
- pci_read_config_word(dev, 0x54, &reg54);
- pci_read_config_byte(dev, 0x55, &reg55);
-
- switch(speed) {
- case XFER_UDMA_4:
- case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
- case XFER_UDMA_5:
- case XFER_UDMA_3:
- case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
- case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_SW_DMA_2: break;
- default: return -1;
- }
-
- if (speed >= XFER_UDMA_0) {
- if (!(reg48 & u_flag))
- pci_write_config_word(dev, 0x48, reg48|u_flag);
- if (speed == XFER_UDMA_5) {
- pci_write_config_byte(dev, 0x55, (byte) reg55|w_flag);
- } else {
- pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag);
- }
- if (!(reg4a & u_speed)) {
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
- pci_write_config_word(dev, 0x4a, reg4a|u_speed);
- }
- if (speed > XFER_UDMA_2) {
- if (!(reg54 & v_flag)) {
- pci_write_config_word(dev, 0x54, reg54|v_flag);
- }
- } else {
- pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
- }
- }
- if (speed < XFER_UDMA_0) {
- if (reg48 & u_flag)
- pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
- if (reg4a & a_speed)
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
- if (reg54 & v_flag)
- pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
- if (reg55 & w_flag)
- pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag);
- }
-
- piix_tune_drive(drive, piix_dma_2_pio(speed));
-
-#if PIIX_DEBUG_DRIVE_INFO
- printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
-#endif /* PIIX_DEBUG_DRIVE_INFO */
- if (!drive->init_speed)
- drive->init_speed = speed;
- err = ide_config_drive_speed(drive, speed);
- drive->current_speed = speed;
- return err;
-}
-
-static int piix_config_drive_for_dma (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- byte speed;
-
- byte udma_66 = eighty_ninty_three(drive);
- int ultra100 = ((dev->device == PCI_DEVICE_ID_INTEL_82801BA_8) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801BA_9) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801CA_10) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801CA_11) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801DB_11) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801E_11)) ? 1 : 0;
- int ultra66 = ((ultra100) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0;
- int ultra = ((ultra66) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82443MX_1) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82451NX) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0;
-
- if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) {
- speed = XFER_UDMA_5;
- } else if ((id->dma_ultra & 0x0010) && (ultra)) {
- speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2;
- } else if ((id->dma_ultra & 0x0008) && (ultra)) {
- speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1;
- } else if ((id->dma_ultra & 0x0004) && (ultra)) {
- speed = XFER_UDMA_2;
- } else if ((id->dma_ultra & 0x0002) && (ultra)) {
- speed = XFER_UDMA_1;
- } else if ((id->dma_ultra & 0x0001) && (ultra)) {
- speed = XFER_UDMA_0;
- } else if (id->dma_mword & 0x0004) {
- speed = XFER_MW_DMA_2;
- } else if (id->dma_mword & 0x0002) {
- speed = XFER_MW_DMA_1;
- } else if (id->dma_1word & 0x0004) {
- speed = XFER_SW_DMA_2;
- } else {
- speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
- }
-
- (void) piix_tune_chipset(drive, speed);
-
- return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
- ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
- ((id->dma_mword >> 8) & 7) ? ide_dma_on :
- ((id->dma_1word >> 8) & 7) ? ide_dma_on :
- ide_dma_off_quietly);
-}
-
-static void config_chipset_for_pio (ide_drive_t *drive)
-{
- piix_tune_drive(drive, ide_get_best_pio_mode(drive, 255, 5, NULL));
-}
-
-static int config_drive_xfer_rate (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
- ide_dma_action_t dma_func = ide_dma_on;
-
- if (id && (id->capability & 1) && HWIF(drive)->autodma) {
- /* Consult the list of known "bad" drives */
- if (ide_dmaproc(ide_dma_bad_drive, drive)) {
- dma_func = ide_dma_off;
- goto fast_ata_pio;
- }
- dma_func = ide_dma_off_quietly;
- if (id->field_valid & 4) {
- if (id->dma_ultra & 0x003F) {
- /* Force if Capable UltraDMA */
- dma_func = piix_config_drive_for_dma(drive);
- if ((id->field_valid & 2) &&
- (dma_func != ide_dma_on))
- goto try_dma_modes;
- }
- } else if (id->field_valid & 2) {
-try_dma_modes:
- if ((id->dma_mword & 0x0007) ||
- (id->dma_1word & 0x007)) {
- /* Force if Capable regular DMA modes */
- dma_func = piix_config_drive_for_dma(drive);
- if (dma_func != ide_dma_on)
- goto no_dma_set;
- }
- } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
- if (id->eide_dma_time > 150) {
- goto no_dma_set;
- }
- /* Consult the list of known "good" drives */
- dma_func = piix_config_drive_for_dma(drive);
- if (dma_func != ide_dma_on)
- goto no_dma_set;
- } else {
- goto fast_ata_pio;
- }
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
- dma_func = ide_dma_off_quietly;
-no_dma_set:
- config_chipset_for_pio(drive);
- }
- return HWIF(drive)->dmaproc(dma_func, drive);
-}
-
-static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
- switch (func) {
- case ide_dma_check:
- return config_drive_xfer_rate(drive);
- default :
- break;
- }
- /* Other cases are done by generic IDE-DMA code. */
- return ide_dmaproc(func, drive);
-}
-#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */
-
-unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name)
-{
-#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
- if (!piix_proc) {
- piix_proc = 1;
- bmide_dev = dev;
- piix_display_info = &piix_get_info;
- }
-#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */
- return 0;
-}
-
-/*
- * Sheesh, someone at Intel needs to go read the ATA-4/5 T13 standards.
- * It does not specify device detection, but channel!!!
- * You determine later if bit 13 of word93 is set...
- */
-unsigned int __init ata66_piix (ide_hwif_t *hwif)
-{
- byte reg54h = 0, reg55h = 0, ata66 = 0;
- byte mask = hwif->channel ? 0xc0 : 0x30;
-
- pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
- pci_read_config_byte(hwif->pci_dev, 0x55, &reg55h);
-
- ata66 = (reg54h & mask) ? 1 : 0;
-
- return ata66;
-}
-
-void __init ide_init_piix (ide_hwif_t *hwif)
-{
-#ifndef CONFIG_IA64
- if (!hwif->irq)
- hwif->irq = hwif->channel ? 15 : 14;
-#endif /* CONFIG_IA64 */
-
- if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_82371MX) {
- /* This is a painful system best to let it self tune for now */
- return;
- }
-
- hwif->tuneproc = &piix_tune_drive;
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
- if (!hwif->dma_base)
- return;
-
-#ifndef CONFIG_BLK_DEV_IDEDMA
- hwif->autodma = 0;
-#else /* CONFIG_BLK_DEV_IDEDMA */
-#ifdef CONFIG_PIIX_TUNING
- if (!noautodma)
- hwif->autodma = 1;
- hwif->dmaproc = &piix_dmaproc;
- hwif->speedproc = &piix_tune_chipset;
-#endif /* CONFIG_PIIX_TUNING */
-#endif /* !CONFIG_BLK_DEV_IDEDMA */
-}