Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
2b2c89a1
Commit
2b2c89a1
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 1.3.23
parent
8f0ec1f9
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
1172 additions
and
514 deletions
+1172
-514
Makefile
Makefile
+1
-1
arch/i386/mm/fault.c
arch/i386/mm/fault.c
+10
-0
drivers/block/README.ide
drivers/block/README.ide
+28
-0
drivers/block/genhd.c
drivers/block/genhd.c
+53
-25
drivers/block/ide-cd.c
drivers/block/ide-cd.c
+879
-336
drivers/block/ide.c
drivers/block/ide.c
+93
-89
drivers/block/ide.h
drivers/block/ide.h
+33
-12
drivers/block/triton.c
drivers/block/triton.c
+42
-28
drivers/net/Makefile
drivers/net/Makefile
+0
-2
drivers/net/lance.c
drivers/net/lance.c
+8
-4
include/asm-i386/io.h
include/asm-i386/io.h
+2
-1
include/linux/hdreg.h
include/linux/hdreg.h
+5
-2
include/linux/igmp.h
include/linux/igmp.h
+2
-2
include/linux/mcd.h
include/linux/mcd.h
+2
-0
include/linux/mcdx.h
include/linux/mcdx.h
+2
-0
net/core/dev.c
net/core/dev.c
+11
-11
net/ipv4/ip.c
net/ipv4/ip.c
+1
-1
No files found.
Makefile
View file @
2b2c89a1
VERSION
=
1
PATCHLEVEL
=
3
SUBLEVEL
=
2
2
SUBLEVEL
=
2
3
ARCH
=
i386
...
...
arch/i386/mm/fault.c
View file @
2b2c89a1
...
...
@@ -49,6 +49,16 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
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
);
/*
...
...
drivers/block/README.ide
View file @
2b2c89a1
...
...
@@ -46,6 +46,9 @@ NEW! - should work for for EZ-Drive disks as well (not verified)
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.
...
...
@@ -161,6 +164,31 @@ interface (/dev/hda) and an IDE cdrom drive on the secondary interface
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).
...
...
drivers/block/genhd.c
View file @
2b2c89a1
...
...
@@ -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 @@ static void extended_partition(struct gendisk *hd, int dev)
{
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 @@ static void extended_partition(struct gendisk *hd, int dev)
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 @@ static int msdos_partition(struct gendisk *hd, unsigned int dev, unsigned long f
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
;
}
}
/*
...
...
drivers/block/ide-cd.c
View file @
2b2c89a1
...
...
@@ -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 th
e fields which
doesn't make sense for cd-roms -- `bios_sect'. */
To save space in the ide_drive_t struct, use
som
e 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 @@ struct {
/****************************************************************************
* Generic packet command support routines.
* Generic packet command support
and error handling
routines.
*/
...
...
@@ -312,7 +369,7 @@ void cdrom_analyze_sense_data (ide_drive_t *drive,
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 @@ void cdrom_analyze_sense_data (ide_drive_t *drive,
}
#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 restore_request (struct request *rq)
}
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 @@ static void cdrom_queue_request_sense (ide_drive_t *drive)
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 @@ static void cdrom_queue_request_sense (ide_drive_t *drive)
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 @@ static void cdrom_end_request (int uptodate, ide_drive_t *drive)
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 @@ static void cdrom_end_request (int uptodate, ide_drive_t *drive)
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 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat, int *stat_ret
{
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 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat, int *stat_ret
/* 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 @@ static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen)
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 D
EV
described by CMD_BUF and CMD_LEN.
/* Send a packet command to D
RIVE
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 @@ static int cdrom_transfer_packet_command (ide_drive_t *drive,
}
/* 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 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
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 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
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 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
and quit this request. */
while
(
len
>
0
)
{
shor
t
dum
=
0
;
OUT_WORDS
(
&
dum
,
1
);
len
-=
2
;
in
t
dum
=
0
;
cdrom_out_bytes
(
drive
,
&
dum
,
sizeof
(
dum
)
);
len
-=
sizeof
(
dum
)
;
}
}
...
...
@@ -833,7 +957,7 @@ static void cdrom_read_intr (ide_drive_t *drive)
{
/* 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 @@ static void cdrom_read_intr (ide_drive_t *drive)
/* 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 @@ static void cdrom_read_intr (ide_drive_t *drive)
/* 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 @@ static int cdrom_read_from_buffer (ide_drive_t *drive)
* 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 @@ static int cdrom_start_read_continuation (ide_drive_t *drive)
drive
->
name
,
rq
->
current_nr_sectors
);
cdrom_end_request
(
0
,
drive
);
IDE_DO_REQUEST
;
return
1
;
return
;
}
sector
-=
nskip
;
...
...
@@ -1016,23 +1140,18 @@ static int cdrom_start_read_continuation (ide_drive_t *drive)
pc
.
c
[
5
]
=
conv
.
b
.
b0
;
}
if
(
cdrom_transfer_packet_command
(
drive
,
pc
.
c
,
sizeof
(
pc
.
c
)))
return
1
;
/* Set up our interrupt handler and return. */
ide_set_handler
(
drive
,
&
cdrom_read_intr
);
/* BUG: do this BEFORE triggering drive */
/* Set up to receive the data-ready interrupt from the drive. */
ide_set_handler
(
drive
,
&
cdrom_read_intr
);
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 @@ static int cdrom_start_read (ide_drive_t *drive, unsigned int block)
/* 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 @@ static int cdrom_start_read (ide_drive_t *drive, unsigned int block)
* Execute all other packet commands.
*/
/* Forward declaration */
/* Forward declaration
s.
*/
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 @@ static void cdrom_pc_intr (ide_drive_t *drive)
}
/* 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
)
{
shor
t
dum
=
0
;
OUT_WORDS
(
&
dum
,
1
);
len
-=
2
;
in
t
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 @@ static void cdrom_pc_intr (ide_drive_t *drive)
}
/* 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
)
{
shor
t
dum
=
0
;
IN_WORDS
(
&
dum
,
1
);
len
-=
2
;
in
t
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 @@ static void cdrom_pc_intr (ide_drive_t *drive)
}
/* 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 our interrupt handler and return. */
ide_set_handler
(
drive
,
&
cdrom_pc_intr
);
/* BUG: do this BEFORE triggering drive */
/* Set up a handler for the data-ready interrupt. */
ide_set_handler
(
drive
,
&
cdrom_pc_intr
);
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 @@ static int cdrom_do_packet_command (ide_drive_t *drive)
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 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
{
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
;
cdrom_queue_request
(
drive
,
&
req
);
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
;
down
(
&
sem
);
--
retries
;
}
/* End of retry loop. */
}
while
(
pc
->
stat
!=
0
&&
retries
>=
0
);
/* Return an error if the command failed. */
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
->
c
[
0
]
==
REQUEST_SENSE
||
cdrom_request_sense
(
drive
,
reqbuf
))
{
memset
(
reqbuf
,
0
,
sizeof
(
*
reqbuf
));
reqbuf
->
asc
=
0xff
;
}
cdrom_analyze_sense_data
(
drive
,
reqbuf
,
pc
);
return
-
EIO
;
/* If the error was a unit attention (usually means media was changed),
retry the command. */
if
(
reqbuf
->
sense_key
==
UNIT_ATTENTION
&&
retries
>
0
)
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 @@ void ide_do_rw_cdrom (ide_drive_t *drive, unsigned long block)
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 @@ void ide_do_rw_cdrom (ide_drive_t *drive, unsigned long block)
/****************************************************************************
* 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 @@ int msf_to_lba (byte m, byte s, byte f)
}
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 @@ cdrom_eject (ide_drive_t *drive, int ejectflag)
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 @@ cdrom_pause (ide_drive_t *drive, int pauseflag)
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
;
...
...
@@ -1461,13 +1641,45 @@ cdrom_startstop (ide_drive_t *drive, int startflag)
}
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 @@ cdrom_read_tocentry (ide_drive_t *drive, int trackno, int msf_flag,
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 @@ cdrom_read_tocentry (ide_drive_t *drive, int trackno, int msf_flag,
/* 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 @@ cdrom_read_toc (ide_drive_t *drive)
/* 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 @@ cdrom_read_toc (ide_drive_t *drive)
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 @@ cdrom_read_toc (ide_drive_t *drive)
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 @@ cdrom_read_toc (ide_drive_t *drive)
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 @@ cdrom_read_subchannel (ide_drive_t *drive,
/* 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 @@ cdrom_mode_sense (ide_drive_t *drive, int pageno, int modeflag,
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 @@ cdrom_mode_select (ide_drive_t *drive, int pageno, char *buf, int buflen)
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 @@ cdrom_play_lba_range_play12 (ide_drive_t *drive, int lba_start, int lba_end)
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 @@ cdrom_play_lba_range_msf (ide_drive_t *drive, int lba_start, int lba_end)
/* 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 @@ cdrom_play_lba_range (ide_drive_t *drive, int lba_start, int lba_end)
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
;
if
(
reqbuf
==
NULL
)
reqbuf
=
&
my_reqbuf
;
stat
=
cdrom_play_lba_range_play12
(
drive
,
lba_start
,
lba_end
);
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 @@ cdrom_play_lba_range (ide_drive_t *drive, int lba_start, int lba_end)
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 @@ int cdrom_get_toc_entry (ide_drive_t *drive, int track,
}
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 @@ int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
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 @@ int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
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 @@ int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
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 @@ int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
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 @@ int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
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 @@ int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
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 @@ int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
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 @@ int ide_cdrom_ioctl (ide_drive_t *drive, struct inode *inode,
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 ide_cdrom_check_media_change (ide_drive_t *drive)
{
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_check_media_change (ide_drive_t *drive)
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 @@ void ide_cdrom_release (struct inode *inode, struct file *file, ide_drive_t *dri
{
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 @@ void ide_cdrom_setup (ide_drive_t *drive)
drive
->
special
.
all
=
0
;
drive
->
ready_stat
=
0
;
CDROM_FLAGS
(
drive
)
->
media_changed
=
0
;
CDROM_FLAGS
(
drive
)
->
toc_valid
=
0
;
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_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_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 @@ void ide_cdrom_setup (ide_drive_t *drive)
}
#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.
*/
drivers/block/ide.c
View file @
2b2c89a1
/*
* linux/drivers/block/ide.c Version 5.1
1 Aug 29
, 1995
* linux/drivers/block/ide.c Version 5.1
2 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 @@ static void init_ide_data (void)
/* 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 @@ static void init_ide_data (void)
}
}
#ifdef __i386__
#define VLB_SYNC 1
/*
* Some localbus EIDE interfaces require a special access sequence
...
...
@@ -278,34 +287,32 @@ static void init_ide_data (void)
* 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_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
*/
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 @@ int ide_do_reset (ide_drive_t *drive)
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 @@ int ide_error (ide_drive_t *drive, const char *msg, byte stat)
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 @@ static void recal_intr (ide_drive_t *drive)
IDE_DO_REQUEST
;
}
#ifdef IDE_DRIVE_CMD
/*
* drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
*/
...
...
@@ -1120,7 +1127,6 @@ static void drive_cmd_intr (ide_drive_t *drive)
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 @@ static inline void do_special (ide_drive_t *drive)
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 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou
*/
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 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned
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 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned
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 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned
}
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 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned
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 @@ static ide_drive_t *get_info_ptr (int i_rdev)
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 @@ static ide_drive_t *get_info_ptr (int i_rdev)
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 @@ static int do_drive_cmd(int rdev, char *args)
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 @@ static int ide_open(struct inode * inode, struct file * filp)
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 @@ static void ide_release(struct inode * inode, struct file * file)
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 @@ static int ide_ioctl (struct inode *inode, struct file *file,
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 @@ static int ide_ioctl (struct inode *inode, struct file *file,
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 @@ void init_cmd640_vlb (void)
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 @@ void init_cmd640_vlb (void)
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 @@ void ide_setup (char *s)
#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 @@ static int init_irq (ide_hwif_t *hwif)
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 @@ void init_cmd640 (byte bus, byte fn)
int
rc
;
unsigned
char
reg
;
single_threaded
=
1
;
printk
(
"ide: buggy CMD640 interface: "
);
if
((
rc
=
pcibios_read_config_byte
(
bus
,
fn
,
0x51
,
&
reg
))
||
(
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 @@ static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci
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 @@ unsigned long ide_init (unsigned long mem_start, unsigned long mem_end)
/*
* Find/initialize PCI IDE interfaces
*/
ide_init_pci
();
if
(
pcibios_present
())
ide_init_pci
();
#endif
/* CONFIG_PCI */
/*
...
...
drivers/block/ide.h
View file @
2b2c89a1
...
...
@@ -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 @@ typedef unsigned char byte; /* used everywhere */
#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
...
...
@@ -414,6 +424,17 @@ int ide_do_reset (ide_drive_t *);
*/
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
/*
* These are routines in ide-cd.c invoked from ide.c
...
...
drivers/block/triton.c
View file @
2b2c89a1
...
...
@@ -194,6 +194,29 @@ static int build_dmatable (ide_drive_t *drive)
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 build_dmatable (ide_drive_t *drive)
*/
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_READ
DMA
,
IDE_COMMAND_REG
);
outb
(
inb
(
dma_base
)
|
1
,
dma_base
);
/* begin DMA */
OUT_BYTE
(
reading
?
WIN_READDMA
:
WIN_WRITE
DMA
,
IDE_COMMAND_REG
);
outb
(
inb
(
dma_base
)
|
1
,
dma_base
);
/* begin DMA */
return
0
;
}
...
...
@@ -326,8 +340,8 @@ void ide_init_triton (byte bus, byte fn)
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
;
...
...
drivers/net/Makefile
View file @
2b2c89a1
...
...
@@ -245,8 +245,6 @@ endif
ifdef
CONFIG_ARCNET
L_OBJS
+=
arcnet.o
else
M_OBJS
+=
arcnet.o
endif
ifdef
CONFIG_PI
...
...
drivers/net/lance.c
View file @
2b2c89a1
...
...
@@ -319,10 +319,14 @@ unsigned long lance_init(unsigned long mem_start, unsigned long mem_end)
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
);
}
}
...
...
include/asm-i386/io.h
View file @
2b2c89a1
...
...
@@ -121,10 +121,11 @@ __IN(b,"")
#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
)
...
...
include/linux/hdreg.h
View file @
2b2c89a1
#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,9 +152,12 @@ struct hd_driveid {
/* 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 */
...
...
@@ -164,4 +165,6 @@ void hd_setup(char *, int *);
void
ide_setup
(
char
*
);
#endif
/* CONFIG_BLK_DEV_IDE */
#endif
/* __KERNEL__ */
#endif
/* _LINUX_HDREG_H */
include/linux/igmp.h
View file @
2b2c89a1
...
...
@@ -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 igmphdr
struct
igmp_header
{
unsigned
char
type
;
unsigned
char
unused
;
unsigned
char
code
;
unsigned
short
csum
;
unsigned
long
group
;
};
...
...
include/linux/mcd.h
View file @
2b2c89a1
...
...
@@ -110,6 +110,8 @@ struct mcd_Toc {
struct
msf
diskTime
;
};
#if 0
#ifndef I_WAS_HERE
#error Please edit this file first.
#endif
#endif
include/linux/mcdx.h
View file @
2b2c89a1
...
...
@@ -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
net/core/dev.c
View file @
2b2c89a1
...
...
@@ -1305,7 +1305,7 @@ int dev_ioctl(unsigned int cmd, void *arg)
void
dev_init
(
void
)
{
struct
device
*
dev
,
*
dev2
;
struct
device
*
dev
,
*
*
dp
;
/*
* Add the devices.
...
...
@@ -1313,24 +1313,25 @@ void dev_init(void)
* from the chain disconnecting the device until the
* next reboot.
*/
d
ev2
=
NULL
;
for
(
dev
=
dev_base
;
dev
!=
NULL
;
dev
=
dev
->
next
)
d
p
=
&
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
{
d
ev2
=
dev
;
d
p
=
&
dev
->
next
;
}
}
proc_net_register
(
&
(
struct
proc_dir_entry
)
{
...
...
@@ -1339,6 +1340,5 @@ void dev_init(void)
0
,
&
proc_net_inode_operations
,
dev_get_info
});
}
net/ipv4/ip.c
View file @
2b2c89a1
...
...
@@ -1819,7 +1819,7 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment