diff options
Diffstat (limited to 'xen/drivers/ide')
-rw-r--r-- | xen/drivers/ide/Makefile | 8 | ||||
-rw-r--r-- | xen/drivers/ide/ide-cd.c | 3084 | ||||
-rw-r--r-- | xen/drivers/ide/ide-cd.h | 746 | ||||
-rw-r--r-- | xen/drivers/ide/ide-disk.c | 1553 | ||||
-rw-r--r-- | xen/drivers/ide/ide-dma.c | 897 | ||||
-rw-r--r-- | xen/drivers/ide/ide-features.c | 384 | ||||
-rw-r--r-- | xen/drivers/ide/ide-geometry.c | 219 | ||||
-rw-r--r-- | xen/drivers/ide/ide-pci.c | 1016 | ||||
-rw-r--r-- | xen/drivers/ide/ide-probe.c | 1066 | ||||
-rw-r--r-- | xen/drivers/ide/ide-taskfile.c | 1733 | ||||
-rw-r--r-- | xen/drivers/ide/ide-xen.c | 61 | ||||
-rw-r--r-- | xen/drivers/ide/ide.c | 4211 | ||||
-rw-r--r-- | xen/drivers/ide/ide_modes.h | 236 | ||||
-rw-r--r-- | xen/drivers/ide/piix.c | 542 |
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, ®40); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, ®42); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, ®44); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, ®48); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, ®4a); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, ®54); - * - */ - -#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, ®40); - pci_read_config_word(bmide_dev, 0x42, ®42); - pci_read_config_byte(bmide_dev, 0x44, ®44); - pci_read_config_byte(bmide_dev, 0x48, ®48); - pci_read_config_byte(bmide_dev, 0x4a, ®4a); - pci_read_config_byte(bmide_dev, 0x4b, ®4b); - pci_read_config_byte(bmide_dev, 0x54, ®54); - pci_read_config_byte(bmide_dev, 0x55, ®55); - - 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, ®4042); - sitre = (reg4042 & 0x4000) ? 1 : 0; - pci_read_config_word(dev, 0x44, ®44); - pci_read_config_word(dev, 0x48, ®48); - pci_read_config_word(dev, 0x4a, ®4a); - pci_read_config_word(dev, 0x54, ®54); - pci_read_config_byte(dev, 0x55, ®55); - - 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, ®54h); - pci_read_config_byte(hwif->pci_dev, 0x55, ®55h); - - 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 */ -} |