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
nexedi
linux
Commits
1fdffbce
Commit
1fdffbce
authored
Feb 09, 2006
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[libata] Move PCI IDE BMDMA-related code to new file libata-bmdma.c.
parent
389984cb
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
724 additions
and
674 deletions
+724
-674
drivers/scsi/Makefile
drivers/scsi/Makefile
+1
-1
drivers/scsi/libata-bmdma.c
drivers/scsi/libata-bmdma.c
+703
-0
drivers/scsi/libata-core.c
drivers/scsi/libata-core.c
+20
-673
No files found.
drivers/scsi/Makefile
View file @
1fdffbce
...
@@ -163,7 +163,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
...
@@ -163,7 +163,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
CFLAGS_ncr53c8xx.o
:=
$
(
ncr53c8xx-flags-y
)
$
(
ncr53c8xx-flags-m
)
CFLAGS_ncr53c8xx.o
:=
$
(
ncr53c8xx-flags-y
)
$
(
ncr53c8xx-flags-m
)
zalon7xx-objs
:=
zalon.o ncr53c8xx.o
zalon7xx-objs
:=
zalon.o ncr53c8xx.o
NCR_Q720_mod-objs
:=
NCR_Q720.o ncr53c8xx.o
NCR_Q720_mod-objs
:=
NCR_Q720.o ncr53c8xx.o
libata-objs
:=
libata-core.o libata-scsi.o
libata-objs
:=
libata-core.o libata-scsi.o
libata-bmdma.o
oktagon_esp_mod-objs
:=
oktagon_esp.o oktagon_io.o
oktagon_esp_mod-objs
:=
oktagon_esp.o oktagon_io.o
# Files generated that shall be removed upon make clean
# Files generated that shall be removed upon make clean
...
...
drivers/scsi/libata-bmdma.c
0 → 100644
View file @
1fdffbce
/*
* libata-bmdma.c - helper library for PCI IDE BMDMA
*
* Maintained by: Jeff Garzik <jgarzik@pobox.com>
* Please ALWAYS copy linux-ide@vger.kernel.org
* on emails.
*
* Copyright 2003-2006 Red Hat, Inc. All rights reserved.
* Copyright 2003-2006 Jeff Garzik
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* libata documentation is available via 'make {ps|pdf}docs',
* as Documentation/DocBook/libata.*
*
* Hardware documentation available from http://www.t13.org/ and
* http://www.sata-io.org/
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/libata.h>
#include "libata.h"
/**
* ata_tf_load_pio - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
* Outputs ATA taskfile to standard ATA host controller.
*
* LOCKING:
* Inherited from caller.
*/
static
void
ata_tf_load_pio
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
struct
ata_ioports
*
ioaddr
=
&
ap
->
ioaddr
;
unsigned
int
is_addr
=
tf
->
flags
&
ATA_TFLAG_ISADDR
;
if
(
tf
->
ctl
!=
ap
->
last_ctl
)
{
outb
(
tf
->
ctl
,
ioaddr
->
ctl_addr
);
ap
->
last_ctl
=
tf
->
ctl
;
ata_wait_idle
(
ap
);
}
if
(
is_addr
&&
(
tf
->
flags
&
ATA_TFLAG_LBA48
))
{
outb
(
tf
->
hob_feature
,
ioaddr
->
feature_addr
);
outb
(
tf
->
hob_nsect
,
ioaddr
->
nsect_addr
);
outb
(
tf
->
hob_lbal
,
ioaddr
->
lbal_addr
);
outb
(
tf
->
hob_lbam
,
ioaddr
->
lbam_addr
);
outb
(
tf
->
hob_lbah
,
ioaddr
->
lbah_addr
);
VPRINTK
(
"hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X
\n
"
,
tf
->
hob_feature
,
tf
->
hob_nsect
,
tf
->
hob_lbal
,
tf
->
hob_lbam
,
tf
->
hob_lbah
);
}
if
(
is_addr
)
{
outb
(
tf
->
feature
,
ioaddr
->
feature_addr
);
outb
(
tf
->
nsect
,
ioaddr
->
nsect_addr
);
outb
(
tf
->
lbal
,
ioaddr
->
lbal_addr
);
outb
(
tf
->
lbam
,
ioaddr
->
lbam_addr
);
outb
(
tf
->
lbah
,
ioaddr
->
lbah_addr
);
VPRINTK
(
"feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X
\n
"
,
tf
->
feature
,
tf
->
nsect
,
tf
->
lbal
,
tf
->
lbam
,
tf
->
lbah
);
}
if
(
tf
->
flags
&
ATA_TFLAG_DEVICE
)
{
outb
(
tf
->
device
,
ioaddr
->
device_addr
);
VPRINTK
(
"device 0x%X
\n
"
,
tf
->
device
);
}
ata_wait_idle
(
ap
);
}
/**
* ata_tf_load_mmio - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
* Outputs ATA taskfile to standard ATA host controller using MMIO.
*
* LOCKING:
* Inherited from caller.
*/
static
void
ata_tf_load_mmio
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
struct
ata_ioports
*
ioaddr
=
&
ap
->
ioaddr
;
unsigned
int
is_addr
=
tf
->
flags
&
ATA_TFLAG_ISADDR
;
if
(
tf
->
ctl
!=
ap
->
last_ctl
)
{
writeb
(
tf
->
ctl
,
(
void
__iomem
*
)
ap
->
ioaddr
.
ctl_addr
);
ap
->
last_ctl
=
tf
->
ctl
;
ata_wait_idle
(
ap
);
}
if
(
is_addr
&&
(
tf
->
flags
&
ATA_TFLAG_LBA48
))
{
writeb
(
tf
->
hob_feature
,
(
void
__iomem
*
)
ioaddr
->
feature_addr
);
writeb
(
tf
->
hob_nsect
,
(
void
__iomem
*
)
ioaddr
->
nsect_addr
);
writeb
(
tf
->
hob_lbal
,
(
void
__iomem
*
)
ioaddr
->
lbal_addr
);
writeb
(
tf
->
hob_lbam
,
(
void
__iomem
*
)
ioaddr
->
lbam_addr
);
writeb
(
tf
->
hob_lbah
,
(
void
__iomem
*
)
ioaddr
->
lbah_addr
);
VPRINTK
(
"hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X
\n
"
,
tf
->
hob_feature
,
tf
->
hob_nsect
,
tf
->
hob_lbal
,
tf
->
hob_lbam
,
tf
->
hob_lbah
);
}
if
(
is_addr
)
{
writeb
(
tf
->
feature
,
(
void
__iomem
*
)
ioaddr
->
feature_addr
);
writeb
(
tf
->
nsect
,
(
void
__iomem
*
)
ioaddr
->
nsect_addr
);
writeb
(
tf
->
lbal
,
(
void
__iomem
*
)
ioaddr
->
lbal_addr
);
writeb
(
tf
->
lbam
,
(
void
__iomem
*
)
ioaddr
->
lbam_addr
);
writeb
(
tf
->
lbah
,
(
void
__iomem
*
)
ioaddr
->
lbah_addr
);
VPRINTK
(
"feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X
\n
"
,
tf
->
feature
,
tf
->
nsect
,
tf
->
lbal
,
tf
->
lbam
,
tf
->
lbah
);
}
if
(
tf
->
flags
&
ATA_TFLAG_DEVICE
)
{
writeb
(
tf
->
device
,
(
void
__iomem
*
)
ioaddr
->
device_addr
);
VPRINTK
(
"device 0x%X
\n
"
,
tf
->
device
);
}
ata_wait_idle
(
ap
);
}
/**
* ata_tf_load - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
* Outputs ATA taskfile to standard ATA host controller using MMIO
* or PIO as indicated by the ATA_FLAG_MMIO flag.
* Writes the control, feature, nsect, lbal, lbam, and lbah registers.
* Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
* hob_lbal, hob_lbam, and hob_lbah.
*
* This function waits for idle (!BUSY and !DRQ) after writing
* registers. If the control register has a new value, this
* function also waits for idle after writing control and before
* writing the remaining registers.
*
* May be used as the tf_load() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
void
ata_tf_load
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
ata_tf_load_mmio
(
ap
,
tf
);
else
ata_tf_load_pio
(
ap
,
tf
);
}
/**
* ata_exec_command_pio - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues PIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static
void
ata_exec_command_pio
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
DPRINTK
(
"ata%u: cmd 0x%X
\n
"
,
ap
->
id
,
tf
->
command
);
outb
(
tf
->
command
,
ap
->
ioaddr
.
command_addr
);
ata_pause
(
ap
);
}
/**
* ata_exec_command_mmio - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues MMIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static
void
ata_exec_command_mmio
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
DPRINTK
(
"ata%u: cmd 0x%X
\n
"
,
ap
->
id
,
tf
->
command
);
writeb
(
tf
->
command
,
(
void
__iomem
*
)
ap
->
ioaddr
.
command_addr
);
ata_pause
(
ap
);
}
/**
* ata_exec_command - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues PIO/MMIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void
ata_exec_command
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
ata_exec_command_mmio
(
ap
,
tf
);
else
ata_exec_command_pio
(
ap
,
tf
);
}
/**
* ata_tf_read_pio - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf.
*
* LOCKING:
* Inherited from caller.
*/
static
void
ata_tf_read_pio
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
)
{
struct
ata_ioports
*
ioaddr
=
&
ap
->
ioaddr
;
tf
->
command
=
ata_check_status
(
ap
);
tf
->
feature
=
inb
(
ioaddr
->
error_addr
);
tf
->
nsect
=
inb
(
ioaddr
->
nsect_addr
);
tf
->
lbal
=
inb
(
ioaddr
->
lbal_addr
);
tf
->
lbam
=
inb
(
ioaddr
->
lbam_addr
);
tf
->
lbah
=
inb
(
ioaddr
->
lbah_addr
);
tf
->
device
=
inb
(
ioaddr
->
device_addr
);
if
(
tf
->
flags
&
ATA_TFLAG_LBA48
)
{
outb
(
tf
->
ctl
|
ATA_HOB
,
ioaddr
->
ctl_addr
);
tf
->
hob_feature
=
inb
(
ioaddr
->
error_addr
);
tf
->
hob_nsect
=
inb
(
ioaddr
->
nsect_addr
);
tf
->
hob_lbal
=
inb
(
ioaddr
->
lbal_addr
);
tf
->
hob_lbam
=
inb
(
ioaddr
->
lbam_addr
);
tf
->
hob_lbah
=
inb
(
ioaddr
->
lbah_addr
);
}
}
/**
* ata_tf_read_mmio - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf via MMIO.
*
* LOCKING:
* Inherited from caller.
*/
static
void
ata_tf_read_mmio
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
)
{
struct
ata_ioports
*
ioaddr
=
&
ap
->
ioaddr
;
tf
->
command
=
ata_check_status
(
ap
);
tf
->
feature
=
readb
((
void
__iomem
*
)
ioaddr
->
error_addr
);
tf
->
nsect
=
readb
((
void
__iomem
*
)
ioaddr
->
nsect_addr
);
tf
->
lbal
=
readb
((
void
__iomem
*
)
ioaddr
->
lbal_addr
);
tf
->
lbam
=
readb
((
void
__iomem
*
)
ioaddr
->
lbam_addr
);
tf
->
lbah
=
readb
((
void
__iomem
*
)
ioaddr
->
lbah_addr
);
tf
->
device
=
readb
((
void
__iomem
*
)
ioaddr
->
device_addr
);
if
(
tf
->
flags
&
ATA_TFLAG_LBA48
)
{
writeb
(
tf
->
ctl
|
ATA_HOB
,
(
void
__iomem
*
)
ap
->
ioaddr
.
ctl_addr
);
tf
->
hob_feature
=
readb
((
void
__iomem
*
)
ioaddr
->
error_addr
);
tf
->
hob_nsect
=
readb
((
void
__iomem
*
)
ioaddr
->
nsect_addr
);
tf
->
hob_lbal
=
readb
((
void
__iomem
*
)
ioaddr
->
lbal_addr
);
tf
->
hob_lbam
=
readb
((
void
__iomem
*
)
ioaddr
->
lbam_addr
);
tf
->
hob_lbah
=
readb
((
void
__iomem
*
)
ioaddr
->
lbah_addr
);
}
}
/**
* ata_tf_read - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf.
*
* Reads nsect, lbal, lbam, lbah, and device. If ATA_TFLAG_LBA48
* is set, also reads the hob registers.
*
* May be used as the tf_read() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
void
ata_tf_read
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
)
{
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
ata_tf_read_mmio
(
ap
,
tf
);
else
ata_tf_read_pio
(
ap
,
tf
);
}
/**
* ata_check_status_pio - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
* and return its value. This also clears pending interrupts
* from this device
*
* LOCKING:
* Inherited from caller.
*/
static
u8
ata_check_status_pio
(
struct
ata_port
*
ap
)
{
return
inb
(
ap
->
ioaddr
.
status_addr
);
}
/**
* ata_check_status_mmio - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
* via MMIO and return its value. This also clears pending interrupts
* from this device
*
* LOCKING:
* Inherited from caller.
*/
static
u8
ata_check_status_mmio
(
struct
ata_port
*
ap
)
{
return
readb
((
void
__iomem
*
)
ap
->
ioaddr
.
status_addr
);
}
/**
* ata_check_status - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
* and return its value. This also clears pending interrupts
* from this device
*
* May be used as the check_status() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
u8
ata_check_status
(
struct
ata_port
*
ap
)
{
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
return
ata_check_status_mmio
(
ap
);
return
ata_check_status_pio
(
ap
);
}
/**
* ata_altstatus - Read device alternate status reg
* @ap: port where the device is
*
* Reads ATA taskfile alternate status register for
* currently-selected device and return its value.
*
* Note: may NOT be used as the check_altstatus() entry in
* ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
u8
ata_altstatus
(
struct
ata_port
*
ap
)
{
if
(
ap
->
ops
->
check_altstatus
)
return
ap
->
ops
->
check_altstatus
(
ap
);
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
return
readb
((
void
__iomem
*
)
ap
->
ioaddr
.
altstatus_addr
);
return
inb
(
ap
->
ioaddr
.
altstatus_addr
);
}
#ifdef CONFIG_PCI
static
struct
ata_probe_ent
*
ata_probe_ent_alloc
(
struct
device
*
dev
,
const
struct
ata_port_info
*
port
)
{
struct
ata_probe_ent
*
probe_ent
;
probe_ent
=
kzalloc
(
sizeof
(
*
probe_ent
),
GFP_KERNEL
);
if
(
!
probe_ent
)
{
printk
(
KERN_ERR
DRV_NAME
"(%s): out of memory
\n
"
,
kobject_name
(
&
(
dev
->
kobj
)));
return
NULL
;
}
INIT_LIST_HEAD
(
&
probe_ent
->
node
);
probe_ent
->
dev
=
dev
;
probe_ent
->
sht
=
port
->
sht
;
probe_ent
->
host_flags
=
port
->
host_flags
;
probe_ent
->
pio_mask
=
port
->
pio_mask
;
probe_ent
->
mwdma_mask
=
port
->
mwdma_mask
;
probe_ent
->
udma_mask
=
port
->
udma_mask
;
probe_ent
->
port_ops
=
port
->
port_ops
;
return
probe_ent
;
}
/**
* ata_pci_init_native_mode - Initialize native-mode driver
* @pdev: pci device to be initialized
* @port: array[2] of pointers to port info structures.
* @ports: bitmap of ports present
*
* Utility function which allocates and initializes an
* ata_probe_ent structure for a standard dual-port
* PIO-based IDE controller. The returned ata_probe_ent
* structure can be passed to ata_device_add(). The returned
* ata_probe_ent structure should then be freed with kfree().
*
* The caller need only pass the address of the primary port, the
* secondary will be deduced automatically. If the device has non
* standard secondary port mappings this function can be called twice,
* once for each interface.
*/
struct
ata_probe_ent
*
ata_pci_init_native_mode
(
struct
pci_dev
*
pdev
,
struct
ata_port_info
**
port
,
int
ports
)
{
struct
ata_probe_ent
*
probe_ent
=
ata_probe_ent_alloc
(
pci_dev_to_dev
(
pdev
),
port
[
0
]);
int
p
=
0
;
if
(
!
probe_ent
)
return
NULL
;
probe_ent
->
irq
=
pdev
->
irq
;
probe_ent
->
irq_flags
=
SA_SHIRQ
;
probe_ent
->
private_data
=
port
[
0
]
->
private_data
;
if
(
ports
&
ATA_PORT_PRIMARY
)
{
probe_ent
->
port
[
p
].
cmd_addr
=
pci_resource_start
(
pdev
,
0
);
probe_ent
->
port
[
p
].
altstatus_addr
=
probe_ent
->
port
[
p
].
ctl_addr
=
pci_resource_start
(
pdev
,
1
)
|
ATA_PCI_CTL_OFS
;
probe_ent
->
port
[
p
].
bmdma_addr
=
pci_resource_start
(
pdev
,
4
);
ata_std_ports
(
&
probe_ent
->
port
[
p
]);
p
++
;
}
if
(
ports
&
ATA_PORT_SECONDARY
)
{
probe_ent
->
port
[
p
].
cmd_addr
=
pci_resource_start
(
pdev
,
2
);
probe_ent
->
port
[
p
].
altstatus_addr
=
probe_ent
->
port
[
p
].
ctl_addr
=
pci_resource_start
(
pdev
,
3
)
|
ATA_PCI_CTL_OFS
;
probe_ent
->
port
[
p
].
bmdma_addr
=
pci_resource_start
(
pdev
,
4
)
+
8
;
ata_std_ports
(
&
probe_ent
->
port
[
p
]);
p
++
;
}
probe_ent
->
n_ports
=
p
;
return
probe_ent
;
}
static
struct
ata_probe_ent
*
ata_pci_init_legacy_port
(
struct
pci_dev
*
pdev
,
struct
ata_port_info
*
port
,
int
port_num
)
{
struct
ata_probe_ent
*
probe_ent
;
probe_ent
=
ata_probe_ent_alloc
(
pci_dev_to_dev
(
pdev
),
port
);
if
(
!
probe_ent
)
return
NULL
;
probe_ent
->
legacy_mode
=
1
;
probe_ent
->
n_ports
=
1
;
probe_ent
->
hard_port_no
=
port_num
;
probe_ent
->
private_data
=
port
->
private_data
;
switch
(
port_num
)
{
case
0
:
probe_ent
->
irq
=
14
;
probe_ent
->
port
[
0
].
cmd_addr
=
0x1f0
;
probe_ent
->
port
[
0
].
altstatus_addr
=
probe_ent
->
port
[
0
].
ctl_addr
=
0x3f6
;
break
;
case
1
:
probe_ent
->
irq
=
15
;
probe_ent
->
port
[
0
].
cmd_addr
=
0x170
;
probe_ent
->
port
[
0
].
altstatus_addr
=
probe_ent
->
port
[
0
].
ctl_addr
=
0x376
;
break
;
}
probe_ent
->
port
[
0
].
bmdma_addr
=
pci_resource_start
(
pdev
,
4
)
+
8
*
port_num
;
ata_std_ports
(
&
probe_ent
->
port
[
0
]);
return
probe_ent
;
}
/**
* ata_pci_init_one - Initialize/register PCI IDE host controller
* @pdev: Controller to be initialized
* @port_info: Information from low-level host driver
* @n_ports: Number of ports attached to host controller
*
* This is a helper function which can be called from a driver's
* xxx_init_one() probe function if the hardware uses traditional
* IDE taskfile registers.
*
* This function calls pci_enable_device(), reserves its register
* regions, sets the dma mask, enables bus master mode, and calls
* ata_device_add()
*
* LOCKING:
* Inherited from PCI layer (may sleep).
*
* RETURNS:
* Zero on success, negative on errno-based value on error.
*/
int
ata_pci_init_one
(
struct
pci_dev
*
pdev
,
struct
ata_port_info
**
port_info
,
unsigned
int
n_ports
)
{
struct
ata_probe_ent
*
probe_ent
=
NULL
,
*
probe_ent2
=
NULL
;
struct
ata_port_info
*
port
[
2
];
u8
tmp8
,
mask
;
unsigned
int
legacy_mode
=
0
;
int
disable_dev_on_err
=
1
;
int
rc
;
DPRINTK
(
"ENTER
\n
"
);
port
[
0
]
=
port_info
[
0
];
if
(
n_ports
>
1
)
port
[
1
]
=
port_info
[
1
];
else
port
[
1
]
=
port
[
0
];
if
((
port
[
0
]
->
host_flags
&
ATA_FLAG_NO_LEGACY
)
==
0
&&
(
pdev
->
class
>>
8
)
==
PCI_CLASS_STORAGE_IDE
)
{
/* TODO: What if one channel is in native mode ... */
pci_read_config_byte
(
pdev
,
PCI_CLASS_PROG
,
&
tmp8
);
mask
=
(
1
<<
2
)
|
(
1
<<
0
);
if
((
tmp8
&
mask
)
!=
mask
)
legacy_mode
=
(
1
<<
3
);
}
/* FIXME... */
if
((
!
legacy_mode
)
&&
(
n_ports
>
2
))
{
printk
(
KERN_ERR
"ata: BUG: native mode, n_ports > 2
\n
"
);
n_ports
=
2
;
/* For now */
}
/* FIXME: Really for ATA it isn't safe because the device may be
multi-purpose and we want to leave it alone if it was already
enabled. Secondly for shared use as Arjan says we want refcounting
Checking dev->is_enabled is insufficient as this is not set at
boot for the primary video which is BIOS enabled
*/
rc
=
pci_enable_device
(
pdev
);
if
(
rc
)
return
rc
;
rc
=
pci_request_regions
(
pdev
,
DRV_NAME
);
if
(
rc
)
{
disable_dev_on_err
=
0
;
goto
err_out
;
}
/* FIXME: Should use platform specific mappers for legacy port ranges */
if
(
legacy_mode
)
{
if
(
!
request_region
(
0x1f0
,
8
,
"libata"
))
{
struct
resource
*
conflict
,
res
;
res
.
start
=
0x1f0
;
res
.
end
=
0x1f0
+
8
-
1
;
conflict
=
____request_resource
(
&
ioport_resource
,
&
res
);
if
(
!
strcmp
(
conflict
->
name
,
"libata"
))
legacy_mode
|=
(
1
<<
0
);
else
{
disable_dev_on_err
=
0
;
printk
(
KERN_WARNING
"ata: 0x1f0 IDE port busy
\n
"
);
}
}
else
legacy_mode
|=
(
1
<<
0
);
if
(
!
request_region
(
0x170
,
8
,
"libata"
))
{
struct
resource
*
conflict
,
res
;
res
.
start
=
0x170
;
res
.
end
=
0x170
+
8
-
1
;
conflict
=
____request_resource
(
&
ioport_resource
,
&
res
);
if
(
!
strcmp
(
conflict
->
name
,
"libata"
))
legacy_mode
|=
(
1
<<
1
);
else
{
disable_dev_on_err
=
0
;
printk
(
KERN_WARNING
"ata: 0x170 IDE port busy
\n
"
);
}
}
else
legacy_mode
|=
(
1
<<
1
);
}
/* we have legacy mode, but all ports are unavailable */
if
(
legacy_mode
==
(
1
<<
3
))
{
rc
=
-
EBUSY
;
goto
err_out_regions
;
}
rc
=
pci_set_dma_mask
(
pdev
,
ATA_DMA_MASK
);
if
(
rc
)
goto
err_out_regions
;
rc
=
pci_set_consistent_dma_mask
(
pdev
,
ATA_DMA_MASK
);
if
(
rc
)
goto
err_out_regions
;
if
(
legacy_mode
)
{
if
(
legacy_mode
&
(
1
<<
0
))
probe_ent
=
ata_pci_init_legacy_port
(
pdev
,
port
[
0
],
0
);
if
(
legacy_mode
&
(
1
<<
1
))
probe_ent2
=
ata_pci_init_legacy_port
(
pdev
,
port
[
1
],
1
);
}
else
{
if
(
n_ports
==
2
)
probe_ent
=
ata_pci_init_native_mode
(
pdev
,
port
,
ATA_PORT_PRIMARY
|
ATA_PORT_SECONDARY
);
else
probe_ent
=
ata_pci_init_native_mode
(
pdev
,
port
,
ATA_PORT_PRIMARY
);
}
if
(
!
probe_ent
&&
!
probe_ent2
)
{
rc
=
-
ENOMEM
;
goto
err_out_regions
;
}
pci_set_master
(
pdev
);
/* FIXME: check ata_device_add return */
if
(
legacy_mode
)
{
if
(
legacy_mode
&
(
1
<<
0
))
ata_device_add
(
probe_ent
);
if
(
legacy_mode
&
(
1
<<
1
))
ata_device_add
(
probe_ent2
);
}
else
ata_device_add
(
probe_ent
);
kfree
(
probe_ent
);
kfree
(
probe_ent2
);
return
0
;
err_out_regions:
if
(
legacy_mode
&
(
1
<<
0
))
release_region
(
0x1f0
,
8
);
if
(
legacy_mode
&
(
1
<<
1
))
release_region
(
0x170
,
8
);
pci_release_regions
(
pdev
);
err_out:
if
(
disable_dev_on_err
)
pci_disable_device
(
pdev
);
return
rc
;
}
#endif
/* CONFIG_PCI */
drivers/scsi/libata-core.c
View file @
1fdffbce
...
@@ -83,403 +83,6 @@ MODULE_DESCRIPTION("Library module for ATA devices");
...
@@ -83,403 +83,6 @@ MODULE_DESCRIPTION("Library module for ATA devices");
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_VERSION
(
DRV_VERSION
);
MODULE_VERSION
(
DRV_VERSION
);
/**
* ata_tf_load_pio - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
* Outputs ATA taskfile to standard ATA host controller.
*
* LOCKING:
* Inherited from caller.
*/
static
void
ata_tf_load_pio
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
struct
ata_ioports
*
ioaddr
=
&
ap
->
ioaddr
;
unsigned
int
is_addr
=
tf
->
flags
&
ATA_TFLAG_ISADDR
;
if
(
tf
->
ctl
!=
ap
->
last_ctl
)
{
outb
(
tf
->
ctl
,
ioaddr
->
ctl_addr
);
ap
->
last_ctl
=
tf
->
ctl
;
ata_wait_idle
(
ap
);
}
if
(
is_addr
&&
(
tf
->
flags
&
ATA_TFLAG_LBA48
))
{
outb
(
tf
->
hob_feature
,
ioaddr
->
feature_addr
);
outb
(
tf
->
hob_nsect
,
ioaddr
->
nsect_addr
);
outb
(
tf
->
hob_lbal
,
ioaddr
->
lbal_addr
);
outb
(
tf
->
hob_lbam
,
ioaddr
->
lbam_addr
);
outb
(
tf
->
hob_lbah
,
ioaddr
->
lbah_addr
);
VPRINTK
(
"hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X
\n
"
,
tf
->
hob_feature
,
tf
->
hob_nsect
,
tf
->
hob_lbal
,
tf
->
hob_lbam
,
tf
->
hob_lbah
);
}
if
(
is_addr
)
{
outb
(
tf
->
feature
,
ioaddr
->
feature_addr
);
outb
(
tf
->
nsect
,
ioaddr
->
nsect_addr
);
outb
(
tf
->
lbal
,
ioaddr
->
lbal_addr
);
outb
(
tf
->
lbam
,
ioaddr
->
lbam_addr
);
outb
(
tf
->
lbah
,
ioaddr
->
lbah_addr
);
VPRINTK
(
"feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X
\n
"
,
tf
->
feature
,
tf
->
nsect
,
tf
->
lbal
,
tf
->
lbam
,
tf
->
lbah
);
}
if
(
tf
->
flags
&
ATA_TFLAG_DEVICE
)
{
outb
(
tf
->
device
,
ioaddr
->
device_addr
);
VPRINTK
(
"device 0x%X
\n
"
,
tf
->
device
);
}
ata_wait_idle
(
ap
);
}
/**
* ata_tf_load_mmio - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
* Outputs ATA taskfile to standard ATA host controller using MMIO.
*
* LOCKING:
* Inherited from caller.
*/
static
void
ata_tf_load_mmio
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
struct
ata_ioports
*
ioaddr
=
&
ap
->
ioaddr
;
unsigned
int
is_addr
=
tf
->
flags
&
ATA_TFLAG_ISADDR
;
if
(
tf
->
ctl
!=
ap
->
last_ctl
)
{
writeb
(
tf
->
ctl
,
(
void
__iomem
*
)
ap
->
ioaddr
.
ctl_addr
);
ap
->
last_ctl
=
tf
->
ctl
;
ata_wait_idle
(
ap
);
}
if
(
is_addr
&&
(
tf
->
flags
&
ATA_TFLAG_LBA48
))
{
writeb
(
tf
->
hob_feature
,
(
void
__iomem
*
)
ioaddr
->
feature_addr
);
writeb
(
tf
->
hob_nsect
,
(
void
__iomem
*
)
ioaddr
->
nsect_addr
);
writeb
(
tf
->
hob_lbal
,
(
void
__iomem
*
)
ioaddr
->
lbal_addr
);
writeb
(
tf
->
hob_lbam
,
(
void
__iomem
*
)
ioaddr
->
lbam_addr
);
writeb
(
tf
->
hob_lbah
,
(
void
__iomem
*
)
ioaddr
->
lbah_addr
);
VPRINTK
(
"hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X
\n
"
,
tf
->
hob_feature
,
tf
->
hob_nsect
,
tf
->
hob_lbal
,
tf
->
hob_lbam
,
tf
->
hob_lbah
);
}
if
(
is_addr
)
{
writeb
(
tf
->
feature
,
(
void
__iomem
*
)
ioaddr
->
feature_addr
);
writeb
(
tf
->
nsect
,
(
void
__iomem
*
)
ioaddr
->
nsect_addr
);
writeb
(
tf
->
lbal
,
(
void
__iomem
*
)
ioaddr
->
lbal_addr
);
writeb
(
tf
->
lbam
,
(
void
__iomem
*
)
ioaddr
->
lbam_addr
);
writeb
(
tf
->
lbah
,
(
void
__iomem
*
)
ioaddr
->
lbah_addr
);
VPRINTK
(
"feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X
\n
"
,
tf
->
feature
,
tf
->
nsect
,
tf
->
lbal
,
tf
->
lbam
,
tf
->
lbah
);
}
if
(
tf
->
flags
&
ATA_TFLAG_DEVICE
)
{
writeb
(
tf
->
device
,
(
void
__iomem
*
)
ioaddr
->
device_addr
);
VPRINTK
(
"device 0x%X
\n
"
,
tf
->
device
);
}
ata_wait_idle
(
ap
);
}
/**
* ata_tf_load - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
* Outputs ATA taskfile to standard ATA host controller using MMIO
* or PIO as indicated by the ATA_FLAG_MMIO flag.
* Writes the control, feature, nsect, lbal, lbam, and lbah registers.
* Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
* hob_lbal, hob_lbam, and hob_lbah.
*
* This function waits for idle (!BUSY and !DRQ) after writing
* registers. If the control register has a new value, this
* function also waits for idle after writing control and before
* writing the remaining registers.
*
* May be used as the tf_load() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
void
ata_tf_load
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
ata_tf_load_mmio
(
ap
,
tf
);
else
ata_tf_load_pio
(
ap
,
tf
);
}
/**
* ata_exec_command_pio - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues PIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static
void
ata_exec_command_pio
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
DPRINTK
(
"ata%u: cmd 0x%X
\n
"
,
ap
->
id
,
tf
->
command
);
outb
(
tf
->
command
,
ap
->
ioaddr
.
command_addr
);
ata_pause
(
ap
);
}
/**
* ata_exec_command_mmio - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues MMIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static
void
ata_exec_command_mmio
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
DPRINTK
(
"ata%u: cmd 0x%X
\n
"
,
ap
->
id
,
tf
->
command
);
writeb
(
tf
->
command
,
(
void
__iomem
*
)
ap
->
ioaddr
.
command_addr
);
ata_pause
(
ap
);
}
/**
* ata_exec_command - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues PIO/MMIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void
ata_exec_command
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
ata_exec_command_mmio
(
ap
,
tf
);
else
ata_exec_command_pio
(
ap
,
tf
);
}
/**
* ata_tf_to_host - issue ATA taskfile to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues ATA taskfile register set to ATA host controller,
* with proper synchronization with interrupt handler and
* other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static
inline
void
ata_tf_to_host
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
ap
->
ops
->
tf_load
(
ap
,
tf
);
ap
->
ops
->
exec_command
(
ap
,
tf
);
}
/**
* ata_tf_read_pio - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf.
*
* LOCKING:
* Inherited from caller.
*/
static
void
ata_tf_read_pio
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
)
{
struct
ata_ioports
*
ioaddr
=
&
ap
->
ioaddr
;
tf
->
command
=
ata_check_status
(
ap
);
tf
->
feature
=
inb
(
ioaddr
->
error_addr
);
tf
->
nsect
=
inb
(
ioaddr
->
nsect_addr
);
tf
->
lbal
=
inb
(
ioaddr
->
lbal_addr
);
tf
->
lbam
=
inb
(
ioaddr
->
lbam_addr
);
tf
->
lbah
=
inb
(
ioaddr
->
lbah_addr
);
tf
->
device
=
inb
(
ioaddr
->
device_addr
);
if
(
tf
->
flags
&
ATA_TFLAG_LBA48
)
{
outb
(
tf
->
ctl
|
ATA_HOB
,
ioaddr
->
ctl_addr
);
tf
->
hob_feature
=
inb
(
ioaddr
->
error_addr
);
tf
->
hob_nsect
=
inb
(
ioaddr
->
nsect_addr
);
tf
->
hob_lbal
=
inb
(
ioaddr
->
lbal_addr
);
tf
->
hob_lbam
=
inb
(
ioaddr
->
lbam_addr
);
tf
->
hob_lbah
=
inb
(
ioaddr
->
lbah_addr
);
}
}
/**
* ata_tf_read_mmio - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf via MMIO.
*
* LOCKING:
* Inherited from caller.
*/
static
void
ata_tf_read_mmio
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
)
{
struct
ata_ioports
*
ioaddr
=
&
ap
->
ioaddr
;
tf
->
command
=
ata_check_status
(
ap
);
tf
->
feature
=
readb
((
void
__iomem
*
)
ioaddr
->
error_addr
);
tf
->
nsect
=
readb
((
void
__iomem
*
)
ioaddr
->
nsect_addr
);
tf
->
lbal
=
readb
((
void
__iomem
*
)
ioaddr
->
lbal_addr
);
tf
->
lbam
=
readb
((
void
__iomem
*
)
ioaddr
->
lbam_addr
);
tf
->
lbah
=
readb
((
void
__iomem
*
)
ioaddr
->
lbah_addr
);
tf
->
device
=
readb
((
void
__iomem
*
)
ioaddr
->
device_addr
);
if
(
tf
->
flags
&
ATA_TFLAG_LBA48
)
{
writeb
(
tf
->
ctl
|
ATA_HOB
,
(
void
__iomem
*
)
ap
->
ioaddr
.
ctl_addr
);
tf
->
hob_feature
=
readb
((
void
__iomem
*
)
ioaddr
->
error_addr
);
tf
->
hob_nsect
=
readb
((
void
__iomem
*
)
ioaddr
->
nsect_addr
);
tf
->
hob_lbal
=
readb
((
void
__iomem
*
)
ioaddr
->
lbal_addr
);
tf
->
hob_lbam
=
readb
((
void
__iomem
*
)
ioaddr
->
lbam_addr
);
tf
->
hob_lbah
=
readb
((
void
__iomem
*
)
ioaddr
->
lbah_addr
);
}
}
/**
* ata_tf_read - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf.
*
* Reads nsect, lbal, lbam, lbah, and device. If ATA_TFLAG_LBA48
* is set, also reads the hob registers.
*
* May be used as the tf_read() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
void
ata_tf_read
(
struct
ata_port
*
ap
,
struct
ata_taskfile
*
tf
)
{
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
ata_tf_read_mmio
(
ap
,
tf
);
else
ata_tf_read_pio
(
ap
,
tf
);
}
/**
* ata_check_status_pio - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
* and return its value. This also clears pending interrupts
* from this device
*
* LOCKING:
* Inherited from caller.
*/
static
u8
ata_check_status_pio
(
struct
ata_port
*
ap
)
{
return
inb
(
ap
->
ioaddr
.
status_addr
);
}
/**
* ata_check_status_mmio - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
* via MMIO and return its value. This also clears pending interrupts
* from this device
*
* LOCKING:
* Inherited from caller.
*/
static
u8
ata_check_status_mmio
(
struct
ata_port
*
ap
)
{
return
readb
((
void
__iomem
*
)
ap
->
ioaddr
.
status_addr
);
}
/**
* ata_check_status - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
* and return its value. This also clears pending interrupts
* from this device
*
* May be used as the check_status() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
u8
ata_check_status
(
struct
ata_port
*
ap
)
{
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
return
ata_check_status_mmio
(
ap
);
return
ata_check_status_pio
(
ap
);
}
/**
* ata_altstatus - Read device alternate status reg
* @ap: port where the device is
*
* Reads ATA taskfile alternate status register for
* currently-selected device and return its value.
*
* Note: may NOT be used as the check_altstatus() entry in
* ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
u8
ata_altstatus
(
struct
ata_port
*
ap
)
{
if
(
ap
->
ops
->
check_altstatus
)
return
ap
->
ops
->
check_altstatus
(
ap
);
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
return
readb
((
void
__iomem
*
)
ap
->
ioaddr
.
altstatus_addr
);
return
inb
(
ap
->
ioaddr
.
altstatus_addr
);
}
/**
/**
* ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
* ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
...
@@ -2008,6 +1611,26 @@ static void ata_set_mode(struct ata_port *ap)
...
@@ -2008,6 +1611,26 @@ static void ata_set_mode(struct ata_port *ap)
ata_port_disable
(
ap
);
ata_port_disable
(
ap
);
}
}
/**
* ata_tf_to_host - issue ATA taskfile to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues ATA taskfile register set to ATA host controller,
* with proper synchronization with interrupt handler and
* other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static
inline
void
ata_tf_to_host
(
struct
ata_port
*
ap
,
const
struct
ata_taskfile
*
tf
)
{
ap
->
ops
->
tf_load
(
ap
,
tf
);
ap
->
ops
->
exec_command
(
ap
,
tf
);
}
/**
/**
* ata_busy_sleep - sleep until BSY clears, or timeout
* ata_busy_sleep - sleep until BSY clears, or timeout
* @ap: port containing status register to be polled
* @ap: port containing status register to be polled
...
@@ -5106,32 +4729,6 @@ void ata_std_ports(struct ata_ioports *ioaddr)
...
@@ -5106,32 +4729,6 @@ void ata_std_ports(struct ata_ioports *ioaddr)
ioaddr
->
command_addr
=
ioaddr
->
cmd_addr
+
ATA_REG_CMD
;
ioaddr
->
command_addr
=
ioaddr
->
cmd_addr
+
ATA_REG_CMD
;
}
}
static
struct
ata_probe_ent
*
ata_probe_ent_alloc
(
struct
device
*
dev
,
const
struct
ata_port_info
*
port
)
{
struct
ata_probe_ent
*
probe_ent
;
probe_ent
=
kzalloc
(
sizeof
(
*
probe_ent
),
GFP_KERNEL
);
if
(
!
probe_ent
)
{
printk
(
KERN_ERR
DRV_NAME
"(%s): out of memory
\n
"
,
kobject_name
(
&
(
dev
->
kobj
)));
return
NULL
;
}
INIT_LIST_HEAD
(
&
probe_ent
->
node
);
probe_ent
->
dev
=
dev
;
probe_ent
->
sht
=
port
->
sht
;
probe_ent
->
host_flags
=
port
->
host_flags
;
probe_ent
->
pio_mask
=
port
->
pio_mask
;
probe_ent
->
mwdma_mask
=
port
->
mwdma_mask
;
probe_ent
->
udma_mask
=
port
->
udma_mask
;
probe_ent
->
port_ops
=
port
->
port_ops
;
return
probe_ent
;
}
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
...
@@ -5142,256 +4739,6 @@ void ata_pci_host_stop (struct ata_host_set *host_set)
...
@@ -5142,256 +4739,6 @@ void ata_pci_host_stop (struct ata_host_set *host_set)
pci_iounmap
(
pdev
,
host_set
->
mmio_base
);
pci_iounmap
(
pdev
,
host_set
->
mmio_base
);
}
}
/**
* ata_pci_init_native_mode - Initialize native-mode driver
* @pdev: pci device to be initialized
* @port: array[2] of pointers to port info structures.
* @ports: bitmap of ports present
*
* Utility function which allocates and initializes an
* ata_probe_ent structure for a standard dual-port
* PIO-based IDE controller. The returned ata_probe_ent
* structure can be passed to ata_device_add(). The returned
* ata_probe_ent structure should then be freed with kfree().
*
* The caller need only pass the address of the primary port, the
* secondary will be deduced automatically. If the device has non
* standard secondary port mappings this function can be called twice,
* once for each interface.
*/
struct
ata_probe_ent
*
ata_pci_init_native_mode
(
struct
pci_dev
*
pdev
,
struct
ata_port_info
**
port
,
int
ports
)
{
struct
ata_probe_ent
*
probe_ent
=
ata_probe_ent_alloc
(
pci_dev_to_dev
(
pdev
),
port
[
0
]);
int
p
=
0
;
if
(
!
probe_ent
)
return
NULL
;
probe_ent
->
irq
=
pdev
->
irq
;
probe_ent
->
irq_flags
=
SA_SHIRQ
;
probe_ent
->
private_data
=
port
[
0
]
->
private_data
;
if
(
ports
&
ATA_PORT_PRIMARY
)
{
probe_ent
->
port
[
p
].
cmd_addr
=
pci_resource_start
(
pdev
,
0
);
probe_ent
->
port
[
p
].
altstatus_addr
=
probe_ent
->
port
[
p
].
ctl_addr
=
pci_resource_start
(
pdev
,
1
)
|
ATA_PCI_CTL_OFS
;
probe_ent
->
port
[
p
].
bmdma_addr
=
pci_resource_start
(
pdev
,
4
);
ata_std_ports
(
&
probe_ent
->
port
[
p
]);
p
++
;
}
if
(
ports
&
ATA_PORT_SECONDARY
)
{
probe_ent
->
port
[
p
].
cmd_addr
=
pci_resource_start
(
pdev
,
2
);
probe_ent
->
port
[
p
].
altstatus_addr
=
probe_ent
->
port
[
p
].
ctl_addr
=
pci_resource_start
(
pdev
,
3
)
|
ATA_PCI_CTL_OFS
;
probe_ent
->
port
[
p
].
bmdma_addr
=
pci_resource_start
(
pdev
,
4
)
+
8
;
ata_std_ports
(
&
probe_ent
->
port
[
p
]);
p
++
;
}
probe_ent
->
n_ports
=
p
;
return
probe_ent
;
}
static
struct
ata_probe_ent
*
ata_pci_init_legacy_port
(
struct
pci_dev
*
pdev
,
struct
ata_port_info
*
port
,
int
port_num
)
{
struct
ata_probe_ent
*
probe_ent
;
probe_ent
=
ata_probe_ent_alloc
(
pci_dev_to_dev
(
pdev
),
port
);
if
(
!
probe_ent
)
return
NULL
;
probe_ent
->
legacy_mode
=
1
;
probe_ent
->
n_ports
=
1
;
probe_ent
->
hard_port_no
=
port_num
;
probe_ent
->
private_data
=
port
->
private_data
;
switch
(
port_num
)
{
case
0
:
probe_ent
->
irq
=
14
;
probe_ent
->
port
[
0
].
cmd_addr
=
0x1f0
;
probe_ent
->
port
[
0
].
altstatus_addr
=
probe_ent
->
port
[
0
].
ctl_addr
=
0x3f6
;
break
;
case
1
:
probe_ent
->
irq
=
15
;
probe_ent
->
port
[
0
].
cmd_addr
=
0x170
;
probe_ent
->
port
[
0
].
altstatus_addr
=
probe_ent
->
port
[
0
].
ctl_addr
=
0x376
;
break
;
}
probe_ent
->
port
[
0
].
bmdma_addr
=
pci_resource_start
(
pdev
,
4
)
+
8
*
port_num
;
ata_std_ports
(
&
probe_ent
->
port
[
0
]);
return
probe_ent
;
}
/**
* ata_pci_init_one - Initialize/register PCI IDE host controller
* @pdev: Controller to be initialized
* @port_info: Information from low-level host driver
* @n_ports: Number of ports attached to host controller
*
* This is a helper function which can be called from a driver's
* xxx_init_one() probe function if the hardware uses traditional
* IDE taskfile registers.
*
* This function calls pci_enable_device(), reserves its register
* regions, sets the dma mask, enables bus master mode, and calls
* ata_device_add()
*
* LOCKING:
* Inherited from PCI layer (may sleep).
*
* RETURNS:
* Zero on success, negative on errno-based value on error.
*/
int
ata_pci_init_one
(
struct
pci_dev
*
pdev
,
struct
ata_port_info
**
port_info
,
unsigned
int
n_ports
)
{
struct
ata_probe_ent
*
probe_ent
=
NULL
,
*
probe_ent2
=
NULL
;
struct
ata_port_info
*
port
[
2
];
u8
tmp8
,
mask
;
unsigned
int
legacy_mode
=
0
;
int
disable_dev_on_err
=
1
;
int
rc
;
DPRINTK
(
"ENTER
\n
"
);
port
[
0
]
=
port_info
[
0
];
if
(
n_ports
>
1
)
port
[
1
]
=
port_info
[
1
];
else
port
[
1
]
=
port
[
0
];
if
((
port
[
0
]
->
host_flags
&
ATA_FLAG_NO_LEGACY
)
==
0
&&
(
pdev
->
class
>>
8
)
==
PCI_CLASS_STORAGE_IDE
)
{
/* TODO: What if one channel is in native mode ... */
pci_read_config_byte
(
pdev
,
PCI_CLASS_PROG
,
&
tmp8
);
mask
=
(
1
<<
2
)
|
(
1
<<
0
);
if
((
tmp8
&
mask
)
!=
mask
)
legacy_mode
=
(
1
<<
3
);
}
/* FIXME... */
if
((
!
legacy_mode
)
&&
(
n_ports
>
2
))
{
printk
(
KERN_ERR
"ata: BUG: native mode, n_ports > 2
\n
"
);
n_ports
=
2
;
/* For now */
}
/* FIXME: Really for ATA it isn't safe because the device may be
multi-purpose and we want to leave it alone if it was already
enabled. Secondly for shared use as Arjan says we want refcounting
Checking dev->is_enabled is insufficient as this is not set at
boot for the primary video which is BIOS enabled
*/
rc
=
pci_enable_device
(
pdev
);
if
(
rc
)
return
rc
;
rc
=
pci_request_regions
(
pdev
,
DRV_NAME
);
if
(
rc
)
{
disable_dev_on_err
=
0
;
goto
err_out
;
}
/* FIXME: Should use platform specific mappers for legacy port ranges */
if
(
legacy_mode
)
{
if
(
!
request_region
(
0x1f0
,
8
,
"libata"
))
{
struct
resource
*
conflict
,
res
;
res
.
start
=
0x1f0
;
res
.
end
=
0x1f0
+
8
-
1
;
conflict
=
____request_resource
(
&
ioport_resource
,
&
res
);
if
(
!
strcmp
(
conflict
->
name
,
"libata"
))
legacy_mode
|=
(
1
<<
0
);
else
{
disable_dev_on_err
=
0
;
printk
(
KERN_WARNING
"ata: 0x1f0 IDE port busy
\n
"
);
}
}
else
legacy_mode
|=
(
1
<<
0
);
if
(
!
request_region
(
0x170
,
8
,
"libata"
))
{
struct
resource
*
conflict
,
res
;
res
.
start
=
0x170
;
res
.
end
=
0x170
+
8
-
1
;
conflict
=
____request_resource
(
&
ioport_resource
,
&
res
);
if
(
!
strcmp
(
conflict
->
name
,
"libata"
))
legacy_mode
|=
(
1
<<
1
);
else
{
disable_dev_on_err
=
0
;
printk
(
KERN_WARNING
"ata: 0x170 IDE port busy
\n
"
);
}
}
else
legacy_mode
|=
(
1
<<
1
);
}
/* we have legacy mode, but all ports are unavailable */
if
(
legacy_mode
==
(
1
<<
3
))
{
rc
=
-
EBUSY
;
goto
err_out_regions
;
}
rc
=
pci_set_dma_mask
(
pdev
,
ATA_DMA_MASK
);
if
(
rc
)
goto
err_out_regions
;
rc
=
pci_set_consistent_dma_mask
(
pdev
,
ATA_DMA_MASK
);
if
(
rc
)
goto
err_out_regions
;
if
(
legacy_mode
)
{
if
(
legacy_mode
&
(
1
<<
0
))
probe_ent
=
ata_pci_init_legacy_port
(
pdev
,
port
[
0
],
0
);
if
(
legacy_mode
&
(
1
<<
1
))
probe_ent2
=
ata_pci_init_legacy_port
(
pdev
,
port
[
1
],
1
);
}
else
{
if
(
n_ports
==
2
)
probe_ent
=
ata_pci_init_native_mode
(
pdev
,
port
,
ATA_PORT_PRIMARY
|
ATA_PORT_SECONDARY
);
else
probe_ent
=
ata_pci_init_native_mode
(
pdev
,
port
,
ATA_PORT_PRIMARY
);
}
if
(
!
probe_ent
&&
!
probe_ent2
)
{
rc
=
-
ENOMEM
;
goto
err_out_regions
;
}
pci_set_master
(
pdev
);
/* FIXME: check ata_device_add return */
if
(
legacy_mode
)
{
if
(
legacy_mode
&
(
1
<<
0
))
ata_device_add
(
probe_ent
);
if
(
legacy_mode
&
(
1
<<
1
))
ata_device_add
(
probe_ent2
);
}
else
ata_device_add
(
probe_ent
);
kfree
(
probe_ent
);
kfree
(
probe_ent2
);
return
0
;
err_out_regions:
if
(
legacy_mode
&
(
1
<<
0
))
release_region
(
0x1f0
,
8
);
if
(
legacy_mode
&
(
1
<<
1
))
release_region
(
0x170
,
8
);
pci_release_regions
(
pdev
);
err_out:
if
(
disable_dev_on_err
)
pci_disable_device
(
pdev
);
return
rc
;
}
/**
/**
* ata_pci_remove_one - PCI layer callback for device removal
* ata_pci_remove_one - PCI layer callback for device removal
* @pdev: PCI device that was removed
* @pdev: PCI device that was removed
...
...
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