ide: add ide_transfer_pc() helper

* Add ide-atapi.c file for generic ATAPI support together with
  CONFIG_IDE_ATAPI config option.

* Add generic ide_transfer_pc() helper to ide-atapi.c and then
  convert ide-{floppy,tape,scsi} device drivers to use it.

There should be no functional changes caused by this patch.

Cc: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent f83cbc77
...@@ -98,6 +98,9 @@ if BLK_DEV_IDE ...@@ -98,6 +98,9 @@ if BLK_DEV_IDE
comment "Please see Documentation/ide/ide.txt for help/info on IDE drives" comment "Please see Documentation/ide/ide.txt for help/info on IDE drives"
config IDE_ATAPI
bool
config BLK_DEV_IDE_SATA config BLK_DEV_IDE_SATA
bool "Support for SATA (deprecated; conflicts with libata SATA driver)" bool "Support for SATA (deprecated; conflicts with libata SATA driver)"
default n default n
...@@ -201,6 +204,7 @@ config BLK_DEV_IDECD_VERBOSE_ERRORS ...@@ -201,6 +204,7 @@ config BLK_DEV_IDECD_VERBOSE_ERRORS
config BLK_DEV_IDETAPE config BLK_DEV_IDETAPE
tristate "Include IDE/ATAPI TAPE support" tristate "Include IDE/ATAPI TAPE support"
select IDE_ATAPI
help help
If you have an IDE tape drive using the ATAPI protocol, say Y. If you have an IDE tape drive using the ATAPI protocol, say Y.
ATAPI is a newer protocol used by IDE tape and CD-ROM drives, ATAPI is a newer protocol used by IDE tape and CD-ROM drives,
...@@ -223,6 +227,7 @@ config BLK_DEV_IDETAPE ...@@ -223,6 +227,7 @@ config BLK_DEV_IDETAPE
config BLK_DEV_IDEFLOPPY config BLK_DEV_IDEFLOPPY
tristate "Include IDE/ATAPI FLOPPY support" tristate "Include IDE/ATAPI FLOPPY support"
select IDE_ATAPI
---help--- ---help---
If you have an IDE floppy drive which uses the ATAPI protocol, If you have an IDE floppy drive which uses the ATAPI protocol,
answer Y. ATAPI is a newer protocol used by IDE CD-ROM/tape/floppy answer Y. ATAPI is a newer protocol used by IDE CD-ROM/tape/floppy
...@@ -246,6 +251,7 @@ config BLK_DEV_IDEFLOPPY ...@@ -246,6 +251,7 @@ config BLK_DEV_IDEFLOPPY
config BLK_DEV_IDESCSI config BLK_DEV_IDESCSI
tristate "SCSI emulation support" tristate "SCSI emulation support"
depends on SCSI depends on SCSI
select IDE_ATAPI
---help--- ---help---
WARNING: ide-scsi is no longer needed for cd writing applications! WARNING: ide-scsi is no longer needed for cd writing applications!
The 2.6 kernel supports direct writing to ide-cd, which eliminates The 2.6 kernel supports direct writing to ide-cd, which eliminates
......
...@@ -14,6 +14,7 @@ EXTRA_CFLAGS += -Idrivers/ide ...@@ -14,6 +14,7 @@ EXTRA_CFLAGS += -Idrivers/ide
ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o
# core IDE code # core IDE code
ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o
ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o
ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o
ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o
......
/*
* ATAPI support.
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
{
ide_hwif_t *hwif = drive->hwif;
int retries = 100;
while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, retrying\n", drive->name);
udelay(100);
ireason = hwif->INB(hwif->io_ports.nsect_addr);
if (retries == 0) {
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, ignoring\n",
drive->name);
ireason |= CD;
ireason &= ~IO;
}
}
return ireason;
}
ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
ide_handler_t *handler, unsigned int timeout,
ide_expiry_t *expiry)
{
ide_hwif_t *hwif = drive->hwif;
ide_startstop_t startstop;
u8 ireason;
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
printk(KERN_ERR "%s: Strange, packet command initiated yet "
"DRQ isn't asserted\n", drive->name);
return startstop;
}
ireason = hwif->INB(hwif->io_ports.nsect_addr);
if (drive->media == ide_tape && !drive->scsi)
ireason = ide_wait_ireason(drive, ireason);
if ((ireason & CD) == 0 || (ireason & IO)) {
printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
"a packet command\n", drive->name);
return ide_do_reset(drive);
}
/* Set the interrupt routine */
ide_set_handler(drive, handler, timeout, expiry);
/* Begin DMA, if necessary */
if (pc->flags & PC_FLAG_DMA_OK) {
pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
hwif->dma_ops->dma_start(drive);
}
/* Send the actual packet */
if ((pc->flags & PC_FLAG_ZIP_DRIVE) == 0)
hwif->output_data(drive, NULL, pc->c, 12);
return ide_started;
}
EXPORT_SYMBOL_GPL(ide_transfer_pc);
...@@ -532,25 +532,11 @@ static int idefloppy_transfer_pc2(ide_drive_t *drive) ...@@ -532,25 +532,11 @@ static int idefloppy_transfer_pc2(ide_drive_t *drive)
static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive) static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif;
idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_floppy_t *floppy = drive->driver_data;
struct ide_atapi_pc *pc = floppy->pc; struct ide_atapi_pc *pc = floppy->pc;
ide_expiry_t *expiry; ide_expiry_t *expiry;
unsigned int timeout; unsigned int timeout;
ide_startstop_t startstop;
u8 ireason;
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
printk(KERN_ERR "%s: Strange, packet command initiated yet "
"DRQ isn't asserted\n", drive->name);
return startstop;
}
ireason = hwif->INB(hwif->io_ports.nsect_addr);
if ((ireason & CD) == 0 || (ireason & IO)) {
printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
"a packet command\n", drive->name);
return ide_do_reset(drive);
}
/* /*
* The following delay solves a problem with ATAPI Zip 100 drives * The following delay solves a problem with ATAPI Zip 100 drives
* where the Busy flag was apparently being deasserted before the * where the Busy flag was apparently being deasserted before the
...@@ -567,19 +553,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive) ...@@ -567,19 +553,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
expiry = NULL; expiry = NULL;
} }
ide_set_handler(drive, &idefloppy_pc_intr, timeout, expiry); return ide_transfer_pc(drive, pc, idefloppy_pc_intr, timeout, expiry);
/* Begin DMA, if necessary */
if (pc->flags & PC_FLAG_DMA_OK) {
pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
hwif->dma_ops->dma_start(drive);
}
if ((pc->flags & PC_FLAG_ZIP_DRIVE) == 0)
/* Send the actual packet */
hwif->output_data(drive, NULL, floppy->pc->c, 12);
return ide_started;
} }
static void ide_floppy_report_error(idefloppy_floppy_t *floppy, static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
......
...@@ -947,64 +947,12 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) ...@@ -947,64 +947,12 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
* again, the callback function will be called and then we will handle the next * again, the callback function will be called and then we will handle the next
* request. * request.
*/ */
static u8 ide_tape_wait_ireason(ide_drive_t *drive, u8 ireason)
{
ide_hwif_t *hwif = drive->hwif;
int retries = 100;
while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, retrying\n", drive->name);
udelay(100);
ireason = hwif->INB(hwif->io_ports.nsect_addr);
if (retries == 0) {
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, ignoring\n",
drive->name);
ireason |= CD;
ireason &= ~IO;
}
}
return ireason;
}
static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data; idetape_tape_t *tape = drive->driver_data;
struct ide_atapi_pc *pc = tape->pc;
ide_startstop_t startstop;
u8 ireason;
if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
printk(KERN_ERR "%s: Strange, packet command initiated yet "
"DRQ isn't asserted\n", drive->name);
return startstop;
}
ireason = hwif->INB(hwif->io_ports.nsect_addr);
ireason = ide_tape_wait_ireason(drive, ireason);
if ((ireason & CD) == 0 || (ireason & IO)) { return ide_transfer_pc(drive, tape->pc, idetape_pc_intr,
printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " IDETAPE_WAIT_CMD, NULL);
"a packet command\n", drive->name);
return ide_do_reset(drive);
}
/* Set the interrupt routine */
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
/* Begin DMA, if necessary */
if (pc->flags & PC_FLAG_DMA_OK) {
pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
hwif->dma_ops->dma_start(drive);
}
/* Send the actual packet */
hwif->output_data(drive, NULL, pc->c, 12);
return ide_started;
} }
static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
......
...@@ -453,36 +453,10 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) ...@@ -453,36 +453,10 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif;
idescsi_scsi_t *scsi = drive_to_idescsi(drive); idescsi_scsi_t *scsi = drive_to_idescsi(drive);
struct ide_atapi_pc *pc = scsi->pc;
ide_startstop_t startstop;
u8 ireason;
if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
printk(KERN_ERR "%s: Strange, packet command initiated yet "
"DRQ isn't asserted\n", drive->name);
return startstop;
}
ireason = hwif->INB(hwif->io_ports.nsect_addr);
if ((ireason & CD) == 0 || (ireason & IO)) {
printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
"a packet command\n", drive->name);
return ide_do_reset (drive);
}
/* Set the interrupt routine */ return ide_transfer_pc(drive, scsi->pc, idescsi_pc_intr,
ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry); get_timeout(scsi->pc), idescsi_expiry);
if (pc->flags & PC_FLAG_DMA_OK) {
pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
hwif->dma_ops->dma_start(drive);
}
/* Send the actual packet */
hwif->output_data(drive, NULL, scsi->pc->c, 12);
return ide_started;
} }
static inline int idescsi_set_direction(struct ide_atapi_pc *pc) static inline int idescsi_set_direction(struct ide_atapi_pc *pc)
......
...@@ -967,6 +967,9 @@ extern int drive_is_ready(ide_drive_t *); ...@@ -967,6 +967,9 @@ extern int drive_is_ready(ide_drive_t *);
void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8); void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8);
ide_startstop_t ide_transfer_pc(ide_drive_t *, struct ide_atapi_pc *,
ide_handler_t *, unsigned int, ide_expiry_t *);
ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *); ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);
void task_end_request(ide_drive_t *, struct request *, u8); void task_end_request(ide_drive_t *, struct request *, u8);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment