home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-09-03 | 89.6 KB | 3,000 lines |
- diff -u --recursive --new-file v1.3.22/linux/Makefile linux/Makefile
- --- v1.3.22/linux/Makefile Sun Sep 3 12:26:48 1995
- +++ linux/Makefile Sun Sep 3 12:28:30 1995
- @@ -1,6 +1,6 @@
- VERSION = 1
- PATCHLEVEL = 3
- -SUBLEVEL = 22
- +SUBLEVEL = 23
-
- ARCH = i386
-
- diff -u --recursive --new-file v1.3.22/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
- --- v1.3.22/linux/arch/i386/mm/fault.c Wed Aug 2 13:20:59 1995
- +++ linux/arch/i386/mm/fault.c Sun Sep 3 13:26:40 1995
- @@ -49,6 +49,16 @@
- goto bad_area;
- if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
- goto bad_area;
- + if (error_code & 4) {
- + /*
- + * accessing the stack below %esp is always a bug.
- + * The "+ 32" is there due to some instructions (like
- + * pusha) doing pre-decrement on the stack and that
- + * doesn't show up until later..
- + */
- + if (address + 32 < regs->esp)
- + goto bad_area;
- + }
- vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
- vma->vm_start = (address & PAGE_MASK);
- /*
- diff -u --recursive --new-file v1.3.22/linux/drivers/block/README.ide linux/drivers/block/README.ide
- --- v1.3.22/linux/drivers/block/README.ide Sun Sep 3 12:26:50 1995
- +++ linux/drivers/block/README.ide Sun Sep 3 12:03:42 1995
- @@ -46,6 +46,9 @@
- NEW! - ide-cd.c now compiles separate from ide.c
- NEW! - Bus-Master DMA support for Intel PCI Triton chipset IDE interfaces
- NEW! - for details, see comments at top of triton.c
- +NEW! - ide-cd.c now supports door locking and auto-loading.
- +NEW! Also preliminary support for multisession and direct
- +NEW! reads of audio data.
-
- For work in progress, see the comments in ide.c, ide-cd.c, and triton.c.
-
- @@ -160,6 +163,31 @@
- ln -sf /dev/hdc /dev/cdrom
- mkdir /cd
- mount /dev/cdrom /cd -t iso9660 -o ro
- +
- +If, after doing all of the above, mount doesn't work and you see
- +errors from the driver (with dmesg) complaining about `status=0xff',
- +this means that the hardware is not responding to the driver's attempts
- +to read it. One of the following is probably the problem:
- +
- + - Your hardware is broken.
- +
- + - You are using the wrong address for the device, or you have the
- + drive jumpered wrong. Review the configuration instructions above.
- +
- + - Your IDE controller requires some nonstandard initialization sequence
- + before it will work properly. If this is the case, there will often
- + be a separate MS-DOS driver just for the controller. IDE interfaces
- + on sound cards usually fall into this category. Such configurations
- + can often be made to work by first booting MS-DOS, loading the
- + appropriate drivers, and then warm-booting linux (without powering
- + off). This can be automated using loadlin in the MS-DOS autoexec.
- +
- +If you always get timeout errors, interrupts from the drive are probably
- +not making it to the host. Check how you have the hardware jumpered
- +and make sure it matches what the driver expects (see the configuration
- +instructions above). If you have a PCI system, also check the BIOS
- +setup; i've had one report of a system which was shipped with IRQ 15
- +disabled by the BIOS.
-
- The kernel is able to execute binaries directly off of the cdrom,
- provided it is mounted with the default block size of 1024 (as above).
- diff -u --recursive --new-file v1.3.22/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
- --- v1.3.22/linux/drivers/block/genhd.c Sun Sep 3 12:26:50 1995
- +++ linux/drivers/block/genhd.c Sun Sep 3 12:20:25 1995
- @@ -3,20 +3,17 @@
- * linux/kernel/hd.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- - */
- -
- -/*
- + *
- + *
- * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
- * in the early extended-partition checks and added DM partitions
- - */
- -
- -/*
- + *
- * Support for DiskManager v6.0x added by Mark Lord (mlord@bnr.ca)
- * with information provided by OnTrack. This now works for linux fdisk
- * and LILO, as well as loadlin and bootln. Note that disks other than
- * /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
- - *
- - * Added support for "missing/deleted" extended partitions - mlord@bnr.ca
- + *
- + * More flexible handling of extended partitions - aeb, 950831
- */
-
- #include <linux/config.h>
- @@ -82,14 +79,15 @@
- {
- struct buffer_head *bh;
- struct partition *p;
- - unsigned long first_sector, this_sector;
- + unsigned long first_sector, this_sector, this_size;
- int mask = (1 << hd->minor_shift) - 1;
- + int i;
-
- first_sector = hd->part[MINOR(dev)].start_sect;
- this_sector = first_sector;
-
- while (1) {
- - if ((current_minor & mask) >= (4 + hd->max_p))
- + if ((current_minor & mask) >= hd->max_p)
- return;
- if (!(bh = bread(dev,0,1024)))
- return;
- @@ -100,29 +98,56 @@
- bh->b_dirt = 0;
- bh->b_uptodate = 0;
- bh->b_req = 0;
- +
- if (*(unsigned short *) (bh->b_data+510) != 0xAA55)
- goto done;
- +
- p = (struct partition *) (0x1BE + bh->b_data);
- +
- + this_size = hd->part[MINOR(dev)].nr_sects;
- +
- /*
- - * Process the first entry, which should be the real
- - * data partition.
- + * Usually, the first entry is the real data partition,
- + * the 2nd entry is the next extended partition, or empty,
- + * and the 3rd and 4th entries are unused.
- + * However, DRDOS sometimes has the extended partition as
- + * the first entry (when the data partition is empty),
- + * and OS/2 seems to use all four entries.
- */
- - if (p->sys_ind == EXTENDED_PARTITION)
- - goto done; /* shouldn't happen */
- - if (p->sys_ind && p->nr_sects)
- - add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects);
- - current_minor++;
- - p++;
- +
- + /*
- + * First process the data partition(s)
- + */
- + for (i=0; i<4; i++, p++) {
- + if (!p->nr_sects || p->sys_ind == EXTENDED_PARTITION)
- + continue;
- +
- + if (p->start_sect + p->nr_sects > this_size)
- + continue;
- +
- + add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects);
- + current_minor++;
- + if ((current_minor & mask) >= hd->max_p)
- + goto done;
- + }
- /*
- - * Process the second entry, which should be a link
- - * to the next logical partition. Create a minor
- - * for this just long enough to get the next partition
- - * table. The minor will be reused for the real
- + * Next, process the (first) extended partition, if present.
- + * (So far, there seems to be no reason to make
- + * extended_partition() recursive and allow a tree
- + * of extended partitions.)
- + * It should be a link to the next logical partition.
- + * Create a minor for this just long enough to get the next
- + * partition table. The minor will be reused for the next
- * data partition.
- */
- - if (p->sys_ind != EXTENDED_PARTITION ||
- - !(hd->part[current_minor].nr_sects = p->nr_sects))
- - goto done; /* no more logicals in this partition */
- + p -= 4;
- + for (i=0; i<4; i++, p++)
- + if(p->nr_sects && p->sys_ind == EXTENDED_PARTITION)
- + break;
- + if (i == 4)
- + goto done; /* nothing left to do */
- +
- + hd->part[current_minor].nr_sects = p->nr_sects;
- hd->part[current_minor].start_sect = first_sector + p->start_sect;
- this_sector = first_sector + p->start_sect;
- dev = ((hd->major) << 8) | current_minor;
- @@ -211,6 +236,9 @@
- printk(" <");
- extended_partition(hd, (hd->major << 8) | minor);
- printk(" >");
- + /* prevent someone doing mkfs or mkswap on
- + an extended partition */
- + hd->part[minor].nr_sects = 0;
- }
- }
- /*
- diff -u --recursive --new-file v1.3.22/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
- --- v1.3.22/linux/drivers/block/ide-cd.c Mon Aug 28 14:52:18 1995
- +++ linux/drivers/block/ide-cd.c Sun Sep 3 12:03:42 1995
- @@ -41,21 +41,35 @@
- * 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 (UNTESTED).
- + * 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.
- *
- - * FIX ME!! A day-one bug exists when the ide.c "serialize" option is used.
- - * For this to always work correctly, ide_set_handler() must be called
- - * *just before* the final trigger is given to the drive (to cause it to go
- - * off and get data and then interrupt us again). Otherwise, we may get the
- - * interrupt before set_handler() has actually run, resulting in "unexpected_intr".
- - *
- - * This can only happen in scenarios where we handle a "final" interrupt
- - * for one IDE port on, say irq14, and then initiate a new request for the
- - * other port on, say irq15, from the irq14 interrupt handler. If we are
- - * running with "unmask" on, or have done sti(), then Whammo -- we're exposed.
- - *
- - * Places where this needs fixing have been identified in the code with "BUG".
- - * -ml August 11, 1995
- - *
- + * NOTE: I've tried to implement support for multisession CDs and
- + * direct audio reads in this version, but i haven't been able to fully
- + * test them due to a lack of the proper hardware. I'd appreciate hearing
- + * if the multisession stuff works; i'd also be interested in hearing
- + * if you get anything other than a `Parameter not supported'
- + * (asc=0x26, ascq=1) error when trying to do a direct audio read.
- *
- * ATAPI cd-rom driver. To be used with ide.c.
- *
- @@ -80,6 +94,7 @@
- #include <linux/hdreg.h>
- #include <linux/cdrom.h>
- #include <asm/irq.h>
- +#include <asm/io.h>
-
- #define _IDE_CD_C /* used in blk.h */
- #include "ide.h"
- @@ -98,17 +113,10 @@
-
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
-
- -#if 1 /* "old" method */
- -#define OUT_WORDS(b,n) outsw (IDE_DATA_REG, (b), (n))
- -#define IN_WORDS(b,n) insw (IDE_DATA_REG, (b), (n))
- -#else /* "new" method -- should really fix each instance instead of this */
- -#define OUT_WORDS(b,n) output_ide_data(drive,b,(n)/2)
- -#define IN_WORDS(b,n) input_ide_data(drive,b,(n)/2)
- -#endif
- -
- /* special command codes for strategy routine. */
- -#define PACKET_COMMAND 4315
- +#define PACKET_COMMAND 4315
- #define REQUEST_SENSE_COMMAND 4316
- +#define RESET_DRIVE_COMMAND 4317
-
- /* Some ATAPI command opcodes (just like SCSI).
- (Some other cdrom-specific codes are in cdrom.h.) */
- @@ -116,9 +124,11 @@
- #define REQUEST_SENSE 0x03
- #define START_STOP 0x1b
- #define ALLOW_MEDIUM_REMOVAL 0x1e
- +#define READ_CAPACITY 0x25
- #define READ_10 0x28
- #define MODE_SENSE_10 0x5a
- #define MODE_SELECT_10 0x55
- +#define READ_CD 0xbe
-
-
- /* ATAPI sense keys (mostly copied from scsi.h). */
- @@ -135,25 +145,72 @@
- #define MISCOMPARE 0x0e
-
- /* We want some additional flags for cd-rom drives.
- - To save space in the ide_drive_t struct, use one of the fields which
- - doesn't make sense for cd-roms -- `bios_sect'. */
- + To save space in the ide_drive_t struct, use some fields which
- + doesn't make sense for cd-roms -- `bios_sect' and `bios_head'. */
-
- -struct ide_cd_flags {
- +/* 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 {
- unsigned drq_interrupt : 1; /* Device sends an interrupt when ready
- for a packet command. */
- unsigned no_playaudio12: 1; /* The PLAYAUDIO12 command is not supported. */
- -
- - unsigned media_changed : 1; /* Driver has noticed a media change. */
- - unsigned toc_valid : 1; /* Saved TOC information is current. */
- +
- unsigned no_lba_toc : 1; /* Drive cannot return TOC info in LBA format. */
- unsigned msf_as_bcd : 1; /* Drive uses BCD in PLAYAUDIO_MSF. */
- + unsigned no_doorlock : 1; /* Drive cannot lock the door. */
- + unsigned old_readcd : 1; /* Drive uses old READ CD opcode. */
- unsigned reserved : 2;
- };
- +#define CDROM_CONFIG_FLAGS(drive) ((struct ide_cd_config_flags *)&((drive)->bios_sect))
- +
- +
- +/* State flags. These give information about the current state of the
- + drive, and will change during normal operation. */
- +struct ide_cd_state_flags {
- + unsigned media_changed : 1; /* Driver has noticed a media change. */
- + unsigned toc_valid : 1; /* Saved TOC information is current. */
- + unsigned door_locked : 1; /* We think that the drive door is locked. */
- + unsigned eject_on_close: 1; /* Drive should eject when device is closed. */
- + unsigned reserved : 4;
- +};
- +#define CDROM_STATE_FLAGS(drive) ((struct ide_cd_state_flags *)&((drive)->bios_head))
-
- -#define CDROM_FLAGS(drive) ((struct ide_cd_flags *)&((drive)->bios_sect))
-
- #define SECTOR_BUFFER_SIZE CD_FRAMESIZE
-
- +
- +
- +/****************************************************************************
- + * Routines to read and write data from/to the drive, using
- + * the routines input_ide_data() and output_ide_data() from ide.c.
- + *
- + * All transfer lengths should be multiples of 16-bit shorts.
- + */
- +
- +
- +static inline
- +void cdrom_in_bytes (ide_drive_t *drive, void *buffer, uint bytecount)
- +{
- + ide_input_data (drive, buffer, bytecount / 4);
- + if ((bytecount & 0x03 >= 2))
- + {
- + insw (IDE_DATA_REG, buffer + (bytecount & ~0x03), 1);
- + }
- +}
- +
- +
- +static inline
- +void cdrom_out_bytes (ide_drive_t *drive, void *buffer, uint bytecount)
- +{
- + ide_output_data (drive, buffer, bytecount / 4);
- + if ((bytecount & 0x03 >= 2))
- + {
- + outsw (IDE_DATA_REG, buffer + (bytecount & ~0x03), 1);
- + }
- +}
- +
- +
-
- /****************************************************************************
- * Descriptions of ATAPI error codes.
- @@ -298,7 +355,7 @@
-
-
- /****************************************************************************
- - * Generic packet command support routines.
- + * Generic packet command support and error handling routines.
- */
-
-
- @@ -312,7 +369,7 @@
- the drive, and we don't want to fill the syslog with useless errors. */
- if (failed_command &&
- failed_command->c[0] == SCMD_READ_SUBCHANNEL &&
- - (reqbuf->sense_key == 2 || reqbuf->sense_key == 6))
- + (reqbuf->sense_key == NOT_READY || reqbuf->sense_key == UNIT_ATTENTION))
- return;
-
- #if VERBOSE_IDE_CD_ERRORS
- @@ -380,6 +437,15 @@
- }
-
- #else
- +
- + /* Suppress printing unit attention and `in progress of becoming ready'
- + errors when we're not being verbose. */
- +
- + if (reqbuf->sense_key == UNIT_ATTENTION ||
- + (reqbuf->sense_key == NOT_READY && (reqbuf->asc == 4 ||
- + reqbuf->asc == 0x3a)))
- + return;
- +
- printk ("%s: code: %x key: %x asc: %x ascq: %x\n",
- drive->name,
- reqbuf->error_code, reqbuf->sense_key, reqbuf->asc, reqbuf->ascq);
- @@ -402,12 +468,14 @@
- }
-
-
- -static void cdrom_queue_request_sense (ide_drive_t *drive)
- +static void cdrom_queue_request_sense (ide_drive_t *drive,
- + struct semaphore *sem,
- + struct atapi_request_sense *reqbuf)
- {
- struct request *rq;
- struct packet_command *pc;
- - struct atapi_request_sense *reqbuf;
- unsigned long flags;
- + int len;
-
- int major = HWIF(drive)->major;
-
- @@ -427,16 +495,30 @@
-
- restore_flags (flags);
-
- + /* If the request didn't explicitly specify where to put the sense data,
- + use the statically allocated structure. */
- + if (reqbuf == NULL)
- + reqbuf = &drive->cdrom_info.sense_data;
- +
- /* Make up a new request to retrieve sense information. */
- - reqbuf = &drive->cdrom_info.sense_data;
-
- pc = &HWIF(drive)->request_sense_pc;
- memset (pc, 0, sizeof (*pc));
-
- + /* The request_sense structure has an odd number of (16-bit) words,
- + which won't work well with 32-bit transfers. However, we don't care
- + about the last two bytes, so just truncate the structure down
- + to an even length. */
- + len = sizeof (*reqbuf) / 4;
- + len *= 4;
- +
- pc->c[0] = REQUEST_SENSE;
- - pc->c[4] = sizeof (*reqbuf);
- + pc->c[4] = len;
- pc->buffer = (char *)reqbuf;
- - pc->buflen = sizeof (*reqbuf);
- + pc->buflen = len;
- + pc->sense_data = reqbuf; /* The only reason to set this here is so
- + that cdrom_end_request can find the correct
- + buffer for dumps to the syslog. */
-
- rq = &HWIF(drive)->request_sense_request;
- rq->dev = MKDEV (major, (drive->select.b.unit) << PARTN_BITS);
- @@ -446,7 +528,7 @@
- rq->nr_sectors = 0;
- rq->current_nr_sectors = 0;
- rq->buffer = (char *)pc;
- - rq->sem = NULL;
- + rq->sem = sem;
- rq->bh = NULL;
- rq->bhtail = NULL;
- rq->next = NULL;
- @@ -477,9 +559,8 @@
-
- if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate)
- {
- - struct atapi_request_sense *reqbuf;
- - reqbuf = &drive->cdrom_info.sense_data;
- - cdrom_analyze_sense_data (drive, reqbuf, NULL);
- + struct packet_command *pc = (struct packet_command *)rq->buffer;
- + cdrom_analyze_sense_data (drive, pc->sense_data, NULL);
- }
-
- ide_end_request (uptodate, HWGROUP(drive));
- @@ -490,8 +571,8 @@
- buffers. */
- static void cdrom_saw_media_change (ide_drive_t *drive)
- {
- - CDROM_FLAGS (drive)->media_changed = 1;
- - CDROM_FLAGS (drive)->toc_valid = 0;
- + CDROM_STATE_FLAGS (drive)->media_changed = 1;
- + CDROM_STATE_FLAGS (drive)->toc_valid = 0;
- drive->cdrom_info.nsectors_buffered = 0;
- }
-
- @@ -520,97 +601,126 @@
- {
- cmd = rq->cmd;
-
- - /* Check for tray open */
- - if (sense_key == NOT_READY)
- + if (cmd == REQUEST_SENSE_COMMAND)
- {
- - struct packet_command *pc;
- - cdrom_saw_media_change (drive);
- + /* We got an error trying to get sense info from the drive
- + (probably while trying to recover from a former error).
- + Just give up. */
-
- - /* Fail the request if this is a read command. */
- - if (cmd == READ)
- - {
- - printk ("%s : tray open\n", drive->name);
- - cdrom_end_request (0, drive);
- - }
- + struct packet_command *pc = (struct packet_command *)rq->buffer;
- + pc->stat = 1;
- + cdrom_end_request (1, drive);
- + if (ide_error (drive, "request sense failure", stat))
- + return 1;
- + }
-
- - else
- + else if (cmd == PACKET_COMMAND)
- + {
- + /* All other functions, except for READ. */
- +
- + struct packet_command *pc = (struct packet_command *)rq->buffer;
- + struct semaphore *sem = NULL;
- +
- + /* Check for tray open. */
- + if (sense_key == NOT_READY)
- {
- - /* Otherwise, it's some other packet command.
- - Print an error message to the syslog.
- + cdrom_saw_media_change (drive);
- +
- + /* Print an error message to the syslog.
- Exception: don't print anything if this is a read subchannel
- command. This is because workman constantly polls the drive
- with this command, and we don't want to uselessly fill up
- the syslog. */
- - pc = (struct packet_command *)rq->buffer;
- if (pc->c[0] != SCMD_READ_SUBCHANNEL)
- - printk ("%s : tray open\n", drive->name);
- -
- - /* Set the error flag and complete the request. */
- - pc->stat = 1;
- - cdrom_end_request (1, drive);
- + printk ("%s : tray open or drive not ready\n", drive->name);
- }
- - }
-
- - /* Check for media change. */
- - else if (sense_key == UNIT_ATTENTION)
- - {
- - cdrom_saw_media_change (drive);
- - printk ("%s: media changed\n", drive->name);
- -
- - /* Return failure for a packet command, so that
- - cdrom_queue_packet_command can do a request sense before
- - the command gets retried. */
- + /* Check for media change. */
- + else if (sense_key == UNIT_ATTENTION)
- + {
- + cdrom_saw_media_change (drive);
- + printk ("%s: media changed\n", drive->name);
- + }
-
- - if (cmd == PACKET_COMMAND)
- + /* Otherwise, print an error. */
- + else
- {
- - struct packet_command *pc = (struct packet_command *)rq->buffer;
- - pc->stat = 1;
- - cdrom_end_request (1, drive);
- + ide_dump_status (drive, "packet command error", stat);
- }
-
- - /* Otherwise, it's a block read. Arrange to retry it.
- - But be sure to give up if we've retried too many times. */
- - else if ((++rq->errors > ERROR_MAX))
- + /* 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)
- {
- - cdrom_end_request (0, drive);
- + sem = rq->sem;
- + rq->sem = NULL;
- }
- - }
-
- - /* Don't attempt to retry if this was a packet command. */
- - else if (cmd == PACKET_COMMAND)
- - {
- - struct packet_command *pc = (struct packet_command *)rq->buffer;
- - ide_dump_status (drive, "packet command error", stat);
- - pc->stat = 1; /* signal error */
- + pc->stat = 1;
- cdrom_end_request (1, drive);
- - }
-
- - /* No point in retrying after an illegal request or data protect error.*/
- - else if (sense_key == ILLEGAL_REQUEST || sense_key == DATA_PROTECT)
- - {
- - ide_dump_status (drive, "command error", stat);
- - cdrom_end_request (0, drive);
- + if ((stat & ERR_STAT) != 0)
- + cdrom_queue_request_sense (drive, sem, pc->sense_data);
- }
-
- - /* If there were other errors, go to the default handler. */
- - else if ((err & ~ABRT_ERR) != 0)
- + else
- {
- - if (ide_error (drive, "cdrom_decode_status", stat))
- - return 1;
- - }
- + /* Handle errors from READ requests. */
-
- - /* Else, abort if we've racked up too many retries. */
- - else if ((++rq->errors > ERROR_MAX))
- - {
- - cdrom_end_request (0, drive);
- - }
- + /* Check for tray open. */
- + if (sense_key == NOT_READY)
- + {
- + cdrom_saw_media_change (drive);
-
- - /* If we got a CHECK_STATUS condition, and this was a READ request,
- - queue a request sense command to try to find out more about
- - what went wrong (and clear a unit attention)? For packet commands,
- - this is done separately in cdrom_queue_packet_command. */
- - if ((stat & ERR_STAT) != 0 && cmd == READ)
- - cdrom_queue_request_sense (drive);
- + /* Fail the request. */
- + printk ("%s : tray open\n", drive->name);
- + cdrom_end_request (0, drive);
- + }
- +
- + /* Check for media change. */
- + else if (sense_key == UNIT_ATTENTION)
- + {
- + 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);
- + }
- + }
- + /* No point in retrying after an illegal request or
- + data protect error.*/
- + else if (sense_key == ILLEGAL_REQUEST || sense_key == DATA_PROTECT)
- + {
- + ide_dump_status (drive, "command error", stat);
- + cdrom_end_request (0, drive);
- + }
- +
- + /* If there were other errors, go to the default handler. */
- + else if ((err & ~ABRT_ERR) != 0)
- + {
- + if (ide_error (drive, "cdrom_decode_status", stat))
- + return 1;
- + }
- +
- + /* Else, abort if we've racked up too many retries. */
- + else if ((++rq->errors > ERROR_MAX))
- + {
- + 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);
- + }
- }
-
- /* Retry, or handle the next request. */
- @@ -620,10 +730,14 @@
-
-
- /* Set up the device registers for transferring a packet command on DEV,
- - expecting to later transfer XFERLEN bytes. This should be followed
- - by a call to cdrom_transfer_packet_command; however, if this is a
- - drq_interrupt device, one must wait for an interrupt first. */
- -static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen)
- + 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 int cdrom_start_packet_command (ide_drive_t *drive, int xferlen,
- + ide_handler_t *handler)
- {
- /* Wait for the controller to be idle. */
- if (ide_wait_stat (drive, 0, BUSY_STAT, WAIT_READY)) return 1;
- @@ -636,19 +750,29 @@
- OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG);
- OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG);
- OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
- - OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- +
- + if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt)
- + {
- + ide_set_handler (drive, handler);
- + OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- + }
- + else
- + {
- + OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
- + (*handler) (drive);
- + }
-
- return 0;
- }
-
-
- -/* Send a packet command to DEV described by CMD_BUF and CMD_LEN.
- +/* 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. */
- static int cdrom_transfer_packet_command (ide_drive_t *drive,
- char *cmd_buf, int cmd_len)
- {
- - if (CDROM_FLAGS (drive)->drq_interrupt)
- + 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. */
- @@ -664,7 +788,7 @@
- }
-
- /* Send the command to the device. */
- - OUT_WORDS (cmd_buf, cmd_len/2);
- + cdrom_out_bytes (drive, cmd_buf, cmd_len);
-
- return 0;
- }
- @@ -714,7 +838,7 @@
- dest = info->sector_buffer + info->nsectors_buffered * SECTOR_SIZE;
- while (sectors_to_buffer > 0)
- {
- - IN_WORDS (dest, SECTOR_SIZE / 2);
- + cdrom_in_bytes (drive, dest, SECTOR_SIZE);
- --sectors_to_buffer;
- --sectors_to_transfer;
- ++info->nsectors_buffered;
- @@ -725,7 +849,7 @@
- while (sectors_to_transfer > 0)
- {
- char dum[SECTOR_SIZE];
- - IN_WORDS (dum, sizeof (dum) / 2);
- + cdrom_in_bytes (drive, dum, sizeof (dum));
- --sectors_to_transfer;
- }
- }
- @@ -753,9 +877,9 @@
- and quit this request. */
- while (len > 0)
- {
- - short dum = 0;
- - OUT_WORDS (&dum, 1);
- - len -= 2;
- + int dum = 0;
- + cdrom_out_bytes (drive, &dum, sizeof (dum));
- + len -= sizeof (dum);
- }
- }
-
- @@ -833,7 +957,7 @@
- {
- /* We need to throw away a sector. */
- char dum[SECTOR_SIZE];
- - IN_WORDS (dum, sizeof (dum) / 2);
- + cdrom_in_bytes (drive, dum, sizeof (dum));
-
- --rq->current_nr_sectors;
- --nskip;
- @@ -869,7 +993,7 @@
- /* Read this_transfer sectors into the current buffer. */
- while (this_transfer > 0)
- {
- - IN_WORDS (rq->buffer, SECTOR_SIZE / 2);
- + cdrom_in_bytes (drive, rq->buffer, SECTOR_SIZE);
- rq->buffer += SECTOR_SIZE;
- --rq->nr_sectors;
- --rq->current_nr_sectors;
- @@ -882,7 +1006,7 @@
-
- /* Done moving data!
- Wait for another interrupt. */
- - ide_set_handler(drive, &cdrom_read_intr); /* this one is okay */
- + ide_set_handler (drive, &cdrom_read_intr);
- }
-
-
- @@ -952,7 +1076,7 @@
- * However, for drq_interrupt devices, it is called from an interrupt
- * when the drive is ready to accept the command.
- */
- -static int cdrom_start_read_continuation (ide_drive_t *drive)
- +static void cdrom_start_read_continuation (ide_drive_t *drive)
- {
- struct packet_command pc;
- struct request *rq = HWGROUP(drive)->rq;
- @@ -981,7 +1105,7 @@
- drive->name, rq->current_nr_sectors);
- cdrom_end_request (0, drive);
- IDE_DO_REQUEST;
- - return 1;
- + return;
- }
-
- sector -= nskip;
- @@ -1016,23 +1140,18 @@
- pc.c[5] = conv.b.b0;
- }
-
- - if (cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c)))
- - return 1;
- + /* Set up to receive the data-ready interrupt from the drive. */
- + ide_set_handler (drive, &cdrom_read_intr);
-
- - /* Set up our interrupt handler and return. */
- - ide_set_handler(drive, &cdrom_read_intr); /* BUG: do this BEFORE triggering drive */
- -
- - return 0;
- + /* Send the command to the drive and return. */
- + (void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c));
- }
-
-
- /*
- * Start a read request from the CD-ROM.
- - * Returns 0 if the request was started successfully,
- - * 1 if there was an error and we should either retry or move on to the
- - * next request.
- */
- -static int cdrom_start_read (ide_drive_t *drive, unsigned int block)
- +static void cdrom_start_read (ide_drive_t *drive, unsigned int block)
- {
- struct request *rq = HWGROUP(drive)->rq;
-
- @@ -1042,23 +1161,13 @@
-
- /* Satisfy whatever we can of this request from our cached sector. */
- if (cdrom_read_from_buffer (drive))
- - return 1;
- + return;
-
- /* Clear the local sector buffer. */
- drive->cdrom_info.nsectors_buffered = 0;
-
- - if (cdrom_start_packet_command (drive, 32768))
- - return 1;
- -
- - if (CDROM_FLAGS (drive)->drq_interrupt)
- - ide_set_handler(drive, (ide_handler_t *)&cdrom_start_read_continuation); /* BUG: do this BEFORE triggering drive */
- - else
- - {
- - if (cdrom_start_read_continuation (drive))
- - return 1;
- - }
- -
- - return 0;
- + /* Start sending the read request to the drive. */
- + cdrom_start_packet_command (drive, 32768, cdrom_start_read_continuation);
- }
-
-
- @@ -1068,9 +1177,11 @@
- * Execute all other packet commands.
- */
-
- -/* Forward declaration */
- +/* Forward declarations. */
- static int
- -cdrom_request_sense (ide_drive_t *drive, struct atapi_request_sense *reqbuf);
- +cdrom_lockdoor (ide_drive_t *drive, int lockflag,
- + struct atapi_request_sense *reqbuf);
- +
-
-
- /* Interrupt routine for packet command completion. */
- @@ -1131,15 +1242,15 @@
- }
-
- /* Transfer the data. */
- - OUT_WORDS (pc->buffer, thislen / 2);
- + cdrom_out_bytes (drive, pc->buffer, thislen);
-
- /* If we haven't moved enough data to satisfy the drive,
- add some padding. */
- while (len > thislen)
- {
- - short dum = 0;
- - OUT_WORDS (&dum, 1);
- - len -= 2;
- + int dum = 0;
- + cdrom_out_bytes (drive, &dum, sizeof (dum));
- + len -= sizeof (dum);
- }
-
- /* Keep count of how much data we've moved. */
- @@ -1160,15 +1271,15 @@
- }
-
- /* Transfer the data. */
- - IN_WORDS (pc->buffer, thislen / 2);
- + cdrom_in_bytes (drive, pc->buffer, thislen);
-
- /* If we haven't moved enough data to satisfy the drive,
- add some padding. */
- while (len > thislen)
- {
- - short dum = 0;
- - IN_WORDS (&dum, 1);
- - len -= 2;
- + int dum = 0;
- + cdrom_in_bytes (drive, &dum, sizeof (dum));
- + len -= sizeof (dum);
- }
-
- /* Keep count of how much data we've moved. */
- @@ -1184,26 +1295,24 @@
- }
-
- /* Now we wait for another interrupt. */
- - ide_set_handler(drive, &cdrom_pc_intr); /* this one is okay */
- + ide_set_handler (drive, &cdrom_pc_intr);
- }
-
-
- -static int cdrom_do_pc_continuation (ide_drive_t *drive)
- +static void cdrom_do_pc_continuation (ide_drive_t *drive)
- {
- struct request *rq = HWGROUP(drive)->rq;
- struct packet_command *pc = (struct packet_command *)rq->buffer;
-
- - if (cdrom_transfer_packet_command (drive, pc->c, sizeof (pc->c)))
- - return 1;
- + /* Set up a handler for the data-ready interrupt. */
- + ide_set_handler (drive, &cdrom_pc_intr);
-
- - /* Set up our interrupt handler and return. */
- - ide_set_handler(drive, &cdrom_pc_intr); /* BUG: do this BEFORE triggering drive */
- -
- - return 0;
- + /* Send the command to the drive and return. */
- + cdrom_transfer_packet_command (drive, pc->c, sizeof (pc->c));
- }
-
-
- -static int cdrom_do_packet_command (ide_drive_t *drive)
- +static void cdrom_do_packet_command (ide_drive_t *drive)
- {
- int len;
- struct request *rq = HWGROUP(drive)->rq;
- @@ -1214,42 +1323,34 @@
-
- pc->stat = 0;
-
- - if (cdrom_start_packet_command (drive, len))
- - return 1;
- + /* Start sending the command to the drive. */
- + cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation);
- +}
-
- - if (CDROM_FLAGS (drive)->drq_interrupt)
- - ide_set_handler(drive, (ide_handler_t *)&cdrom_do_pc_continuation); /* BUG: do this BEFORE triggering drive */
- - else
- - {
- - if (cdrom_do_pc_continuation (drive))
- - return 1;
- - }
-
- - return 0;
- +/* Sleep for TIME jiffies.
- + Not to be called from an interrupt handler. */
- +static
- +void cdrom_sleep (int time)
- +{
- + current->state = TASK_INTERRUPTIBLE;
- + current->timeout = jiffies + time;
- + schedule ();
- }
-
-
- static
- -int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
- +void cdrom_queue_request (ide_drive_t *drive, struct request *req)
- {
- - int retries = 3;
- unsigned long flags;
- - struct request req, **p, **pfirst;
- - struct semaphore sem = MUTEX_LOCKED;
- + struct request **p, **pfirst;
- int major = HWIF(drive)->major;
- + struct semaphore sem = MUTEX_LOCKED;
-
- - retry:
- - req.dev = MKDEV (major, (drive->select.b.unit) << PARTN_BITS);
- - req.cmd = PACKET_COMMAND;
- - req.errors = 0;
- - req.sector = 0;
- - req.nr_sectors = 0;
- - req.current_nr_sectors = 0;
- - req.buffer = (char *)pc;
- - req.sem = &sem;
- - req.bh = NULL;
- - req.bhtail = NULL;
- - req.next = NULL;
- + req->dev = MKDEV (major, (drive->select.b.unit) << PARTN_BITS);
- + req->sem = &sem;
- + req->errors = 0;
- + req->next = NULL;
-
- save_flags (flags);
- cli ();
- @@ -1260,42 +1361,88 @@
- {
- p = &((*p)->next);
- }
- - *p = &req;
- + *p = req;
- if (p == pfirst)
- blk_dev[major].request_fn ();
-
- + down (&sem);
- +
- restore_flags (flags);
- +}
- +
- +
- +static
- +int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
- +{
- + struct atapi_request_sense my_reqbuf;
- + int retries = 10;
- + struct request req;
- +
- + /* If our caller has not provided a place to stick any sense data,
- + use our own area. */
- + if (pc->sense_data == NULL)
- + pc->sense_data = &my_reqbuf;
- + pc->sense_data->sense_key = 0;
- +
- + /* Start of retry loop. */
- + do {
- + req.cmd = PACKET_COMMAND;
- + req.sector = 0;
- + req.nr_sectors = 0;
- + req.current_nr_sectors = 0;
- + req.buffer = (char *)pc;
- + req.bh = NULL;
- + req.bhtail = NULL;
-
- - down (&sem);
- + cdrom_queue_request (drive, &req);
-
- - if (pc->stat != 0)
- - {
- - /* The request failed. Try to do a request sense to get more information
- - about the error; store the result in the cdrom_info struct
- - for this drive. Check to be sure that it wasn't a request sense
- - request that failed, though, to prevent infinite loops. */
- -
- - struct atapi_request_sense *reqbuf = &drive->cdrom_info.sense_data;
- + if (pc->stat != 0)
- + {
- + /* The request failed. Retry if it was due to a unit attention status
- + (usually means media was changed). */
- + struct atapi_request_sense *reqbuf = pc->sense_data;
- +
- + if (reqbuf->sense_key == UNIT_ATTENTION)
- + ;
- +
- + /* Also retry if the drive is in the process of loading a disk.
- + This time, however, wait a little between retries to give
- + the drive time. */
- + else if (reqbuf->sense_key == NOT_READY && reqbuf->asc == 4)
- + {
- + cdrom_sleep (HZ);
- + }
- +
- + /* Otherwise, don't retry. */
- + else
- + retries = 0;
- +
- + --retries;
- + }
- +
- + /* End of retry loop. */
- + } while (pc->stat != 0 && retries >= 0);
-
- - if (pc->c[0] == REQUEST_SENSE || cdrom_request_sense (drive, reqbuf))
- - {
- - memset (reqbuf, 0, sizeof (*reqbuf));
- - reqbuf->asc = 0xff;
- - }
- - cdrom_analyze_sense_data (drive, reqbuf, pc);
-
- - /* If the error was a unit attention (usually means media was changed),
- - retry the command. */
- - if (reqbuf->sense_key == UNIT_ATTENTION && retries > 0)
- + /* Return an error if the command failed. */
- + if (pc->stat != 0)
- + return -EIO;
- +
- + else
- + {
- + /* The command succeeded. If it was anything other than a request sense,
- + eject, or door lock command, and we think that the door is presently
- + unlocked, lock it again. (The door was probably unlocked via
- + an explicit CDROMEJECT ioctl.) */
- + if (CDROM_STATE_FLAGS (drive)->door_locked == 0 &&
- + (pc->c[0] != REQUEST_SENSE &&
- + pc->c[0] != ALLOW_MEDIUM_REMOVAL &&
- + pc->c[0] != START_STOP))
- {
- - --retries;
- - goto retry;
- + (void) cdrom_lockdoor (drive, 1, NULL);
- }
- -
- - return -EIO;
- + return 0;
- }
- - else
- - return 0;
- }
-
-
- @@ -1310,6 +1457,14 @@
-
- if (rq -> cmd == PACKET_COMMAND || rq -> cmd == REQUEST_SENSE_COMMAND)
- cdrom_do_packet_command (drive);
- +
- + else if (rq -> cmd == RESET_DRIVE_COMMAND)
- + {
- + cdrom_end_request (1, drive);
- + if (ide_do_reset (drive))
- + return;
- + }
- +
- else if (rq -> cmd != READ)
- {
- printk ("ide-cd: bad cmd %d\n", rq -> cmd);
- @@ -1322,7 +1477,13 @@
-
-
- /****************************************************************************
- - * ioctl handling.
- + * Ioctl handling.
- + *
- + * Routines which queue packet commands take as a final argument a pointer
- + * to an atapi_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.
- */
-
- static inline
- @@ -1374,59 +1535,74 @@
- }
-
-
- -static void
- -cdrom_check_status (ide_drive_t *drive)
- -{
- - struct packet_command pc;
- -
- - memset (&pc, 0, sizeof (pc));
- -
- - pc.c[0] = TEST_UNIT_READY;
- -
- - (void) cdrom_queue_packet_command (drive, &pc);
- -}
- -
- -
- static int
- -cdrom_request_sense (ide_drive_t *drive, struct atapi_request_sense *reqbuf)
- +cdrom_check_status (ide_drive_t *drive,
- + struct atapi_request_sense *reqbuf)
- {
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
-
- - pc.c[0] = REQUEST_SENSE;
- - pc.c[4] = sizeof (*reqbuf);
- - pc.buffer = (char *)reqbuf;
- - pc.buflen = sizeof (*reqbuf);
- + pc.sense_data = reqbuf;
- + pc.c[0] = TEST_UNIT_READY;
-
- return cdrom_queue_packet_command (drive, &pc);
- }
-
-
- -#if 0
- /* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
- static int
- -cdrom_lockdoor (ide_drive_t *drive, int lockflag)
- +cdrom_lockdoor (ide_drive_t *drive, int lockflag,
- + struct atapi_request_sense *reqbuf)
- {
- + struct atapi_request_sense my_reqbuf;
- + int stat;
- struct packet_command pc;
-
- - memset (&pc, 0, sizeof (pc));
- + if (reqbuf == NULL)
- + reqbuf = &my_reqbuf;
-
- - pc.c[0] = ALLOW_MEDIUM_REMOVAL;
- - pc.c[4] = (lockflag != 0);
- - return cdrom_queue_packet_command (drive, &pc);
- + /* 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_data = reqbuf;
- +
- + pc.c[0] = ALLOW_MEDIUM_REMOVAL;
- + pc.c[4] = (lockflag != 0);
- + stat = cdrom_queue_packet_command (drive, &pc);
- + }
- +
- + if (stat == 0)
- + CDROM_STATE_FLAGS (drive)->door_locked = lockflag;
- + else
- + {
- + /* If we got an illegal field error, the drive
- + probably cannot lock the door. */
- + if (reqbuf->sense_key == ILLEGAL_REQUEST && reqbuf->asc == 0x24)
- + {
- + printk ("%s: door locking not supported\n", drive->name);
- + CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
- + stat = 0;
- + CDROM_STATE_FLAGS (drive)->door_locked = lockflag;
- + }
- + }
- + return stat;
- }
- -#endif
-
-
- /* 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)
- +cdrom_eject (ide_drive_t *drive, int ejectflag,
- + struct atapi_request_sense *reqbuf)
- {
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
-
- pc.c[0] = START_STOP;
- pc.c[4] = 2 + (ejectflag != 0);
- @@ -1435,11 +1611,13 @@
-
-
- static int
- -cdrom_pause (ide_drive_t *drive, int pauseflag)
- +cdrom_pause (ide_drive_t *drive, int pauseflag,
- + struct atapi_request_sense *reqbuf)
- {
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
-
- pc.c[0] = SCMD_PAUSE_RESUME;
- pc.c[8] = !pauseflag;
- @@ -1448,11 +1626,13 @@
-
-
- static int
- -cdrom_startstop (ide_drive_t *drive, int startflag)
- +cdrom_startstop (ide_drive_t *drive, int startflag,
- + struct atapi_request_sense *reqbuf)
- {
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
-
- pc.c[0] = START_STOP;
- pc.c[1] = 1;
- @@ -1462,12 +1642,44 @@
-
-
- static int
- +cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity,
- + struct atapi_request_sense *reqbuf)
- +{
- + struct {
- + unsigned lba;
- + unsigned blocklen;
- + } capbuf;
- +
- + int stat;
- + struct packet_command pc;
- +
- + memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
- +
- + pc.c[0] = READ_CAPACITY;
- + pc.buffer = (char *)&capbuf;
- + pc.buflen = sizeof (capbuf);
- +
- + stat = cdrom_queue_packet_command (drive, &pc);
- + if (stat == 0)
- + {
- + byte_swap_long (&capbuf.lba);
- + *capacity = capbuf.lba;
- + }
- +
- + return stat;
- +}
- +
- +
- +static int
- cdrom_read_tocentry (ide_drive_t *drive, int trackno, int msf_flag,
- - char *buf, int buflen)
- + int format, char *buf, int buflen,
- + struct atapi_request_sense *reqbuf)
- {
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = buflen;
- @@ -1475,6 +1687,7 @@
- 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);
- }
- @@ -1482,11 +1695,16 @@
-
- /* Try to read the entire TOC for the disk into our internal buffer. */
- static int
- -cdrom_read_toc (ide_drive_t *drive)
- +cdrom_read_toc (ide_drive_t *drive,
- + struct atapi_request_sense *reqbuf)
- {
- int msf_flag;
- int stat, ntracks, i;
- struct atapi_toc *toc = drive->cdrom_info.toc;
- + struct {
- + struct atapi_toc_header hdr;
- + struct atapi_toc_entry ent;
- + } ms_tmp;
-
- if (toc == NULL)
- {
- @@ -1504,18 +1722,19 @@
-
- /* Check to see if the existing data is still valid.
- If it is, just return. */
- - if (CDROM_FLAGS (drive)->toc_valid)
- - cdrom_check_status (drive);
- + if (CDROM_STATE_FLAGS (drive)->toc_valid)
- + (void) cdrom_check_status (drive, NULL);
-
- - if (CDROM_FLAGS (drive)->toc_valid) return 0;
- + if (CDROM_STATE_FLAGS (drive)->toc_valid) return 0;
-
- /* Some drives can't return TOC data in LBA format. */
- - msf_flag = (CDROM_FLAGS (drive)->no_lba_toc);
- + msf_flag = (CDROM_CONFIG_FLAGS (drive)->no_lba_toc);
-
- /* First read just the header, so we know how long the TOC is. */
- - stat = cdrom_read_tocentry (drive, 0, msf_flag, (char *)toc,
- + stat = cdrom_read_tocentry (drive, 0, msf_flag, 0, (char *)&toc->hdr,
- sizeof (struct atapi_toc_header) +
- - sizeof (struct atapi_toc_entry));
- + sizeof (struct atapi_toc_entry),
- + reqbuf);
- if (stat) return stat;
-
- ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
- @@ -1523,9 +1742,10 @@
- if (ntracks > MAX_TRACKS) ntracks = MAX_TRACKS;
-
- /* Now read the whole schmeer. */
- - stat = cdrom_read_tocentry (drive, 0, msf_flag, (char *)toc,
- + stat = cdrom_read_tocentry (drive, 0, msf_flag, 0, (char *)&toc->hdr,
- sizeof (struct atapi_toc_header) +
- - (ntracks+1) * sizeof (struct atapi_toc_entry));
- + (ntracks+1) * sizeof (struct atapi_toc_entry),
- + reqbuf);
- if (stat) return stat;
- byte_swap_word (&toc->hdr.toc_length);
- for (i=0; i<=ntracks; i++)
- @@ -1539,8 +1759,32 @@
- byte_swap_long (&toc->ent[i].lba);
- }
-
- + /* Read the multisession information. */
- + stat = cdrom_read_tocentry (drive, 0, msf_flag, 1,
- + (char *)&ms_tmp, sizeof (ms_tmp),
- + reqbuf);
- + if (stat) return stat;
- + if (msf_flag)
- + {
- + byte *adr = (byte *)&(ms_tmp.ent.lba);
- + toc->last_session_lba = msf_to_lba (adr[1], adr[2], adr[3]);
- + }
- + else
- + {
- + byte_swap_long (&ms_tmp.ent.lba);
- + toc->last_session_lba = ms_tmp.ent.lba;
- + }
- + toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
- +
- + /* Now try to get the total cdrom capacity. */
- + stat = cdrom_read_capacity (drive, &toc->capacity, reqbuf);
- + if (stat) toc->capacity = 0x1fffff;
- +
- + HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS]
- + = toc->capacity * SECTORS_PER_FRAME;
- +
- /* Remember that we've read this stuff. */
- - CDROM_FLAGS (drive)->toc_valid = 1;
- + CDROM_STATE_FLAGS (drive)->toc_valid = 1;
-
- return 0;
- }
- @@ -1548,11 +1792,13 @@
-
- static int
- cdrom_read_subchannel (ide_drive_t *drive,
- - char *buf, int buflen)
- + char *buf, int buflen,
- + struct atapi_request_sense *reqbuf)
- {
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = buflen;
- @@ -1568,11 +1814,13 @@
- /* modeflag: 0 = current, 1 = changeable mask, 2 = default, 3 = saved */
- static int
- cdrom_mode_sense (ide_drive_t *drive, int pageno, int modeflag,
- - char *buf, int buflen)
- + char *buf, int buflen,
- + struct atapi_request_sense *reqbuf)
- {
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = buflen;
- @@ -1585,11 +1833,13 @@
-
-
- static int
- -cdrom_mode_select (ide_drive_t *drive, int pageno, char *buf, int buflen)
- +cdrom_mode_select (ide_drive_t *drive, int pageno, char *buf, int buflen,
- + struct atapi_request_sense *reqbuf)
- {
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = - buflen;
- @@ -1603,11 +1853,13 @@
-
-
- static int
- -cdrom_play_lba_range_play12 (ide_drive_t *drive, int lba_start, int lba_end)
- +cdrom_play_lba_range_play12 (ide_drive_t *drive, int lba_start, int lba_end,
- + struct atapi_request_sense *reqbuf)
- {
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
-
- pc.c[0] = SCMD_PLAYAUDIO12;
- *(int *)(&pc.c[2]) = lba_start;
- @@ -1620,17 +1872,19 @@
-
-
- static int
- -cdrom_play_lba_range_msf (ide_drive_t *drive, int lba_start, int lba_end)
- +cdrom_play_lba_range_msf (ide_drive_t *drive, int lba_start, int lba_end,
- + struct atapi_request_sense *reqbuf)
- {
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
-
- pc.c[0] = SCMD_PLAYAUDIO_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]);
-
- - if (CDROM_FLAGS (drive)->msf_as_bcd)
- + if (CDROM_CONFIG_FLAGS (drive)->msf_as_bcd)
- {
- pc.c[3] = bin2bcd (pc.c[3]);
- pc.c[4] = bin2bcd (pc.c[4]);
- @@ -1647,7 +1901,8 @@
- /* Play audio starting at LBA LBA_START and finishing with the
- LBA before LBA_END. */
- static int
- -cdrom_play_lba_range (ide_drive_t *drive, int lba_start, int lba_end)
- +cdrom_play_lba_range (ide_drive_t *drive, int lba_start, int lba_end,
- + struct atapi_request_sense *reqbuf)
- {
- /* This is rather annoying.
- My NEC-260 won't recognize group 5 commands such as PLAYAUDIO12;
- @@ -1660,27 +1915,29 @@
- great. Otherwise, if the drive reports an illegal command code,
- try PLAYAUDIO_MSF using the NEC 260-style bcd parameters. */
-
- - if (CDROM_FLAGS (drive)->no_playaudio12)
- - return cdrom_play_lba_range_msf (drive, lba_start, lba_end);
- + if (CDROM_CONFIG_FLAGS (drive)->no_playaudio12)
- + return cdrom_play_lba_range_msf (drive, lba_start, lba_end, reqbuf);
- else
- {
- int stat;
- - struct atapi_request_sense *reqbuf;
- + struct atapi_request_sense my_reqbuf;
-
- - stat = cdrom_play_lba_range_play12 (drive, lba_start, lba_end);
- + if (reqbuf == NULL)
- + reqbuf = &my_reqbuf;
- +
- + stat = cdrom_play_lba_range_play12 (drive, lba_start, lba_end, reqbuf);
- if (stat == 0) return 0;
-
- /* It failed. Try to find out why. */
- - reqbuf = &drive->cdrom_info.sense_data;
- - if (reqbuf->sense_key == 0x05 && reqbuf->asc == 0x20)
- + if (reqbuf->sense_key == ILLEGAL_REQUEST && reqbuf->asc == 0x20)
- {
- /* The drive didn't recognize the command.
- Retry with the MSF variant. */
- printk ("%s: Drive does not support PLAYAUDIO12; "
- "trying PLAYAUDIO_MSF\n", drive->name);
- - CDROM_FLAGS (drive)->no_playaudio12 = 1;
- - CDROM_FLAGS (drive)->msf_as_bcd = 1;
- - return cdrom_play_lba_range_msf (drive, lba_start, lba_end);
- + CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
- + CDROM_CONFIG_FLAGS (drive)->msf_as_bcd = 1;
- + return cdrom_play_lba_range_msf (drive, lba_start, lba_end, reqbuf);
- }
-
- /* Failed for some other reason. Give up. */
- @@ -1691,13 +1948,14 @@
-
- static
- int cdrom_get_toc_entry (ide_drive_t *drive, int track,
- - struct atapi_toc_entry **ent)
- + struct atapi_toc_entry **ent,
- + struct atapi_request_sense *reqbuf)
- {
- int stat, ntracks;
- struct atapi_toc *toc;
-
- /* Make sure our saved TOC is valid. */
- - stat = cdrom_read_toc (drive);
- + stat = cdrom_read_toc (drive, reqbuf);
- if (stat) return stat;
-
- toc = drive->cdrom_info.toc;
- @@ -1716,25 +1974,94 @@
- }
-
-
- +static int
- +cdrom_read_block (ide_drive_t *drive, int format, int lba,
- + char *buf, int buflen,
- + struct atapi_request_sense *reqbuf)
- +{
- + struct packet_command pc;
- + struct atapi_request_sense my_reqbuf;
- + int stat;
- +
- + if (reqbuf == NULL)
- + reqbuf = &my_reqbuf;
- +
- + memset (&pc, 0, sizeof (pc));
- + pc.sense_data = reqbuf;
- +
- + pc.buffer = buf;
- + pc.buflen = buflen;
- +
- + if (CDROM_CONFIG_FLAGS (drive)->old_readcd)
- + pc.c[0] = 0xd4;
- + else
- + pc.c[0] = READ_CD;
- +
- + pc.c[1] = (format << 2);
- + *(int *)(&pc.c[2]) = lba;
- + byte_swap_long ((int *)(&pc.c[2]));
- + pc.c[8] = 1; /* one block */
- + pc.c[9] = 0x10;
- +
- + stat = cdrom_queue_packet_command (drive, &pc);
- +
- + /* If the drive doesn't recognize the READ CD opcode, retry the command
- + with an older opcode for that command. */
- + if (stat && reqbuf->sense_key == ILLEGAL_REQUEST && reqbuf->asc == 0x20 &&
- + CDROM_CONFIG_FLAGS (drive)->old_readcd == 0)
- + {
- + printk ("%s: Drive does not recognize READ_CD; trying opcode 0xd4\n",
- + drive->name);
- + CDROM_CONFIG_FLAGS (drive)->old_readcd = 1;
- + return cdrom_read_block (drive, format, lba, buf, buflen, reqbuf);
- + }
- +
- + return stat;
- +}
- +
- +
- int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
- - struct file *file, unsigned int cmd, unsigned long arg)
- + struct file *file, unsigned int cmd, unsigned long arg)
- {
- switch (cmd)
- {
- case CDROMEJECT:
- - return cdrom_eject (drive, 0);
- + {
- + int stat;
- +
- + if (drive->usage > 1)
- + return -EBUSY;
- +
- + stat = cdrom_lockdoor (drive, 0, NULL);
- + if (stat) return stat;
- +
- + return cdrom_eject (drive, 0, NULL);
- + }
- +
- + case CDROMEJECT_SW:
- + {
- + CDROM_STATE_FLAGS (drive)->eject_on_close = arg;
- + return 0;
- + }
-
- case CDROMPAUSE:
- - return cdrom_pause (drive, 1);
- + return cdrom_pause (drive, 1, NULL);
-
- case CDROMRESUME:
- - return cdrom_pause (drive, 0);
- + return cdrom_pause (drive, 0, NULL);
-
- case CDROMSTART:
- - return cdrom_startstop (drive, 1);
- + return cdrom_startstop (drive, 1, NULL);
-
- case CDROMSTOP:
- - return cdrom_startstop (drive, 0);
- + {
- + int stat;
- +
- + stat = cdrom_startstop (drive, 0, NULL);
- + if (stat) return stat;
- + /* pit says the Dolphin needs this. */
- + return cdrom_eject (drive, 1, NULL);
- + }
-
- case CDROMPLAYMSF:
- {
- @@ -1753,7 +2080,7 @@
-
- if (lba_end <= lba_start) return -EINVAL;
-
- - return cdrom_play_lba_range (drive, lba_start, lba_end);
- + return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
- }
-
- /* Like just about every other Linux cdrom driver, we ignore the
- @@ -1769,9 +2096,9 @@
-
- memcpy_fromfs (&ti, (void *) arg, sizeof(ti));
-
- - stat = cdrom_get_toc_entry (drive, ti.cdti_trk0, &first_toc);
- + stat = cdrom_get_toc_entry (drive, ti.cdti_trk0, &first_toc, NULL);
- if (stat) return stat;
- - stat = cdrom_get_toc_entry (drive, ti.cdti_trk1, &last_toc);
- + stat = cdrom_get_toc_entry (drive, ti.cdti_trk1, &last_toc, NULL);
- if (stat) return stat;
-
- if (ti.cdti_trk1 != CDROM_LEADOUT) ++last_toc;
- @@ -1780,7 +2107,7 @@
-
- if (lba_end <= lba_start) return -EINVAL;
-
- - return cdrom_play_lba_range (drive, lba_start, lba_end);
- + return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
- }
-
- case CDROMREADTOCHDR:
- @@ -1793,7 +2120,7 @@
- if (stat) return stat;
-
- /* Make sure our saved TOC is valid. */
- - stat = cdrom_read_toc (drive);
- + stat = cdrom_read_toc (drive, NULL);
- if (stat) return stat;
-
- toc = drive->cdrom_info.toc;
- @@ -1818,7 +2145,7 @@
-
- memcpy_fromfs (&tocentry, (void *) arg, sizeof (tocentry));
-
- - stat = cdrom_get_toc_entry (drive, tocentry.cdte_track, &toce);
- + stat = cdrom_get_toc_entry (drive, tocentry.cdte_track, &toce, NULL);
- if (stat) return stat;
-
- tocentry.cdte_ctrl = toce->control;
- @@ -1853,7 +2180,7 @@
-
- memcpy_fromfs (&subchnl, (void *) arg, sizeof (subchnl));
-
- - stat = cdrom_read_subchannel (drive, buffer, sizeof (buffer));
- + stat = cdrom_read_subchannel (drive, buffer, sizeof (buffer), NULL);
- if (stat) return stat;
-
- abs_lba = *(int *)&buffer[8];
- @@ -1898,9 +2225,9 @@
- if (stat) return stat;
- memcpy_fromfs (&volctrl, (void *) arg, sizeof (volctrl));
-
- - stat = cdrom_mode_sense (drive, 0x0e, 0, buffer, sizeof (buffer));
- + stat = cdrom_mode_sense (drive, 0x0e, 0, buffer, sizeof (buffer),NULL);
- if (stat) return stat;
- - stat = cdrom_mode_sense (drive, 0x0e, 1, mask , sizeof (buffer));
- + stat = cdrom_mode_sense (drive, 0x0e, 1, mask , sizeof (buffer),NULL);
- if (stat) return stat;
-
- buffer[1] = buffer[2] = 0;
- @@ -1910,35 +2237,219 @@
- buffer[21] = volctrl.channel2 & mask[21];
- buffer[23] = volctrl.channel3 & mask[23];
-
- - return cdrom_mode_select (drive, 0x0e, buffer, sizeof (buffer));
- + return cdrom_mode_select (drive, 0x0e, buffer, sizeof (buffer), NULL);
- + }
- +
- + case CDROMVOLREAD:
- + {
- + struct cdrom_volctrl volctrl;
- + char buffer[24];
- + int stat;
- +
- + stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (volctrl));
- + if (stat) return stat;
- +
- + stat = cdrom_mode_sense (drive, 0x0e, 0, buffer, sizeof (buffer), NULL);
- + if (stat) return stat;
- +
- + volctrl.channel0 = buffer[17];
- + volctrl.channel1 = buffer[19];
- + volctrl.channel2 = buffer[21];
- + volctrl.channel3 = buffer[23];
- +
- + memcpy_tofs ((void *) arg, &volctrl, sizeof (volctrl));
- +
- + return 0;
- + }
- +
- + case CDROMMULTISESSION:
- + {
- + struct cdrom_multisession ms_info;
- + struct atapi_toc *toc;
- + int stat;
- +
- + stat = verify_area (VERIFY_READ, (void *)arg, sizeof (ms_info));
- + if (stat) return stat;
- + stat = verify_area (VERIFY_WRITE, (void *)arg, sizeof (ms_info));
- + if (stat) return stat;
- +
- + memcpy_fromfs (&ms_info, (void *)arg, sizeof (ms_info));
- +
- + /* Make sure the TOC information is valid. */
- + stat = cdrom_read_toc (drive, NULL);
- + if (stat) return stat;
- +
- + toc = drive->cdrom_info.toc;
- +
- + if (ms_info.addr_format == CDROM_MSF)
- + lba_to_msf (toc->last_session_lba,
- + &ms_info.addr.msf.minute,
- + &ms_info.addr.msf.second,
- + &ms_info.addr.msf.frame);
- +
- + else if (ms_info.addr_format == CDROM_LBA)
- + ms_info.addr.lba = toc->last_session_lba;
- +
- + else
- + return -EINVAL;
- +
- + ms_info.xa_flag = toc->xa_flag;
- +
- + memcpy_tofs ((void *)arg, &ms_info, sizeof (ms_info));
- +
- + return 0;
- + }
- +
- + /* Read 2352 byte blocks from audio tracks. */
- + case CDROMREADAUDIO:
- + {
- + int stat, lba;
- + struct atapi_toc *toc;
- + struct cdrom_read_audio ra;
- + char buf[CD_FRAMESIZE_RAW];
- +
- + /* Make sure the TOC is up to date. */
- + stat = cdrom_read_toc (drive, NULL);
- + if (stat) return stat;
- +
- + toc = drive->cdrom_info.toc;
- +
- + stat = verify_area (VERIFY_READ, (char *)arg, sizeof (ra));
- + if (stat) return stat;
- +
- + memcpy_fromfs (&ra, (void *)arg, sizeof (ra));
- +
- + if (ra.nframes < 0 || ra.nframes > toc->capacity)
- + return -EINVAL;
- + else if (ra.nframes == 0)
- + return 0;
- +
- + stat = verify_area (VERIFY_WRITE, (char *)ra.buf,
- + ra.nframes * CD_FRAMESIZE_RAW);
- + if (stat) return stat;
- +
- + if (ra.addr_format == CDROM_MSF)
- + lba = msf_to_lba (ra.addr.msf.minute, ra.addr.msf.second,
- + ra.addr.msf.frame);
- +
- + else if (ra.addr_format == CDROM_LBA)
- + lba = ra.addr.lba;
- +
- + else
- + return -EINVAL;
- +
- + if (lba < 0 || lba >= toc->capacity)
- + return -EINVAL;
- +
- + while (ra.nframes > 0)
- + {
- + stat = cdrom_read_block (drive, 1, lba, buf,
- + CD_FRAMESIZE_RAW, NULL);
- + if (stat) return stat;
- + memcpy_tofs (ra.buf, buf, CD_FRAMESIZE_RAW);
- + ra.buf += CD_FRAMESIZE_RAW;
- + --ra.nframes;
- + ++lba;
- + }
- +
- + return 0;
- + }
- +
- + case CDROMREADMODE1:
- + case CDROMREADMODE2:
- + {
- + struct cdrom_msf msf;
- + int blocksize, format, stat, lba;
- + struct atapi_toc *toc;
- + char buf[CD_FRAMESIZE_RAW0];
- +
- + if (cmd == CDROMREADMODE1)
- + {
- + blocksize = CD_FRAMESIZE;
- + format = 2;
- + }
- + else
- + {
- + blocksize = CD_FRAMESIZE_RAW0;
- + format = 3;
- + }
- +
- + stat = verify_area (VERIFY_READ, (char *)arg, sizeof (msf));
- + if (stat) return stat;
- + stat = verify_area (VERIFY_WRITE, (char *)arg, blocksize);
- + if (stat) return stat;
- +
- + memcpy_fromfs (&msf, (void *)arg, sizeof (msf));
- +
- + lba = msf_to_lba (msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0);
- +
- + /* Make sure the TOC is up to date. */
- + stat = cdrom_read_toc (drive, NULL);
- + if (stat) return stat;
- +
- + toc = drive->cdrom_info.toc;
- +
- + if (lba < 0 || lba >= toc->capacity)
- + return -EINVAL;
- +
- + stat = cdrom_read_block (drive, format, lba, buf, blocksize, NULL);
- + if (stat) return stat;
- +
- + memcpy_tofs ((char *)arg, buf, blocksize);
- + return 0;
- }
-
- +#if 0 /* Doesn't work reliably yet. */
- + case CDROMRESET:
- + {
- + struct request req;
- + memset (&req, 0, sizeof (req));
- + req.cmd = RESET_DRIVE_COMMAND;
- + cdrom_queue_request (drive, &req);
- + return 0;
- + }
- +#endif
- +
- +
- #ifdef TEST
- case 0x1234:
- {
- int stat;
- struct packet_command pc;
- + int len, lena;
-
- memset (&pc, 0, sizeof (pc));
-
- stat = verify_area (VERIFY_READ, (void *) arg, sizeof (pc.c));
- if (stat) return stat;
- memcpy_fromfs (&pc.c, (void *) arg, sizeof (pc.c));
- + arg += sizeof (pc.c);
-
- - return cdrom_queue_packet_command (drive, &pc);
- - }
- + stat = verify_area (VERIFY_READ, (void *) arg, sizeof (len));
- + if (stat) return stat;
- + memcpy_fromfs (&len, (void *) arg , sizeof (len));
- + arg += sizeof (len);
-
- - case 0x1235:
- - {
- - int stat;
- - struct atapi_request_sense reqbuf;
- + if (len > 0) {
- + stat = verify_area (VERIFY_WRITE, (void *) arg, len);
- + if (stat) return stat;
- + }
-
- - stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (reqbuf));
- - if (stat) return stat;
- + lena = len;
- + if (lena < 0) lena = 0;
-
- - stat = cdrom_request_sense (drive, &reqbuf);
- + {
- + char buf[lena];
- + if (len > 0) {
- + pc.buflen = len;
- + pc.buffer = buf;
- + }
-
- - memcpy_tofs ((void *) arg, &reqbuf, sizeof (reqbuf));
- + stat = cdrom_queue_packet_command (drive, &pc);
- +
- + if (len > 0)
- + memcpy_tofs ((void *)arg, buf, len);
- + }
-
- return stat;
- }
- @@ -1960,10 +2471,10 @@
- {
- int retval;
-
- - cdrom_check_status (drive);
- + (void) cdrom_check_status (drive, NULL);
-
- - retval = CDROM_FLAGS (drive)->media_changed;
- - CDROM_FLAGS (drive)->media_changed = 0;
- + retval = CDROM_STATE_FLAGS (drive)->media_changed;
- + CDROM_STATE_FLAGS (drive)->media_changed = 0;
-
- return retval;
- }
- @@ -1972,15 +2483,43 @@
- int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
- {
- /* no write access */
- - if (fp->f_mode & 2) return -EROFS;
- + if (fp->f_mode & 2)
- + {
- + --drive->usage;
- + return -EROFS;
- + }
-
- -#if 0 /* With this, one cannot eject a disk with workman */
- - /* If this is the first open, lock the door. */
- + /* If this is the first open, check the drive status. */
- if (drive->usage == 1)
- - (void) cdrom_lockdoor (drive, 1);
- -#endif
- + {
- + int stat;
- + struct atapi_request_sense my_reqbuf;
- + my_reqbuf.sense_key = 0;
- +
- + /* Get the drive status. */
- + stat = cdrom_check_status (drive, &my_reqbuf);
- +
- + /* If the tray is open, try to close it. */
- + if (stat && my_reqbuf.sense_key == NOT_READY)
- + {
- + cdrom_eject (drive, 1, &my_reqbuf);
- + stat = cdrom_check_status (drive, &my_reqbuf);
- + }
- +
- + /* Return an error if there are still problems. */
- + if (stat && my_reqbuf.sense_key != UNIT_ATTENTION)
- + {
- + --drive->usage;
- + return -ENXIO;
- + }
- +
- + /* Now lock the door. */
- + (void) cdrom_lockdoor (drive, 1, &my_reqbuf);
- +
- + /* And try to read the TOC information now. */
- + (void) cdrom_read_toc (drive, &my_reqbuf);
- + }
-
- - /* Should check that there's a disk in the drive? */
- return 0;
- }
-
- @@ -1995,10 +2534,12 @@
- {
- invalidate_buffers (inode->i_rdev);
-
- -#if 0
- /* Unlock the door. */
- - (void) cdrom_lockdoor (drive, 0);
- -#endif
- + (void) cdrom_lockdoor (drive, 0, NULL);
- +
- + /* Do an eject if we were requested to do so. */
- + if (CDROM_STATE_FLAGS (drive)->eject_on_close)
- + (void) cdrom_eject (drive, 0, NULL);
- }
- }
-
- @@ -2015,28 +2556,35 @@
- drive->special.all = 0;
- drive->ready_stat = 0;
-
- - CDROM_FLAGS (drive)->media_changed = 0;
- - CDROM_FLAGS (drive)->toc_valid = 0;
- -
- - CDROM_FLAGS (drive)->no_playaudio12 = 0;
- - CDROM_FLAGS (drive)->no_lba_toc = 0;
- - CDROM_FLAGS (drive)->msf_as_bcd = 0;
- - CDROM_FLAGS (drive)->drq_interrupt = ((drive->id->config & 0x0060) == 0x20);
- + CDROM_STATE_FLAGS (drive)->media_changed = 0;
- + CDROM_STATE_FLAGS (drive)->toc_valid = 0;
- + CDROM_STATE_FLAGS (drive)->door_locked = 0;
- +
- + /* Turn this off by default, since many people don't like it. */
- + CDROM_STATE_FLAGS (drive)->eject_on_close= 0;
- +
- + CDROM_CONFIG_FLAGS (drive)->no_doorlock = 0;
- + CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 0;
- + CDROM_CONFIG_FLAGS (drive)->old_readcd = 0;
- + CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 0;
- + CDROM_CONFIG_FLAGS (drive)->msf_as_bcd = 0;
- + CDROM_CONFIG_FLAGS (drive)->drq_interrupt =
- + ((drive->id->config & 0x0060) == 0x20);
-
- /* Accommodate some broken drives... */
- if (strcmp (drive->id->model, "CD220E") == 0) /* Creative Labs */
- - CDROM_FLAGS (drive)->no_lba_toc = 1;
- + CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
- else if (strcmp (drive->id->model, "TO-ICSLYAL") == 0 || /* Acer CD525E */
- strcmp (drive->id->model, "OTI-SCYLLA") == 0)
- - CDROM_FLAGS (drive)->no_lba_toc = 1;
- + CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
- else if (strcmp (drive->id->model, "CDA26803I SE") == 0) /* Aztech */
- {
- - CDROM_FLAGS (drive)->no_lba_toc = 1;
- + CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
-
- /* This drive _also_ does not implement PLAYAUDIO12 correctly. */
- - CDROM_FLAGS (drive)->no_playaudio12 = 1;
- + CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
- }
-
- drive->cdrom_info.toc = NULL;
- @@ -2046,19 +2594,14 @@
- }
-
-
- -#undef MIN
- -#undef SECTOR_SIZE
- -#undef SECTOR_BITS
- -
-
- /*
- * TODO:
- - * Read actual disk capacity.
- - * Multisession support.
- - * Direct reading of audio data.
- - * Eject-on-dismount.
- - * Lock door while there's a mounted volume.
- + * CDROM_GET_UPC
- + * CDROMRESET
- + * Lock the door when a read request completes successfully and the
- + * door is not already locked. Also try to reorganize to reduce
- + * duplicated functionality between read and ioctl paths?
- * Establish interfaces for an IDE port driver, and break out the cdrom
- * code into a loadable module.
- */
- -
- diff -u --recursive --new-file v1.3.22/linux/drivers/block/ide.c linux/drivers/block/ide.c
- --- v1.3.22/linux/drivers/block/ide.c Sun Sep 3 12:26:51 1995
- +++ linux/drivers/block/ide.c Sun Sep 3 12:03:00 1995
- @@ -1,5 +1,5 @@
- /*
- - * linux/drivers/block/ide.c Version 5.11 Aug 29, 1995
- + * linux/drivers/block/ide.c Version 5.12 Sep 1, 1995
- *
- * Copyright (C) 1994, 1995 Linus Torvalds & authors (see below)
- */
- @@ -130,15 +130,24 @@
- * added automatic PCI CMD640 detection/support
- * added option for VLB CMD640 support
- * tweaked probe to find cdrom on hdb with disks on hda,hdc
- + * Version 5.12 some performance tuning
- + * added message to alert user to bad /dev/hd[cd] entries
- + * OOOPS! fixed bug in atapi reset
- + * driver now forces "serialize" again for all cmd640 chips
- + * noticed REALLY_SLOW_IO had no effect, moved it to ide.c
- + * made do_drive_cmd() into public ide_do_drive_cmd()
- *
- * Driver compile-time options are in ide.h
- *
- * To do, in likely order of completion:
- - * - improved CMD support: probably handing this off to someone else
- + * - add ioctls to get/set interface timings on cmd640, ht6560b, triton
- * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
- + * - improved CMD support: probably handing this off to someone else
- * - find someone to work on IDE *tape drive* support
- */
-
- +#undef REALLY_SLOW_IO /* most systems can safely undef this */
- +
- #include <linux/config.h>
- #include <linux/types.h>
- #include <linux/string.h>
- @@ -156,6 +165,7 @@
- #include <asm/byteorder.h>
- #include <asm/irq.h>
- #include <asm/segment.h>
- +#include <asm/io.h>
-
- #ifdef CONFIG_PCI
- #include <linux/bios32.h>
- @@ -239,7 +249,7 @@
- /* fill in any non-zero initial values */
- hwif->noprobe = (h > 1);
- hwif->io_base = default_io_base[h];
- - hwif->ctl_port = hwif->io_base ? hwif->io_base + 0x206 : 0x000;
- + hwif->ctl_port = hwif->io_base ? hwif->io_base+0x206 : 0x000;
- #ifdef CONFIG_BLK_DEV_HD
- if (hwif->io_base == HD_DATA)
- hwif->noprobe = 1; /* may be overriden by ide_setup() */
- @@ -268,7 +278,6 @@
- }
- }
-
- -#ifdef __i386__
- #define VLB_SYNC 1
- /*
- * Some localbus EIDE interfaces require a special access sequence
- @@ -278,34 +287,32 @@
- * to ensure that the reads all happen together.
- */
- static inline void do_vlb_sync (unsigned short port) {
- - unsigned int _v;
- - __asm__ __volatile__ (
- - "inb %w1,%b0\n\t"
- - "inb %w1,%b0\n\t"
- - "inb %w1,%b0"
- - : "=&a" (_v) /* outputs */
- - : "d" (port) ); /* inputs */
- + (void) inb (port);
- + (void) inb (port);
- + (void) inb (port);
- }
- -#endif /* __i386__ */
-
- /*
- * This is used for most PIO data transfers *from* the IDE interface
- */
- void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
- {
- + unsigned short io_base = HWIF(drive)->io_base;
- + unsigned short data_reg = io_base+IDE_DATA_OFFSET;
- +
- if (drive->vlb_32bit) {
- #ifdef VLB_SYNC
- if (drive->vlb_sync) {
- cli();
- - do_vlb_sync(IDE_NSECTOR_REG);
- - insl(IDE_DATA_REG, buffer, wcount);
- + do_vlb_sync(io_base+IDE_NSECTOR_OFFSET);
- + insl(data_reg, buffer, wcount);
- if (drive->unmask)
- sti();
- } else
- #endif /* VLB_SYNC */
- - insl(IDE_DATA_REG, buffer, wcount);
- + insl(data_reg, buffer, wcount);
- } else
- - insw(IDE_DATA_REG, buffer, wcount<<1);
- + insw(data_reg, buffer, wcount<<1);
- }
-
- /*
- @@ -313,19 +320,22 @@
- */
- void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
- {
- + unsigned short io_base = HWIF(drive)->io_base;
- + unsigned short data_reg = io_base+IDE_DATA_OFFSET;
- +
- if (drive->vlb_32bit) {
- #ifdef VLB_SYNC
- if (drive->vlb_sync) {
- cli();
- - do_vlb_sync(IDE_NSECTOR_REG);
- - outsl(IDE_DATA_REG, buffer, wcount);
- + do_vlb_sync(io_base+IDE_NSECTOR_OFFSET);
- + outsl(data_reg, buffer, wcount);
- if (drive->unmask)
- sti();
- } else
- #endif /* VLB_SYNC */
- - outsl(IDE_DATA_REG, buffer, wcount);
- + outsl(data_reg, buffer, wcount);
- } else
- - outsw(IDE_DATA_REG, buffer, wcount<<1);
- + outsw(data_reg, buffer, wcount<<1);
- }
-
- #if SUPPORT_HT6560B
- @@ -677,8 +687,8 @@
- if (!drive->keep_settings)
- drive->unmask = 0;
- OUT_BYTE (drive->select.all, IDE_SELECT_REG);
- + udelay (20);
- OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
- - udelay (10);
- hwgroup->reset_timeout = jiffies + WAIT_WORSTCASE;
- start_reset_timer (hwif); /* begin periodic polling */
- restore_flags (flags);
- @@ -851,12 +861,10 @@
- err = ide_dump_status(drive, msg, stat);
- if ((rq = HWGROUP(drive)->rq) == NULL || drive == NULL)
- return 0;
- -#ifdef IDE_DRIVE_CMD
- if (rq->cmd == IDE_DRIVE_CMD) { /* never retry an explicit DRIVE_CMD */
- end_drive_cmd(drive, stat, err);
- return 0;
- }
- -#endif /* IDE_DRIVE_CMD */
- if (stat & BUSY_STAT) { /* other bits are useless when BUSY */
- rq->errors |= ERROR_RESET;
- } else {
- @@ -1105,7 +1113,6 @@
- IDE_DO_REQUEST;
- }
-
- -#ifdef IDE_DRIVE_CMD
- /*
- * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
- */
- @@ -1120,7 +1127,6 @@
- return;
- IDE_DO_REQUEST;
- }
- -#endif /* IDE_DRIVE_CMD */
-
- /*
- * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT
- @@ -1175,26 +1181,28 @@
- int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout)
- {
- byte stat;
- + unsigned long flags;
- +test:
- + udelay(1); /* spec allows drive 400ns to change "BUSY" */
- + if (OK_STAT((stat = GET_STAT()), good, bad))
- + return 0; /* fast exit for most frequent case */
- + if (!(stat & BUSY_STAT)) {
- + (void) ide_error(drive, "status error", stat);
- + return 1;
- + }
-
- - udelay(1); /* spec allows drive 400ns to assert "BUSY" */
- - if (GET_STAT() & BUSY_STAT) {
- - unsigned long flags;
- - save_flags(flags);
- - sti();
- - timeout += jiffies;
- - while (GET_STAT() & BUSY_STAT) {
- - if (jiffies > timeout) {
- - restore_flags(flags);
- - (void) ide_error(drive, "status timeout", GET_STAT());
- - return 1;
- - }
- + save_flags(flags);
- + sti();
- + timeout += jiffies;
- + do {
- + if (!((stat = GET_STAT()) & BUSY_STAT)) {
- + restore_flags(flags);
- + goto test;
- }
- - restore_flags(flags);
- - udelay(1); /* spec allows 400ns for status to stabilize */
- - }
- - if (OK_STAT(stat=GET_STAT(), good, bad))
- - return 0;
- - (void) ide_error(drive, "status error", stat);
- + } while (jiffies <= timeout);
- +
- + restore_flags(flags);
- + (void) ide_error(drive, "status timeout", GET_STAT());
- return 1;
- }
-
- @@ -1205,28 +1213,30 @@
- */
- static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
- {
- + unsigned short io_base = HWIF(drive)->io_base;
- +
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
- - OUT_BYTE(rq->nr_sectors,IDE_NSECTOR_REG);
- + OUT_BYTE(rq->nr_sectors,io_base+IDE_NSECTOR_OFFSET);
- if (drive->select.b.lba) {
- #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(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);
- + OUT_BYTE(block,io_base+IDE_SECTOR_OFFSET);
- + OUT_BYTE(block>>=8,io_base+IDE_LCYL_OFFSET);
- + OUT_BYTE(block>>=8,io_base+IDE_HCYL_OFFSET);
- + OUT_BYTE(((block>>8)&0x0f)|drive->select.all,io_base+IDE_SELECT_OFFSET);
- } else {
- unsigned int sect,head,cyl,track;
- track = block / drive->sect;
- sect = block % drive->sect + 1;
- - OUT_BYTE(sect,IDE_SECTOR_REG);
- + OUT_BYTE(sect,io_base+IDE_SECTOR_OFFSET);
- head = track % drive->head;
- cyl = track / drive->head;
- - OUT_BYTE(cyl,IDE_LCYL_REG);
- - OUT_BYTE(cyl>>8,IDE_HCYL_REG);
- - OUT_BYTE(head|drive->select.all,IDE_SELECT_REG);
- + OUT_BYTE(cyl,io_base+IDE_LCYL_OFFSET);
- + OUT_BYTE(cyl>>8,io_base+IDE_HCYL_OFFSET);
- + OUT_BYTE(head|drive->select.all,io_base+IDE_SELECT_OFFSET);
- #ifdef DEBUG
- printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n",
- drive->name, (rq->cmd==READ)?"read":"writ", cyl,
- @@ -1239,7 +1249,7 @@
- return;
- #endif /* CONFIG_BLK_DEV_TRITON */
- ide_set_handler(drive, &read_intr);
- - OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG);
- + OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, io_base+IDE_COMMAND_OFFSET);
- return;
- }
- if (rq->cmd == WRITE) {
- @@ -1247,7 +1257,7 @@
- if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))
- return;
- #endif /* CONFIG_BLK_DEV_TRITON */
- - OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG);
- + OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, io_base+IDE_COMMAND_OFFSET);
- if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
- printk("%s: no DRQ after issuing %s\n", drive->name,
- drive->mult_count ? "MULTWRITE" : "WRITE");
- @@ -1265,13 +1275,12 @@
- }
- return;
- }
- -#ifdef IDE_DRIVE_CMD
- if (rq->cmd == IDE_DRIVE_CMD) {
- byte *args = rq->buffer;
- if (args) {
- printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x\n",
- drive->name, args[0], args[1], args[2]);
- - OUT_BYTE(args[2],IDE_FEATURE_REG);
- + OUT_BYTE(args[2],io_base+IDE_FEATURE_OFFSET);
- ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
- return;
- } else {
- @@ -1286,7 +1295,6 @@
- return;
- }
- }
- -#endif /* IDE_DRIVE_CMD */
- printk("%s: bad command: %d\n", drive->name, rq->cmd);
- ide_end_request(0, HWGROUP(drive));
- }
- @@ -1574,6 +1582,10 @@
- ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present)
- return drive;
- + } else if (major == IDE0_MAJOR && unit < 4) {
- + printk("ide: probable bad entry for /dev/hd%c%d\n",
- + 'a' + unit, MINOR(i_rdev) & PARTN_MASK);
- + printk("ide: to fix it, run: /usr/src/linux/drivers/block/MAKEDEV.ide\n");
- }
- break;
- }
- @@ -1581,14 +1593,13 @@
- return NULL;
- }
-
- -#ifdef IDE_DRIVE_CMD
- /*
- * This function issues a specific IDE drive command onto the
- * tail of the request queue, and waits for it to be completed.
- * If arg is NULL, it goes through all the motions,
- * but without actually sending a command to the drive.
- */
- -static int do_drive_cmd(int rdev, char *args)
- +int ide_do_drive_cmd(int rdev, char *args)
- {
- unsigned long flags;
- unsigned int major = MAJOR(rdev);
- @@ -1626,7 +1637,6 @@
- restore_flags(flags);
- return rq.errors ? -EIO : 0; /* return -EIO if errors */
- }
- -#endif /* IDE_DRIVE_CMD */
-
- static int ide_open(struct inode * inode, struct file * filp)
- {
- @@ -1646,13 +1656,9 @@
- return ide_cdrom_open (inode, filp, drive);
- #endif /* CONFIG_BLK_DEV_IDECD */
- if (drive->removeable) {
- - check_disk_change(inode->i_rdev);
- -#ifdef IDE_DRIVE_CMD
- - {
- byte door_lock[] = {WIN_DOORLOCK,0,0,0};
- - do_drive_cmd(inode->i_rdev, door_lock);
- - }
- -#endif /* IDE_DRIVE_CMD */
- + check_disk_change(inode->i_rdev);
- + ide_do_drive_cmd(inode->i_rdev, door_lock);
- }
- return 0;
- }
- @@ -1674,13 +1680,9 @@
- else
- #endif /* CONFIG_BLK_DEV_IDECD */
- if (drive->removeable) {
- - invalidate_buffers(inode->i_rdev);
- -#ifdef IDE_DRIVE_CMD
- - {
- byte door_unlock[] = {WIN_DOORUNLOCK,0,0,0};
- - do_drive_cmd(inode->i_rdev, door_unlock);
- - }
- -#endif /* IDE_DRIVE_CMD */
- + invalidate_buffers(inode->i_rdev);
- + ide_do_drive_cmd(inode->i_rdev, door_unlock);
- }
- }
- }
- @@ -1876,10 +1878,7 @@
- drive->mult_req = arg;
- drive->special.b.set_multmode = 1;
- restore_flags(flags);
- -#ifndef IDE_DRIVE_CMD
- - return 0;
- -#else
- - do_drive_cmd (inode->i_rdev, NULL);
- + ide_do_drive_cmd (inode->i_rdev, NULL);
- return (drive->mult_count == arg) ? 0 : -EIO;
-
- case HDIO_DRIVE_CMD:
- @@ -1887,20 +1886,19 @@
- unsigned long args;
-
- if (NULL == (long *) arg)
- - err = do_drive_cmd(inode->i_rdev,NULL);
- + err = ide_do_drive_cmd(inode->i_rdev,NULL);
- else {
- if (!(err = verify_area(VERIFY_READ,(long *)arg,sizeof(long))))
- {
- args = get_user((long *)arg);
- if (!(err = verify_area(VERIFY_WRITE,(long *)arg,sizeof(long)))) {
- - err = do_drive_cmd(inode->i_rdev,(char *)&args);
- + err = ide_do_drive_cmd(inode->i_rdev,(char *)&args);
- put_user(args,(long *)arg);
- }
- }
- }
- return err;
- }
- -#endif /* IDE_DRIVE_CMD */
-
- RO_IOCTLS(inode->i_rdev, arg);
-
- @@ -2398,7 +2396,8 @@
- byte reg;
- unsigned short port = 0x178;
-
- - printk("ide: buggy CMD640 interface: ");
- + single_threaded = 1;
- + printk("ide: buggy CMD640 interface: serialized, ");
- reg = read_cmd640_vlb(port, 0x50);
- if (reg == 0xff || (reg & 0x90) != 0x90) {
- #if TRY_CMD640_VLB_AT_0x78
- @@ -2406,9 +2405,8 @@
- if (reg == 0xff || (reg & 0x90) != 0x90)
- #endif
- {
- - single_threaded = 1;
- disallow_unmask = 1;
- - printk("(probe failed) serialized, disabled unmasking\n");
- + printk("(probe failed) disabled unmasking\n");
- return;
- }
- }
- @@ -2578,8 +2576,14 @@
- #if SUPPORT_HT6560B
- case -4: /* "ht6560b" */
- if (hw > 1) goto bad_hwif;
- - ide_hwifs[0].select = 0x1c;
- - ide_hwifs[1].select = 0x1d;
- + /*
- + * Using 0x1c and 0x1d apparently selects a
- + * faster interface speed than 0x3c and 0x3d.
- + *
- + * Need to add an ioctl to select between them.
- + */
- + ide_hwifs[0].select = 0x3c;
- + ide_hwifs[1].select = 0x3d;
- goto do_serialize;
- #endif /* SUPPORT_HT6560B */
- #if SUPPORT_DTC2278
- @@ -2752,7 +2756,7 @@
- restore_flags(flags); /* safe now that hwif->hwgroup is set up */
-
- printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name,
- - hwif->io_base, hwif->io_base + 7, hwif->ctl_port, hwif->irq);
- + hwif->io_base, hwif->io_base+7, hwif->ctl_port, hwif->irq);
- if (hwgroup->hwif != hwif) {
- char *name = hwgroup->hwif->name;
- if (hwgroup->hwif->irq == hwif->irq)
- @@ -2818,12 +2822,13 @@
- int rc;
- unsigned char reg;
-
- + single_threaded = 1;
- printk("ide: buggy CMD640 interface: ");
- if ((rc = pcibios_read_config_byte(bus, fn, 0x51, ®))
- || (rc = pcibios_write_config_byte(bus, fn, 0x51, reg | 0xc8)))
- buggy_interface_fallback (rc);
- else
- - printk("disabled read-ahead, enabled secondary\n");
- + printk("serialized, disabled read-ahead, enabled secondary\n");
- }
- #endif /* SUPPORT_CMD640 */
-
- @@ -2840,8 +2845,6 @@
- byte fn, bus;
- int rc;
-
- - if (!pcibios_present())
- - return;
- save_flags(flags);
- cli();
- for (index = 0; !pcibios_find_device (vendor, device, index, &bus, &fn); ++index) {
- @@ -2892,7 +2895,8 @@
- /*
- * Find/initialize PCI IDE interfaces
- */
- - ide_init_pci ();
- + if (pcibios_present())
- + ide_init_pci ();
- #endif /* CONFIG_PCI */
-
- /*
- diff -u --recursive --new-file v1.3.22/linux/drivers/block/ide.h linux/drivers/block/ide.h
- --- v1.3.22/linux/drivers/block/ide.h Sun Sep 3 12:26:51 1995
- +++ linux/drivers/block/ide.h Sun Sep 3 14:06:00 1995
- @@ -17,11 +17,10 @@
-
- /******************************************************************************
- * IDE driver configuration options (play with these as desired):
- + *
- + * REALLY_SLOW_IO can be defined in ide.c and ide-cd.c, if necessary
- */
- -#undef REALLY_SLOW_IO /* most systems can safely undef this */
- -#include <asm/io.h>
- -
- -#undef REALLY_FAST_IO /* define if ide ports are perfect */
- +#define REALLY_FAST_IO /* define if ide ports are perfect */
- #define INITIAL_MULT_COUNT 0 /* off=0; on=2,4,8,16,32, etc.. */
-
- #ifndef DISK_RECOVERY_TIME /* off=0; on=access_delay_time */
- @@ -81,14 +80,25 @@
- #define HWIF(drive) ((ide_hwif_t *)drive->hwif)
- #define HWGROUP(drive) ((ide_hwgroup_t *)(HWIF(drive)->hwgroup))
-
- -#define IDE_DATA_REG (HWIF(drive)->io_base)
- -#define IDE_ERROR_REG (HWIF(drive)->io_base+1)
- -#define IDE_NSECTOR_REG (HWIF(drive)->io_base+2)
- -#define IDE_SECTOR_REG (HWIF(drive)->io_base+3)
- -#define IDE_LCYL_REG (HWIF(drive)->io_base+4)
- -#define IDE_HCYL_REG (HWIF(drive)->io_base+5)
- -#define IDE_SELECT_REG (HWIF(drive)->io_base+6)
- -#define IDE_STATUS_REG (HWIF(drive)->io_base+7)
- +#define IDE_DATA_OFFSET (0)
- +#define IDE_ERROR_OFFSET (1)
- +#define IDE_NSECTOR_OFFSET (2)
- +#define IDE_SECTOR_OFFSET (3)
- +#define IDE_LCYL_OFFSET (4)
- +#define IDE_HCYL_OFFSET (5)
- +#define IDE_SELECT_OFFSET (6)
- +#define IDE_STATUS_OFFSET (7)
- +#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET
- +#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET
- +
- +#define IDE_DATA_REG (HWIF(drive)->io_base+IDE_DATA_OFFSET)
- +#define IDE_ERROR_REG (HWIF(drive)->io_base+IDE_ERROR_OFFSET)
- +#define IDE_NSECTOR_REG (HWIF(drive)->io_base+IDE_NSECTOR_OFFSET)
- +#define IDE_SECTOR_REG (HWIF(drive)->io_base+IDE_SECTOR_OFFSET)
- +#define IDE_LCYL_REG (HWIF(drive)->io_base+IDE_LCYL_OFFSET)
- +#define IDE_HCYL_REG (HWIF(drive)->io_base+IDE_HCYL_OFFSET)
- +#define IDE_SELECT_REG (HWIF(drive)->io_base+IDE_SELECT_OFFSET)
- +#define IDE_STATUS_REG (HWIF(drive)->io_base+IDE_STATUS_OFFSET)
- #define IDE_CONTROL_REG (HWIF(drive)->ctl_port)
- #define IDE_FEATURE_REG IDE_ERROR_REG
- #define IDE_COMMAND_REG IDE_STATUS_REG
- @@ -413,6 +423,17 @@
- * All allocations are longword aligned.
- */
- void *ide_alloc (unsigned long bytecount, unsigned long within_area);
- +
- +/*
- + * This function issues a specific IDE drive command onto the
- + * tail of the request queue, and waits for it to be completed.
- + * If arg is NULL, it goes through all the motions,
- + * but without actually sending a command to the drive.
- + *
- + * The value of arg is passed to the internal handler as rq->buffer.
- + */
- +int ide_do_drive_cmd(int rdev, char *args);
- +
-
- #ifdef CONFIG_BLK_DEV_IDECD
- /*
- diff -u --recursive --new-file v1.3.22/linux/drivers/block/triton.c linux/drivers/block/triton.c
- --- v1.3.22/linux/drivers/block/triton.c Sun Sep 3 12:26:52 1995
- +++ linux/drivers/block/triton.c Sun Sep 3 12:03:00 1995
- @@ -194,6 +194,29 @@
- return 1; /* let the PIO routines handle this weirdness */
- }
-
- +static int config_drive_for_dma (ide_drive_t *drive)
- +{
- + const char **list;
- +
- + struct hd_driveid *id = drive->id;
- + if (id && (id->capability & 1)) {
- + /* Enable DMA on any drive that supports mword2 DMA */
- + if ((id->field_valid & 2) && (id->dma_mword & 0x404) == 0x404) {
- + drive->using_dma = 1;
- + return 0; /* DMA enabled */
- + }
- + /* Consult the list of known "good" drives */
- + list = good_dma_drives;
- + while (*list) {
- + if (!strcmp(*list++,id->model)) {
- + drive->using_dma = 1;
- + return 0; /* DMA enabled */
- + }
- + }
- + }
- + return 1; /* DMA not enabled */
- +}
- +
- /*
- * triton_dmaproc() initiates/aborts DMA read/write operations on a drive.
- *
- @@ -207,40 +230,31 @@
- */
- static int triton_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
- {
- - const char **list;
- unsigned long dma_base = HWIF(drive)->dma_base;
- + unsigned int reading = (1 << 3);
-
- - if (func == ide_dma_abort) {
- - outb(inb(dma_base)&~1, dma_base); /* stop DMA */
- - return 0;
- - }
- - if (func == ide_dma_check) {
- - struct hd_driveid *id = drive->id;
- - if (id && (id->capability & 1)) {
- - /* Enable DMA on any drive that supports mword2 DMA */
- - if ((id->field_valid & 2) && (id->dma_mword & 0x404) == 0x404) {
- - drive->using_dma = 1;
- - return 0; /* DMA enabled */
- - }
- - /* Consult the list of known "good" drives */
- - list = good_dma_drives;
- - while (*list) {
- - if (!strcmp(*list++,id->model)) {
- - drive->using_dma = 1;
- - return 0; /* DMA enabled */
- - }
- - }
- - }
- - return 1; /* DMA not enabled */
- + switch (func) {
- + case ide_dma_abort:
- + outb(inb(dma_base)&~1, dma_base); /* stop DMA */
- + return 0;
- + case ide_dma_check:
- + return config_drive_for_dma (drive);
- + case ide_dma_write:
- + reading = 0;
- + case ide_dma_read:
- + break;
- + default:
- + printk("triton_dmaproc: unsupported func: %d\n", func);
- + return 1;
- }
- if (build_dmatable (drive))
- return 1;
- outl(virt_to_bus (HWIF(drive)->dmatable), dma_base + 4); /* PRD table */
- - outb((!func) << 3, dma_base); /* specify r/w */
- + outb(reading, dma_base); /* specify r/w */
- outb(0x26, dma_base+2); /* clear status bits */
- ide_set_handler (drive, &dma_intr); /* issue cmd to drive */
- - OUT_BYTE(func ? WIN_WRITEDMA : WIN_READDMA, IDE_COMMAND_REG);
- - outb(inb(dma_base)|1, dma_base); /* begin DMA */
- + OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
- + outb(inb(dma_base)|1, dma_base); /* begin DMA */
- return 0;
- }
-
- @@ -326,8 +340,8 @@
- base = bmiba + 8;
- } else
- continue;
- - printk(" %s: BusMaster DMA at 0x%04x-0x%04x", hwif->name, base, base+5);
- - if (check_region(base, 6)) {
- + printk(" %s: BusMaster DMA at 0x%04x-0x%04x", hwif->name, base, base+7);
- + if (check_region(base, 8)) {
- printk(" -- ERROR, PORTS ALREADY IN USE");
- } else {
- unsigned long *table;
- diff -u --recursive --new-file v1.3.22/linux/drivers/net/Makefile linux/drivers/net/Makefile
- --- v1.3.22/linux/drivers/net/Makefile Mon Aug 28 14:52:20 1995
- +++ linux/drivers/net/Makefile Sun Sep 3 12:08:21 1995
- @@ -245,8 +245,6 @@
-
- ifdef CONFIG_ARCNET
- L_OBJS += arcnet.o
- -else
- -M_OBJS += arcnet.o
- endif
-
- ifdef CONFIG_PI
- diff -u --recursive --new-file v1.3.22/linux/drivers/net/lance.c linux/drivers/net/lance.c
- --- v1.3.22/linux/drivers/net/lance.c Tue Aug 15 20:39:03 1995
- +++ linux/drivers/net/lance.c Sun Sep 3 11:13:05 1995
- @@ -319,10 +319,14 @@
- for (port = lance_portlist; *port; port++) {
- int ioaddr = *port;
-
- - if ( check_region(ioaddr, LANCE_TOTAL_SIZE) == 0
- - && inb(ioaddr + 14) == 0x57
- - && inb(ioaddr + 15) == 0x57) {
- - mem_start = lance_probe1(ioaddr, mem_start);
- + if ( check_region(ioaddr, LANCE_TOTAL_SIZE) == 0) {
- + /* Detect "normal" 0x57 0x57 and the NI6510EB 0x52 0x44
- + signatures w/ minimal I/O reads */
- + char offset15, offset14 = inb(ioaddr + 14);
- +
- + if ((offset14 == 0x52 || offset14 == 0x57) &&
- + ((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44))
- + mem_start = lance_probe1(ioaddr, mem_start);
- }
- }
-
- diff -u --recursive --new-file v1.3.22/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
- --- v1.3.22/linux/include/asm-i386/io.h Sun Sep 3 12:27:02 1995
- +++ linux/include/asm-i386/io.h Sun Sep 3 12:06:48 1995
- @@ -121,10 +121,11 @@
- #undef RETURN_TYPE
- #define RETURN_TYPE unsigned short
- /* __IN(w,"w","0" (0)) */
- -__IN(w,)
- +__IN(w,"")
- #undef RETURN_TYPE
- #define RETURN_TYPE unsigned int
- __IN(l,"")
- +#undef RETURN_TYPE
-
- __OUT(b,"b",char)
- __OUT(w,"w",short)
- diff -u --recursive --new-file v1.3.22/linux/include/linux/hdreg.h linux/include/linux/hdreg.h
- --- v1.3.22/linux/include/linux/hdreg.h Mon Aug 28 14:52:22 1995
- +++ linux/include/linux/hdreg.h Sun Sep 3 14:04:52 1995
- @@ -1,8 +1,6 @@
- #ifndef _LINUX_HDREG_H
- #define _LINUX_HDREG_H
-
- -#include <linux/config.h>
- -
- /*
- * This file contains some defines for the AT-hd-controller.
- * Various sources.
- @@ -154,14 +152,19 @@
- /* unsigned short reservedyy[96];*/ /* reserved (words 160-255) */
- };
-
- +#ifdef __KERNEL__
- /*
- * These routines are used for kernel command line parameters from main.c:
- */
- +#include <linux/config.h>
- +
- #ifdef CONFIG_BLK_DEV_HD
- void hd_setup(char *, int *);
- #endif /* CONFIG_BLK_DEV_HD */
- #ifdef CONFIG_BLK_DEV_IDE
- void ide_setup(char *);
- #endif /* CONFIG_BLK_DEV_IDE */
- +
- +#endif /* __KERNEL__ */
-
- #endif /* _LINUX_HDREG_H */
- diff -u --recursive --new-file v1.3.22/linux/include/linux/igmp.h linux/include/linux/igmp.h
- --- v1.3.22/linux/include/linux/igmp.h Tue Jun 6 11:22:11 1995
- +++ linux/include/linux/igmp.h Sun Sep 3 11:19:53 1995
- @@ -25,7 +25,7 @@
- struct igmphdr
- {
- unsigned char type;
- - unsigned char unused;
- + unsigned char code;
- unsigned short csum;
- unsigned long group;
- };
- @@ -37,7 +37,7 @@
- struct igmp_header
- {
- unsigned char type;
- - unsigned char unused;
- + unsigned char code;
- unsigned short csum;
- unsigned long group;
- };
- diff -u --recursive --new-file v1.3.22/linux/include/linux/mcd.h linux/include/linux/mcd.h
- --- v1.3.22/linux/include/linux/mcd.h Sun Sep 3 12:27:02 1995
- +++ linux/include/linux/mcd.h Sun Sep 3 12:09:44 1995
- @@ -110,6 +110,8 @@
- struct msf diskTime;
- };
-
- +#if 0
- #ifndef I_WAS_HERE
- #error Please edit this file first.
- +#endif
- #endif
- diff -u --recursive --new-file v1.3.22/linux/include/linux/mcdx.h linux/include/linux/mcdx.h
- --- v1.3.22/linux/include/linux/mcdx.h Sun Sep 3 12:27:02 1995
- +++ linux/include/linux/mcdx.h Sun Sep 3 12:09:44 1995
- @@ -173,6 +173,8 @@
- #define MCDX_E 1 /* unspec error */
- #define MCDX_EOM 2 /* end of media */
-
- +#if 0
- #ifndef I_WAS_HERE
- #error Please edit this file first.
- +#endif
- #endif
- diff -u --recursive --new-file v1.3.22/linux/net/core/dev.c linux/net/core/dev.c
- --- v1.3.22/linux/net/core/dev.c Sun Sep 3 12:27:05 1995
- +++ linux/net/core/dev.c Sun Sep 3 12:00:24 1995
- @@ -1305,7 +1305,7 @@
-
- void dev_init(void)
- {
- - struct device *dev, *dev2;
- + struct device *dev, **dp;
-
- /*
- * Add the devices.
- @@ -1313,24 +1313,25 @@
- * from the chain disconnecting the device until the
- * next reboot.
- */
- -
- - dev2 = NULL;
- - for (dev = dev_base; dev != NULL; dev=dev->next)
- +
- + dp = &dev_base;
- + while ((dev = *dp) != NULL)
- {
- + int i;
- + for (i = 0; i < DEV_NUMBUFFS; i++) {
- + skb_queue_head_init(dev->buffs + i);
- + }
- +
- if (dev->init && dev->init(dev))
- {
- /*
- * It failed to come up. Unhook it.
- */
- -
- - if (dev2 == NULL)
- - dev_base = dev->next;
- - else
- - dev2->next = dev->next;
- + *dp = dev->next;
- }
- else
- {
- - dev2 = dev;
- + dp = &dev->next;
- }
- }
- proc_net_register(&(struct proc_dir_entry) {
- @@ -1339,6 +1340,5 @@
- 0, &proc_net_inode_operations,
- dev_get_info
- });
- -
- }
-
- diff -u --recursive --new-file v1.3.22/linux/net/ipv4/ip.c linux/net/ipv4/ip.c
- --- v1.3.22/linux/net/ipv4/ip.c Sun Sep 3 12:27:05 1995
- +++ linux/net/ipv4/ip.c Sat Sep 2 11:45:37 1995
- @@ -1819,7 +1819,7 @@
- iph->tot_len = ntohs(skb->len-(((unsigned char *)iph)-skb->data));
-
- #ifdef CONFIG_IP_FIREWALL
- - if(ip_fw_chk(iph, dev, ip_fw_blk_chain, ip_fw_blk_policy, 0) != 1)
- + if(ip_fw_chk(iph, dev, ip_fw_blk_chain, ip_fw_blk_policy, 0) < 1)
- /* just don't send this packet */
- return;
- #endif
-